From 4bafeeba5932b55470df41a7a0c61d4c7e85042c Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Thu, 26 Aug 2021 12:25:20 -0700 Subject: [PATCH 001/585] Create README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000000..c926cb52883c --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# optimistic specs +Inspired by https://github.com/ethereum/execution-specs + +... + +TODO From de93b8d5eb889a23d3bae397b9a4211de0b20310 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Thu, 26 Aug 2021 13:33:54 -0700 Subject: [PATCH 002/585] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c926cb52883c..0b05555a210e 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,11 @@ Inspired by https://github.com/ethereum/execution-specs ... -TODO +- Rollup node +- Fraud proof + - Dispute game + - State machine + - **Generator** + - Python + - **Verifier** + - Solidity From efae589824e77d496f789ffd775b780e628ce2fc Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 27 Aug 2021 00:25:04 +0200 Subject: [PATCH 003/585] initial specs --- LICENSE | 116 ++++++++++++++++++++++++++++++++++ README.md | 40 ++++++++---- components/exec_engine.md | 2 + components/fraud_proof_gen.md | 2 + components/layer1.md | 2 + components/rollup_node.md | 2 + overview.md | 100 +++++++++++++++++++++++++++++ 7 files changed, 251 insertions(+), 13 deletions(-) create mode 100644 LICENSE create mode 100644 components/exec_engine.md create mode 100644 components/fraud_proof_gen.md create mode 100644 components/layer1.md create mode 100644 components/rollup_node.md create mode 100644 overview.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..670154e35388 --- /dev/null +++ b/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/README.md b/README.md index 0b05555a210e..bfe9c23b795c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,27 @@ -# optimistic specs -Inspired by https://github.com/ethereum/execution-specs - -... - -- Rollup node -- Fraud proof - - Dispute game - - State machine - - **Generator** - - Python - - **Verifier** - - Solidity +# Optimistic specs + +Shared open-source specification for an optimistic-rollup that strives for 1:1 Ethereum on L2 while minimizing additional code. + +The dream: *EVM compatibility, all Execution clients, all L1 tooling, L2 security (rollup), no L1-like limits* + +This project is a combined effort of the Optimism, EF research and Quilt/Consensys research teams. + +Enabling rollups on execution-layer data today, and shard-data in the future. + +[**Specs overview**](./overview.md) - experimental! + +Components (under construction): +- [Execution Engine Usage](./components/exec_engine.md) +- [Fraud Proof Generator](./components/fraud_proof_gen.md) +- [Layer 1](./components/layer1.md) +- [Rollup Node](./components/rollup_node.md) + +## Contribute + +Contribute by opening a PR. There are weekly dev calls you can join, +chat with [@protolambda](https://github.com/protolambda/) or [@karlfloersch](https://twitter.com/karl_dot_tech/). + + +## License + +CC0 1.0 Universal, see [`LICENSE`](./LICENSE) file. diff --git a/components/exec_engine.md b/components/exec_engine.md new file mode 100644 index 000000000000..5dd7bd19d481 --- /dev/null +++ b/components/exec_engine.md @@ -0,0 +1,2 @@ +# Execution Engine Usage + diff --git a/components/fraud_proof_gen.md b/components/fraud_proof_gen.md new file mode 100644 index 000000000000..520bbd137782 --- /dev/null +++ b/components/fraud_proof_gen.md @@ -0,0 +1,2 @@ +# Fraud Proof Generator + diff --git a/components/layer1.md b/components/layer1.md new file mode 100644 index 000000000000..5df95215331e --- /dev/null +++ b/components/layer1.md @@ -0,0 +1,2 @@ +# Layer 1 contracts + diff --git a/components/rollup_node.md b/components/rollup_node.md new file mode 100644 index 000000000000..e9bbdfcc80a3 --- /dev/null +++ b/components/rollup_node.md @@ -0,0 +1,2 @@ +# Rollup node + diff --git a/overview.md b/overview.md new file mode 100644 index 000000000000..e15159f6eb98 --- /dev/null +++ b/overview.md @@ -0,0 +1,100 @@ +# Optimistic Rollup Overview + +TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 tech on Layer 2. (Experimental, active R&D!) + +## Goals + +- 1:1 EVM + - No special compiler + - No unexpected gas cost + - All tooling just works (configure different chain ID, that's it) +- 100% compatibility with Eth1 nodes + - The Merge introduces an Engine API + - Fork-choice: change head based on L1 reorgs of data (and leverage undisputed state-roots for finalized checkpoint) + - Block-production: sequencing blocks with any Eth1 node + - Block-insertion: Eth1 node has specialized EVM and DB, valuable for L2, instead of reinventing the wheel + - Leverage sync: insert latest blocks from rollup node (pull from L1), but do state-sync via L2 p2p network + - Leverage tx propagation (happy case, if not forcing tx via L1): L2 user sends transaction to any sequencer, via tx pool. Anyone can bond to be a sequencer + - Fee model fit: EIP1559 on L2, on actual L2 capacity usage + +## Components + +- **L1**: + - Data availability layer (eth1 event logs or sharding): + - (Batch) Transactions + - State roots + - **Bond Contract** + - **Dispute Game Contract**: + - Bi-section game on merkle tree of execution steps between the trusted start and disputed end + - **Verification Engine Contract** + - Loads witness data: + - step witness parts can be represented as `generalized index -> bytes32`, + to simplify interaction with the partial structure (no tree management, every lookup is a simple math evaluation to get the right key) + - involved contract code entries can be large, TBD if put in storage or better of in call-data + - MPT nodes just are just a dict (of internal MPT node hash to MPT node content) + - Runs verification step + - Registers result in bond-manager (slash sequencer, reward challenger, or vice-versa if spam attempt) + - **Optimistic Gateway** + - Log authorized calls as forced L2 transactions + - Enables Deposits + - Verify L2 data statelessly with MPT proof to undisputed state-root + - Enables Withdrawals +- **Rollup node** (previously "Data Transport Layer"): + - Sync data from the L1: call payload-insertion method of Engine API + - Track L1 data tip, and track state-roots: call forkchoice method of Engine API to finalize (undisputed state root) and reorg () + - Create execution payloads: + - L2 Blocks as a whole from the L1 (i.e. include header data for batch of transactions) (TBD) + - Follow rollup rules to batch remaining individual transactions + - L1 may log special transactions, created by the Gateway, + which are paid for (i.e. signed by dummy key, and sent to L2 Gateway receiver contract, avoid new transaction type) + - Verifier (if loaded with a funded L1 account to bond the challenge): + - Block is executed with engine API, resulting state root is cached + - State roots are synced (maybe with a slight delay) + - If roots are different, run the Fraud-Proof Generator and start challenger agent job +- **Execution Engine** (previously "Eth1 client") + - Serves new [Engine API](https://hackmd.io/@n0ble/consensus_api_design_space) (Work in progress, introduced in The Merge hardfork) + - Maintains the L2 state (just like it would on L1) + - Syncs state to other L2 nodes for fast onboarding. Engine API can inform of finalized checkpoint, + to efficiently sync to trusted point, before processing block by block to the head of the L2 chain. +- **Fraud Proof Generator**: + - Highly experimental concept implementation (work in progress!): [Macula](https://github.com/protolambda/macula) + - Python: readability, not performance critical, just a temporary sub-process + - Requires bare minimum API methods from the Engine: + - get a MPT node (actually already present in p2p of eth1) + - get contract-code by contract-code hash + - Inputs: + - the API address to call for MPT node data and contract code + - the last 256 block-hashes + - the failing execution payload + - Output: fraud proof + - array of `bytes32`, root of each step, in sequence. (can be thousands) + - array of `AccessData`, encoding the set of generalized indices, code-hashes and MPT-node-hashes that were accessed this step. + as well as for the step-by-index (optimization, see generator spec). + - dict of `bytes32->(bytes32, bytes32)`: DB of all tree structure of the steps, without duplicating anything + - dict of `bytes->bytes`: map MPT node key (not leaf key, the actual internal node hash referenced in parent MPT nodes) to MPT node (RLP encoded path and child node data) + - dict of `bytes32->bytes`: map contract-code-hash to full contract code + - metadata of fraud (when/where/etc.) +- **Challenger Agent**: + - Take generated fraud proof (e.g. JSON file) + - Submit bond: control spam, challenges get back the bond, if they are actually valid. + - Run dispute game, retrieve disputed step index + - every step before this is agreed on by both parties + - the first differing step will be verified by reproducing the correct outcome on-chain + - Build witness data: + 1. get root of the disputed step + 2. get generalized indices + 3. load nodes as identified by the AccessData from shared dicts + 4. format witness data as L1 transaction input + - Sign tx, finish dispute (resubmit if not confirmed in time) + + +## Caveats + +- Undecided if the rollup will be committing to state-roots or block-roots, both have pros/cons +- MPT (Merkle Patricia Trie, storage layout of ethereum) is even more complex in this context, + possible to translate into execution steps, but takes dev time +- Receipt trie and transaction trie in the block use MPT too, but do not need witness data, they are write-only +- Some precompiles are harder to implement, possible, but ignored for now +- Generator is essentially an EVM implementation, needs a lot of testing (leverage eth1 testing suite) + + From ac0766a945ff3203ee245fddc961a0be07e4578d Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Fri, 27 Aug 2021 01:24:39 +0200 Subject: [PATCH 004/585] Update overview.md Co-authored-by: terence tsao --- overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overview.md b/overview.md index e15159f6eb98..9cadb970665a 100644 --- a/overview.md +++ b/overview.md @@ -31,7 +31,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - step witness parts can be represented as `generalized index -> bytes32`, to simplify interaction with the partial structure (no tree management, every lookup is a simple math evaluation to get the right key) - involved contract code entries can be large, TBD if put in storage or better of in call-data - - MPT nodes just are just a dict (of internal MPT node hash to MPT node content) + - MPT nodes are just a dict (of internal MPT node hash to MPT node content) - Runs verification step - Registers result in bond-manager (slash sequencer, reward challenger, or vice-versa if spam attempt) - **Optimistic Gateway** From bd44e8299a179fff9db4314345761cac1a4c2eab Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Fri, 27 Aug 2021 15:24:45 +0200 Subject: [PATCH 005/585] Update overview.md Co-authored-by: Karl Floersch --- overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overview.md b/overview.md index 9cadb970665a..1645f4b12b77 100644 --- a/overview.md +++ b/overview.md @@ -34,7 +34,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - MPT nodes are just a dict (of internal MPT node hash to MPT node content) - Runs verification step - Registers result in bond-manager (slash sequencer, reward challenger, or vice-versa if spam attempt) - - **Optimistic Gateway** + - **Optimistic Bridge** - Log authorized calls as forced L2 transactions - Enables Deposits - Verify L2 data statelessly with MPT proof to undisputed state-root From 14898062ab973d52e0acb7a8d50b84aadf196cee Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 27 Aug 2021 17:41:39 +0200 Subject: [PATCH 006/585] update overview --- overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/overview.md b/overview.md index 1645f4b12b77..5b6b1589d1a1 100644 --- a/overview.md +++ b/overview.md @@ -15,7 +15,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - Block-insertion: Eth1 node has specialized EVM and DB, valuable for L2, instead of reinventing the wheel - Leverage sync: insert latest blocks from rollup node (pull from L1), but do state-sync via L2 p2p network - Leverage tx propagation (happy case, if not forcing tx via L1): L2 user sends transaction to any sequencer, via tx pool. Anyone can bond to be a sequencer - - Fee model fit: EIP1559 on L2, on actual L2 capacity usage + - Fee model fit: EIP1559 on L2, on actual L2 block-capacity usage. (note: L2 gas-limit of blocks may adjust based on L1 data cost) ## Components @@ -41,7 +41,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - Enables Withdrawals - **Rollup node** (previously "Data Transport Layer"): - Sync data from the L1: call payload-insertion method of Engine API - - Track L1 data tip, and track state-roots: call forkchoice method of Engine API to finalize (undisputed state root) and reorg () + - Track L1 data tip, and track state-roots: call forkchoice method of Engine API to finalize (undisputed state root) and reorg (follow head derived from L1) - Create execution payloads: - L2 Blocks as a whole from the L1 (i.e. include header data for batch of transactions) (TBD) - Follow rollup rules to batch remaining individual transactions From 0e9673af0f2cafd89ac7d6c0e5d8bed7c67b74ca Mon Sep 17 00:00:00 2001 From: ben-chain Date: Fri, 27 Aug 2021 17:19:03 -0700 Subject: [PATCH 007/585] add high level diagram; update overview Co-authored-by: Karl Floersch --- README.md | 10 +++--- architecture.svg | 3 ++ components/batch_submitter.md | 1 + components/challenge_agent.md | 1 + components/fraud_proof_gen.md | 2 -- components/rollup_node.md | 2 -- components/rollup_synchronizer.md | 2 ++ components/witness_gen.md | 1 + overview.md | 58 +++++++++++++++++++------------ 9 files changed, 50 insertions(+), 30 deletions(-) create mode 100644 architecture.svg create mode 100644 components/batch_submitter.md create mode 100644 components/challenge_agent.md delete mode 100644 components/fraud_proof_gen.md delete mode 100644 components/rollup_node.md create mode 100644 components/rollup_synchronizer.md create mode 100644 components/witness_gen.md diff --git a/README.md b/README.md index bfe9c23b795c..40a34f5d5e50 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,12 @@ Enabling rollups on execution-layer data today, and shard-data in the future. [**Specs overview**](./overview.md) - experimental! Components (under construction): -- [Execution Engine Usage](./components/exec_engine.md) -- [Fraud Proof Generator](./components/fraud_proof_gen.md) -- [Layer 1](./components/layer1.md) -- [Rollup Node](./components/rollup_node.md) +- [Layer 1 Contracts](./components/layer1.md) +- [Rollup Synchronizer](./components/rollup_synchronizer.md) +- [Execution Engine](./components/exec_engine.md) +- [Batch Submitter](./components/batch_submitter.md) +- [Witness Generator](./components/witness_gen.md) +- [Challenge Agent](./components/challenge_agent.md) ## Contribute diff --git a/architecture.svg b/architecture.svg new file mode 100644 index 000000000000..8ca6ea9bcea3 --- /dev/null +++ b/architecture.svg @@ -0,0 +1,3 @@ + + +
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
synchronizes & reorgs
synchronizes & reorgs
Rollup Synchronizer
Rollup Synchronizer
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
State Oracle
State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/components/batch_submitter.md b/components/batch_submitter.md new file mode 100644 index 000000000000..4439b8e3c236 --- /dev/null +++ b/components/batch_submitter.md @@ -0,0 +1 @@ +# Batch Submitter diff --git a/components/challenge_agent.md b/components/challenge_agent.md new file mode 100644 index 000000000000..437c937f9d81 --- /dev/null +++ b/components/challenge_agent.md @@ -0,0 +1 @@ +# Challenge Agent diff --git a/components/fraud_proof_gen.md b/components/fraud_proof_gen.md deleted file mode 100644 index 520bbd137782..000000000000 --- a/components/fraud_proof_gen.md +++ /dev/null @@ -1,2 +0,0 @@ -# Fraud Proof Generator - diff --git a/components/rollup_node.md b/components/rollup_node.md deleted file mode 100644 index e9bbdfcc80a3..000000000000 --- a/components/rollup_node.md +++ /dev/null @@ -1,2 +0,0 @@ -# Rollup node - diff --git a/components/rollup_synchronizer.md b/components/rollup_synchronizer.md new file mode 100644 index 000000000000..653dabe33794 --- /dev/null +++ b/components/rollup_synchronizer.md @@ -0,0 +1,2 @@ +# Rollup Synchronizer + diff --git a/components/witness_gen.md b/components/witness_gen.md new file mode 100644 index 000000000000..64acf232a9fb --- /dev/null +++ b/components/witness_gen.md @@ -0,0 +1 @@ +# Fraud Proof Witness Generator diff --git a/overview.md b/overview.md index 5b6b1589d1a1..8cba123a08ed 100644 --- a/overview.md +++ b/overview.md @@ -19,27 +19,38 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 ## Components -- **L1**: - - Data availability layer (eth1 event logs or sharding): - - (Batch) Transactions - - State roots - - **Bond Contract** - - **Dispute Game Contract**: - - Bi-section game on merkle tree of execution steps between the trusted start and disputed end - - **Verification Engine Contract** - - Loads witness data: - - step witness parts can be represented as `generalized index -> bytes32`, - to simplify interaction with the partial structure (no tree management, every lookup is a simple math evaluation to get the right key) - - involved contract code entries can be large, TBD if put in storage or better of in call-data - - MPT nodes are just a dict (of internal MPT node hash to MPT node content) - - Runs verification step - - Registers result in bond-manager (slash sequencer, reward challenger, or vice-versa if spam attempt) - - **Optimistic Bridge** - - Log authorized calls as forced L2 transactions - - Enables Deposits - - Verify L2 data statelessly with MPT proof to undisputed state-root - - Enables Withdrawals -- **Rollup node** (previously "Data Transport Layer"): +![Architecture Diagram](architecture.svg) + +### L1 Contracts +- **Feeds**: "Data availability layer"--append-only logs (e.g. of deposits, transactions, and batched transactions) which must guarantee that: + - all values and their witnesses are indexable by off-chain parties + - witnesses are verifiable by on-chain dispute contract +- **State Oracle**: Cryptoeconomic light client of the L2. + - *Contract separation is not yet final. Highest priority interface spec: Single-step verification API* + - **Proposal Manager**: Handles conflicting state proposals to determine malicious party + - Maintains a set of ongoing optimistic proposals of the L2 state + - Ensures that state proposers are sufficiently bonded + - Distributes bond payouts + - **k-section game** + - executed to narrow in on the first disagreed-upon step between proposers + - played between two parties ("all people who agree with a proposal" may be considered a single party) + - merkle tree of execution steps between the trusted start and disputed end + - **Single Step Verifier** for executing the earliest disagreed-upon step + - Loads witness data: + - step witness parts can be represented as `generalized index -> bytes32`, + to simplify interaction with the partial structure (no tree management, every lookup is a simple math evaluation to get the right key) + - involved contract code entries can be large, TBD if put in storage or better of in call-data + - MPT nodes are just a dict (of internal MPT node hash to MPT node content) + - Runs verification step + - Registers result in bond-manager (slash sequencer, reward challenger, or vice-versa if spam attempt) +- **Cross-domain Messenger**: Message-passing abstraction contract used by applications developers (e.g. token bridge implementations) + - Sends messages into L2, reads messages out from L1 + - Log authorized calls as forced L2 transactions (deposits) + - Verify L2 data statelessly with MPT proof to undisputed state-root (withdrawals) + +### L2 Components + +- **Rollup Synchronizer** (previously "Data Transport Layer"): - Sync data from the L1: call payload-insertion method of Engine API - Track L1 data tip, and track state-roots: call forkchoice method of Engine API to finalize (undisputed state root) and reorg (follow head derived from L1) - Create execution payloads: @@ -56,7 +67,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - Maintains the L2 state (just like it would on L1) - Syncs state to other L2 nodes for fast onboarding. Engine API can inform of finalized checkpoint, to efficiently sync to trusted point, before processing block by block to the head of the L2 chain. -- **Fraud Proof Generator**: +- **Witness Generator**: - Highly experimental concept implementation (work in progress!): [Macula](https://github.com/protolambda/macula) - Python: readability, not performance critical, just a temporary sub-process - Requires bare minimum API methods from the Engine: @@ -86,6 +97,9 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 3. load nodes as identified by the AccessData from shared dicts 4. format witness data as L1 transaction input - Sign tx, finish dispute (resubmit if not confirmed in time) +- **Batch Submitter**: + - Finalizes pre-confirmed sequencer transactions onto L1 + - Writes to sequencer feed ## Caveats From 6fbd9fa312008f262cdbbb81e27d8531d4b9e5c8 Mon Sep 17 00:00:00 2001 From: ben-chain Date: Mon, 30 Aug 2021 14:39:25 -0700 Subject: [PATCH 008/585] add l1 contracts goals --- components/layer1.md | 2 -- layer-1-contracts/README.md | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) delete mode 100644 components/layer1.md create mode 100644 layer-1-contracts/README.md diff --git a/components/layer1.md b/components/layer1.md deleted file mode 100644 index 5df95215331e..000000000000 --- a/components/layer1.md +++ /dev/null @@ -1,2 +0,0 @@ -# Layer 1 contracts - diff --git a/layer-1-contracts/README.md b/layer-1-contracts/README.md new file mode 100644 index 000000000000..55a706943b85 --- /dev/null +++ b/layer-1-contracts/README.md @@ -0,0 +1,19 @@ +# Layer 1 Contracts + +## Design Goals +We want our ORU contracts to be built in compliance with the following goals: +- A **pluggable state machine** which: + - allows separation of concerns and parallelizable work + - is fully stateless, i.e. all state transitions can be expressed in the form `bytes32 _inputHash, bytes _witness => bytes32 _outputhash` and are only dependent on the immediately preceding pre-state +- A cryptoeconomic **State Oracle** which: + - Provides a cryptoeconomic mechanism to propose, assert, challenge, and finalize optimistic states of the L2 machine + - Does NOT require that the entire execution trace is provable, just the execution output + - i.e. an honest party may not necessarily ever post a hash of the full trace + - DOES require that there is a winning strategy for all, and only for all, possible state proposals + - Provides "useful" state hash proposals, i.e. block roots or state roots, which may not be equal to the `_inputHash`es above + - Is optimized to minimize the number of rounds of interaction, so as to be most resistant to hostile L1 censorship and griefing +- A set of **data feed** contracts which: + - allow parties and contracts to provide inputs which are processed by the L2 machine + - allow verifiability of those inputs for disputes + - is highly gas-efficient +- A useful **message-passing abstraction** which can be used to easily send messages (e.g. deposits and withdrawals) between L1 and L2 with a consistent interface From 96bffc42e71ba0dc596c7a3eefbd95811b969d5b Mon Sep 17 00:00:00 2001 From: ben-chain Date: Tue, 31 Aug 2021 17:20:55 -0700 Subject: [PATCH 009/585] update wording for strategy requirements --- layer-1-contracts/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layer-1-contracts/README.md b/layer-1-contracts/README.md index 55a706943b85..28bb554c4aea 100644 --- a/layer-1-contracts/README.md +++ b/layer-1-contracts/README.md @@ -9,7 +9,8 @@ We want our ORU contracts to be built in compliance with the following goals: - Provides a cryptoeconomic mechanism to propose, assert, challenge, and finalize optimistic states of the L2 machine - Does NOT require that the entire execution trace is provable, just the execution output - i.e. an honest party may not necessarily ever post a hash of the full trace - - DOES require that there is a winning strategy for all, and only for all, possible state proposals + - DOES require that there is a winning strategy for all correct state proposals + - DOES require that there is a winning strategy for challenging all incorrect state proposals - Provides "useful" state hash proposals, i.e. block roots or state roots, which may not be equal to the `_inputHash`es above - Is optimized to minimize the number of rounds of interaction, so as to be most resistant to hostile L1 censorship and griefing - A set of **data feed** contracts which: From 4d252fbd8f1a99a2371bd1044a8a4567ec9bc6f3 Mon Sep 17 00:00:00 2001 From: "lightclient@protonmail.com" Date: Sun, 5 Sep 2021 13:00:25 -0700 Subject: [PATCH 010/585] rename rollup synchronizer to rollup client --- README.md | 2 +- architecture.svg | 2 +- components/{rollup_synchronizer.md => rollup_client.md} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename components/{rollup_synchronizer.md => rollup_client.md} (100%) diff --git a/README.md b/README.md index 40a34f5d5e50..8675b7d9d535 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Enabling rollups on execution-layer data today, and shard-data in the future. Components (under construction): - [Layer 1 Contracts](./components/layer1.md) -- [Rollup Synchronizer](./components/rollup_synchronizer.md) +- [Rollup Client](./components/rollup_client.md) - [Execution Engine](./components/exec_engine.md) - [Batch Submitter](./components/batch_submitter.md) - [Witness Generator](./components/witness_gen.md) diff --git a/architecture.svg b/architecture.svg index 8ca6ea9bcea3..87f56c1662c4 100644 --- a/architecture.svg +++ b/architecture.svg @@ -1,3 +1,3 @@ -
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
synchronizes & reorgs
synchronizes & reorgs
Rollup Synchronizer
Rollup Synchronizer
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
State Oracle
State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
provides consensus
provides consensus
Rollup Client
Rollup Client
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
State Oracle
State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/components/rollup_synchronizer.md b/components/rollup_client.md similarity index 100% rename from components/rollup_synchronizer.md rename to components/rollup_client.md From a37a5b333a04009555fe351989a6b577de4d7414 Mon Sep 17 00:00:00 2001 From: "lightclient@protonmail.com" Date: Sun, 5 Sep 2021 13:23:12 -0700 Subject: [PATCH 011/585] update title --- components/rollup_client.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/rollup_client.md b/components/rollup_client.md index 653dabe33794..75f8233913bc 100644 --- a/components/rollup_client.md +++ b/components/rollup_client.md @@ -1,2 +1,2 @@ -# Rollup Synchronizer +# Rollup Client From 93fc84a19a900d272fa1ef501e6bf096b1c85dd1 Mon Sep 17 00:00:00 2001 From: "lightclient@protonmail.com" Date: Sun, 5 Sep 2021 19:15:38 -0700 Subject: [PATCH 012/585] node instead of client --- architecture.svg | 2 +- components/rollup_client.md | 2 -- components/rollup_node.md | 1 + overview.md | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) delete mode 100644 components/rollup_client.md create mode 100644 components/rollup_node.md diff --git a/architecture.svg b/architecture.svg index 87f56c1662c4..9d9b76ec62d8 100644 --- a/architecture.svg +++ b/architecture.svg @@ -1,3 +1,3 @@ -
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
provides consensus
provides consensus
Rollup Client
Rollup Client
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
State Oracle
State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
provides consensus
provides consensus
Rollup Node
Rollup Node
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
State Oracle
State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
diff --git a/components/rollup_client.md b/components/rollup_client.md deleted file mode 100644 index 75f8233913bc..000000000000 --- a/components/rollup_client.md +++ /dev/null @@ -1,2 +0,0 @@ -# Rollup Client - diff --git a/components/rollup_node.md b/components/rollup_node.md new file mode 100644 index 000000000000..6eadea4de82f --- /dev/null +++ b/components/rollup_node.md @@ -0,0 +1 @@ +# Rollup Node diff --git a/overview.md b/overview.md index 8cba123a08ed..b016ebd6b86e 100644 --- a/overview.md +++ b/overview.md @@ -50,7 +50,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 ### L2 Components -- **Rollup Synchronizer** (previously "Data Transport Layer"): +- **Rollup Node** (previously "Data Transport Layer"): - Sync data from the L1: call payload-insertion method of Engine API - Track L1 data tip, and track state-roots: call forkchoice method of Engine API to finalize (undisputed state root) and reorg (follow head derived from L1) - Create execution payloads: From 6bc903448a4c6057a01f03057b3f7b5e62d7154c Mon Sep 17 00:00:00 2001 From: "lightclient@protonmail.com" Date: Sun, 5 Sep 2021 21:31:52 -0700 Subject: [PATCH 013/585] This is a combination of 3 commits. add rough rollup node spec --- components/rollup_node.md | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/components/rollup_node.md b/components/rollup_node.md index 6eadea4de82f..d2658ca9a2b4 100644 --- a/components/rollup_node.md +++ b/components/rollup_node.md @@ -1 +1,81 @@ # Rollup Node + +The consensus module of Optimisc Ethereum. + +## Summary + +The Rollup Node is a consenus client that determines the latest state of the +rollup. It reads state from the canon chain (L1) to compute the rollup state. + +## Components + +#### Feed Oracle + +The Feed Oracle is an adapter that monitors the canon chain for new events in +the rollup contract. The rollup contract provides the *canonical* order for the +rollup chain. + +The Feed Oracle can index the batch submissions and deposits locally into the +database. The batch submissions should be converted into equivalent rollup +blocks. + +#### Consensus + +Additional checks should be imposed on the execution engine. Roughly: + +```python +def on_block(db, block): + ctx = None + for tx in block.transactions: + # verify context tx updates canon light client with correct data + if tx.is_ctx(): + assert db.is_valid_ctx(tx) + ctx = tx + + # verify deposits are valid in the canon chain and in the context of the ctx tx + if tx.is_deposit(): + assert db.is_valid_deposit(ctx, tx) + + # run the block in the executin engine, if it's valid it's the new head of the + # rollup chain + assert verify_block_in_execution_engine(block) +``` + +#### Execution Engine + +The execution engine implements the [execution specification][execution-spec]. +There already many teams who plan to transition their legacy clients into +execution engines. The rollup client will communicate to the engine via a +bidirectional JSON-RPC interface ([WIP][execution-engine-rpc]). + +One of the main goal of the rollup client is to use the exeuction engine +without modification. + +### Miner + +The miner assembles the block via the Execution Engine. It injects context +transactions that update the light client to the canon chain and it inject new +depsit transactions. It submits the transaction batch to and waits until the +transaction is mined (potentially bumping fee price if needed). + +#### Database + +The database persists the rollup chain and indexed data from the canon chain. +Pruning of canon chain data can be aggressive since indexed data is only relavent +to consensus during the force-inclusion period of deposits. + +#### Networking + +The Rollup Node should provide proxied access to the Execution Engine's +networking stack. This allows for two main things: + +* Context updates and deposits are injected into the execution engine via + transactions. This means that it's possible for the Execution Engine to + recieve signed system updates in the public mempool. This could cause block + producing rollup nodes to submit bundles with invalid contexts/deposits. +* To provide fast-confirmations, a group of rollup block producers can define a + "unconfirmed" blocks that haven't yet been submitted to mainnet (but will + likely be in the near future). + +[execution-spec]: https://github.com/ethereum/execution-specs +[execution-engine-rpc]: https://hackmd.io/@n0ble/consensus_api_design_space From 91ed44a36b45129f51fc646e4ac6f1703347c900 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Mon, 6 Sep 2021 22:39:24 +0000 Subject: [PATCH 014/585] add: roadmap doc & diagram Update roadmap.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> Update roadmap.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> Update roadmap.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> Update roadmap.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> Remove 'testbed' framing from OE --- architecture.svg => assets/architecture.svg | 0 assets/roadmap.svg | 3 ++ overview.md | 2 +- roadmap.md | 42 +++++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) rename architecture.svg => assets/architecture.svg (100%) create mode 100644 assets/roadmap.svg create mode 100644 roadmap.md diff --git a/architecture.svg b/assets/architecture.svg similarity index 100% rename from architecture.svg rename to assets/architecture.svg diff --git a/assets/roadmap.svg b/assets/roadmap.svg new file mode 100644 index 000000000000..6f718461bd03 --- /dev/null +++ b/assets/roadmap.svg @@ -0,0 +1,3 @@ + + +
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Client
(DTL replacement)
Rollup Client...
Feed Contracts (CTC replacement)
Feed Contracts (CT...
Minimal Diff Geth
Minimal Diff Geth
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Witness Generator
Witness Generator
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/overview.md b/overview.md index b016ebd6b86e..9e82cafb27f3 100644 --- a/overview.md +++ b/overview.md @@ -19,7 +19,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 ## Components -![Architecture Diagram](architecture.svg) +![Architecture Diagram](./assets/architecture.svg) ### L1 Contracts - **Feeds**: "Data availability layer"--append-only logs (e.g. of deposits, transactions, and batched transactions) which must guarantee that: diff --git a/roadmap.md b/roadmap.md new file mode 100644 index 000000000000..d527d16130d9 --- /dev/null +++ b/roadmap.md @@ -0,0 +1,42 @@ +# Optimistic Roadmap + +![Roadmap Diagram](./assets/roadmap.svg) + +## Design Goals + +The roadmap & abstractions are designed to enable the independent development of each component. The 4 major components are: +1. the optimistic mainnet deployment, +2. the fraud proof infrastructure, +3. stateless clients, +4. sharding. + +Each component will produce incremental and independent releases, each driving closer to unification and Optimistic Ethereum nirvana. + +## Summary of each component + +### Optimism Mainnet + +Optimism mainnet is the first Optimistic Ethereum network. It serves as: + +1. A live deployment of the latest stable Optimistic Ethereum spec; and +2. The source of funding of Optimistic Ethereum protocol development and other Ethereum public goods. + +This network will start out as being a rollup using eth1 as a data availability engine, and will migrate once sharding is ready. + +### Fraud Proof + +The fraud proof contracts and infrastructure are a pluggable set of EVM smart contracts, off-chain witness generators, challenge agents, and more. The near term fraud proof design is a 1:1 implementation of the Ethereum protocol written in the EVM. In the medium to long term, after statelessness is introduced to Ethereum (see the next project), the fraud proof should become entirely native so that Ethereum clients remain fully compatible with layer 2. + +### eth1.x stateless clients + +State expiry and stateless clients are key to solving the Ethereum state bloat problem **and** for native EVM fraud proofs. Once stateless clients are ready we can transition the Optimistic Ethereum fraud proof to a native component of the EVM. + +Note: Although critical to the OE roadmap, this project is tracked [external](https://github.com/ethereum/stateless-ethereum-specs/) to this repository. + +### eth2 + +The eth2 merge API and sharding will allow for native integration into execution engines as well as massive scalability ([~100k TPS](https://vitalik.ca/general/2021/01/05/rollup.html)) by greatly increasing Ethereum's data availability bandwidth. + +Note: Although critical to the OE roadmap, this project is tracked [external](https://github.com/ethereum/consensus-specs) to this repository. + +***Combining the eth2 merge API, native fraud proofs, and sharding - we'll reach Optimistic Ethereum nirvana.*** From 16fb078a938be4496134de05c41b82c6d1d66e2e Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Thu, 9 Sep 2021 15:27:46 -0400 Subject: [PATCH 015/585] Update README.md --- README.md | 73 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 8675b7d9d535..b0510111d986 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,51 @@ -# Optimistic specs - -Shared open-source specification for an optimistic-rollup that strives for 1:1 Ethereum on L2 while minimizing additional code. - -The dream: *EVM compatibility, all Execution clients, all L1 tooling, L2 security (rollup), no L1-like limits* - -This project is a combined effort of the Optimism, EF research and Quilt/Consensys research teams. - -Enabling rollups on execution-layer data today, and shard-data in the future. - -[**Specs overview**](./overview.md) - experimental! - -Components (under construction): -- [Layer 1 Contracts](./components/layer1.md) -- [Rollup Client](./components/rollup_client.md) -- [Execution Engine](./components/exec_engine.md) -- [Batch Submitter](./components/batch_submitter.md) -- [Witness Generator](./components/witness_gen.md) -- [Challenge Agent](./components/challenge_agent.md) - -## Contribute - -Contribute by opening a PR. There are weekly dev calls you can join, -chat with [@protolambda](https://github.com/protolambda/) or [@karlfloersch](https://twitter.com/karl_dot_tech/). - +# The Optimistic Ethereum Spec + +This repository holds the open-source specification for Optimistic Ethereum, an ultra-minimal optimistic rollup protocol that maintains 1:1 compatibility with Ethereum. + +## Work in Progress +Please note that this specification is currently heavily under construction. +You will find that several pages are incomplete or [under discussion](https://github.com/ethereum-optimism/optimistic-specs/discussions). + +## About the project + +Early designs for Optimistic Ethereum were spearheaded by [Optimism](https://optimism.io/), which actively maintains an implementation of the protocol at the [optimism monorepo](https://github.com/ethereum-optimism/optimism). +Recent versions of the protocol have been vastly simplified to the point that we can now envision a future in which Optimistic Ethereum can act as a standardized optimistic rollup design. +We aim to make this specification open and accessible to anyone interesting in building their own ORU system. +Toward that end, this repository is distributed under the [Creative Commons Zero v1.0 Universal](https://github.com/ethereum-optimism/optimistic-specs/blob/main/LICENSE) license which dedicates this work to the public domain. + +For those interested in contributing to this specification, please refer to [Contributing](#contributing). + +## Specification structure + +- [Overview](./overview.md) +- Components: + - [Layer 1 Contracts](./components/layer1.md) + - [Rollup Client](./components/rollup_client.md) + - [Execution Engine](./components/exec_engine.md) + - [Batch Submitter](./components/batch_submitter.md) + - [Witness Generator](./components/witness_gen.md) + - [Challenge Agent](./components/challenge_agent.md) + +## Contributing +### Basic Contributions +Contributing to the Optimistic Ethereum specification is easy. +You'll find a list of open questions and active research topics over on the [Discussions](https://github.com/ethereum-optimism/optimistic-specs/discussions) page. +Specific tasks and TODOs can be found on the [Issues](https://github.com/ethereum-optimism/optimistic-specs/issues) page. +You can edit content or add new pages by creating a [Pull Request](https://github.com/ethereum-optimism/optimistic-specs/pulls). + +### R&D Calls +We hold weekly R&D calls that are open to anyone interested in contributing to the Optimistic Ethereum spec. +Contact [@karlfloersch](https://twitter.com/karl_dot_tech/), [@protolambda](https://github.com/protolambda/), or [@kelvinfichter](https://twitter.com/kelvinfichter) if you'd like to join these calls. +Please note that these calls may be recorded and shared publicly (we will ask for consent before recording). + +### Contributors List +Refer to the [Contributors](https://github.com/ethereum-optimism/optimistic-specs/graphs/contributors) page for a complete list of active contributors. +Members of following organizations have contributed to the spec: +- Optimism +- Quilt/ConsenSys +- EF Research + +Make a [Contribution](#basic-contributions) of your own to be added to this list! ## License From 6305bea44aa349f4b2ee7463ffb969e429db87a4 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Fri, 10 Sep 2021 13:44:13 -0400 Subject: [PATCH 016/585] Update README.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0510111d986..57e87ce5a203 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repository holds the open-source specification for Optimistic Ethereum, an ## Work in Progress Please note that this specification is currently heavily under construction. -You will find that several pages are incomplete or [under discussion](https://github.com/ethereum-optimism/optimistic-specs/discussions). +You will find that several pages are incomplete or [under discussion](https://github.com/ethereum-optimism/optimistic-specs/issues). ## About the project From 706cd8b5fd199822fbb28a5bb94144054dd4b67a Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Fri, 10 Sep 2021 13:44:50 -0400 Subject: [PATCH 017/585] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57e87ce5a203..94d9efc1da72 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ For those interested in contributing to this specification, please refer to [Con ## Contributing ### Basic Contributions Contributing to the Optimistic Ethereum specification is easy. -You'll find a list of open questions and active research topics over on the [Discussions](https://github.com/ethereum-optimism/optimistic-specs/discussions) page. +You'll find a list of open questions and active research topics over on the [Fellowship of Ethereum Magicians](https://ethereum-magicians.org) forum. Specific tasks and TODOs can be found on the [Issues](https://github.com/ethereum-optimism/optimistic-specs/issues) page. You can edit content or add new pages by creating a [Pull Request](https://github.com/ethereum-optimism/optimistic-specs/pulls). From 60fa9337c5b8bdc37279eb6eb9ab011cfc1bbcf8 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Fri, 10 Sep 2021 13:45:07 -0400 Subject: [PATCH 018/585] Update README.md --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 94d9efc1da72..e32eadb70b21 100644 --- a/README.md +++ b/README.md @@ -38,15 +38,6 @@ We hold weekly R&D calls that are open to anyone interested in contributing to t Contact [@karlfloersch](https://twitter.com/karl_dot_tech/), [@protolambda](https://github.com/protolambda/), or [@kelvinfichter](https://twitter.com/kelvinfichter) if you'd like to join these calls. Please note that these calls may be recorded and shared publicly (we will ask for consent before recording). -### Contributors List -Refer to the [Contributors](https://github.com/ethereum-optimism/optimistic-specs/graphs/contributors) page for a complete list of active contributors. -Members of following organizations have contributed to the spec: -- Optimism -- Quilt/ConsenSys -- EF Research - -Make a [Contribution](#basic-contributions) of your own to be added to this list! - ## License CC0 1.0 Universal, see [`LICENSE`](./LICENSE) file. From d0279509a0e9eec40aa81cf9901a19708d21d481 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Sun, 12 Sep 2021 01:17:50 -0400 Subject: [PATCH 019/585] Update README.md --- README.md | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e32eadb70b21..b48c9f5a35ce 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,37 @@ This repository holds the open-source specification for Optimistic Ethereum, an ultra-minimal optimistic rollup protocol that maintains 1:1 compatibility with Ethereum. ## Work in Progress + Please note that this specification is currently heavily under construction. You will find that several pages are incomplete or [under discussion](https://github.com/ethereum-optimism/optimistic-specs/issues). -## About the project +## Design Philosophy + +We believe that **the best optimistic rollup design needs to be minimal, open, and accessible.** + +### Minimalism + +Ethereum-focused optimistic rollups should be minimal to best take advantage of the battle-tested infrastructure (like Geth) that already runs Ethereum. +An ideal optimistic rollup design should be representable as a *diff* against Ethereum client software. +We imagine a world in which any Ethereum client can, with only minor modifications, participate in an Optimistic Ethereum network. + +### Openness + +We think it's time to coordinate the Ethereum community around a well-specified optimistic rollup design. +We acknowledge that this is only possible if the design process remains open to the feedback of the many teams already working on optimistic rollup architectures. +We aim to make this both this specification and the process by which this specification is built available to anyone interesting in building their own ORU system. + +Anyone interested in contributing to this specification should refer to the [Contributing](#contributing) section. +You will find multiple options for contributing to this project. + +This repository is distributed under the [Creative Commons Zero v1.0 Universal](https://github.com/ethereum-optimism/optimistic-specs/blob/main/LICENSE) license which dedicates this work to the public domain. +An MIT licensed implementation of this protocol can be found [here](https://github.com/ethereum-optimism/optimism). -Early designs for Optimistic Ethereum were spearheaded by [Optimism](https://optimism.io/), which actively maintains an implementation of the protocol at the [optimism monorepo](https://github.com/ethereum-optimism/optimism). -Recent versions of the protocol have been vastly simplified to the point that we can now envision a future in which Optimistic Ethereum can act as a standardized optimistic rollup design. -We aim to make this specification open and accessible to anyone interesting in building their own ORU system. -Toward that end, this repository is distributed under the [Creative Commons Zero v1.0 Universal](https://github.com/ethereum-optimism/optimistic-specs/blob/main/LICENSE) license which dedicates this work to the public domain. +### Accessibility -For those interested in contributing to this specification, please refer to [Contributing](#contributing). +Users, developers, and protocol designers need to be confident that a given optimistic rollup is robust and secure. +We believe that this confidence can only truly come from an accessible specification and codebase that developers can reasonably be expected to understand. +Without this accessibility we'll always fundamentally have to trust the knowledge and competence of a very small group of core developers, a fact antithetical to the ideal decentralized nature of these systems. ## Specification structure From c0ebd8065f214d7057b892489cc0480aeaee89a8 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Thu, 30 Sep 2021 02:02:13 +0000 Subject: [PATCH 020/585] Update spec to use block oracle term --- assets/architecture.svg | 3 ++- layer-1-contracts/README.md | 6 +++--- overview.md | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/assets/architecture.svg b/assets/architecture.svg index 9d9b76ec62d8..d353b0ea73af 100644 --- a/assets/architecture.svg +++ b/assets/architecture.svg @@ -1,3 +1,4 @@ + -
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
provides consensus
provides consensus
Rollup Node
Rollup Node
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
State Oracle
State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
+
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
provides consensus
provides consensus
Rollup Client
Rollup Client
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
L2 Block Oracle
L2 Block Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/layer-1-contracts/README.md b/layer-1-contracts/README.md index 28bb554c4aea..1f09ece995d4 100644 --- a/layer-1-contracts/README.md +++ b/layer-1-contracts/README.md @@ -1,17 +1,17 @@ -# Layer 1 Contracts +layer-1-contracts/README.md# Layer 1 Contracts ## Design Goals We want our ORU contracts to be built in compliance with the following goals: - A **pluggable state machine** which: - allows separation of concerns and parallelizable work - is fully stateless, i.e. all state transitions can be expressed in the form `bytes32 _inputHash, bytes _witness => bytes32 _outputhash` and are only dependent on the immediately preceding pre-state -- A cryptoeconomic **State Oracle** which: +- A cryptoeconomic **L2 Block Oracle** which: - Provides a cryptoeconomic mechanism to propose, assert, challenge, and finalize optimistic states of the L2 machine - Does NOT require that the entire execution trace is provable, just the execution output - i.e. an honest party may not necessarily ever post a hash of the full trace - DOES require that there is a winning strategy for all correct state proposals - DOES require that there is a winning strategy for challenging all incorrect state proposals - - Provides "useful" state hash proposals, i.e. block roots or state roots, which may not be equal to the `_inputHash`es above + - Provides access to L2 block hashes, which may not be equal to the `_inputHash`es above - Is optimized to minimize the number of rounds of interaction, so as to be most resistant to hostile L1 censorship and griefing - A set of **data feed** contracts which: - allow parties and contracts to provide inputs which are processed by the L2 machine diff --git a/overview.md b/overview.md index 9e82cafb27f3..3ef0766864ff 100644 --- a/overview.md +++ b/overview.md @@ -25,8 +25,8 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - **Feeds**: "Data availability layer"--append-only logs (e.g. of deposits, transactions, and batched transactions) which must guarantee that: - all values and their witnesses are indexable by off-chain parties - witnesses are verifiable by on-chain dispute contract -- **State Oracle**: Cryptoeconomic light client of the L2. - - *Contract separation is not yet final. Highest priority interface spec: Single-step verification API* +- **L2 Block Oracle**: Cryptoeconomic light client of the L2. + - *Contract separation is not yet final. Highest priority interface spec: Single-step verification API* - **Proposal Manager**: Handles conflicting state proposals to determine malicious party - Maintains a set of ongoing optimistic proposals of the L2 state - Ensures that state proposers are sufficiently bonded @@ -37,7 +37,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - merkle tree of execution steps between the trusted start and disputed end - **Single Step Verifier** for executing the earliest disagreed-upon step - Loads witness data: - - step witness parts can be represented as `generalized index -> bytes32`, + - step witness parts can be represented as `generalized index -> bytes32`, to simplify interaction with the partial structure (no tree management, every lookup is a simple math evaluation to get the right key) - involved contract code entries can be large, TBD if put in storage or better of in call-data - MPT nodes are just a dict (of internal MPT node hash to MPT node content) From a1851015695d7d035640f18ac8194d01a6760842 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Tue, 21 Sep 2021 00:41:08 +0000 Subject: [PATCH 021/585] fix: typos and make newline usage consistent --- components/rollup_node.md | 42 ++++++++++----------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/components/rollup_node.md b/components/rollup_node.md index d2658ca9a2b4..580a2c15faa5 100644 --- a/components/rollup_node.md +++ b/components/rollup_node.md @@ -1,23 +1,18 @@ # Rollup Node -The consensus module of Optimisc Ethereum. +The consensus module of Optimistic Ethereum. ## Summary -The Rollup Node is a consenus client that determines the latest state of the -rollup. It reads state from the canon chain (L1) to compute the rollup state. +The Rollup Node is a consensus client that determines the latest state of the rollup. It reads state from the canon chain (L1) to compute the rollup state. ## Components #### Feed Oracle -The Feed Oracle is an adapter that monitors the canon chain for new events in -the rollup contract. The rollup contract provides the *canonical* order for the -rollup chain. +The Feed Oracle is an adapter that monitors the canon chain for new events in the rollup contract. The rollup contract provides the *canonical* order for the rollup chain. -The Feed Oracle can index the batch submissions and deposits locally into the -database. The batch submissions should be converted into equivalent rollup -blocks. +The Feed Oracle can index the batch submissions and deposits locally into the database. The batch submissions should be converted into equivalent rollup blocks. #### Consensus @@ -43,39 +38,24 @@ def on_block(db, block): #### Execution Engine -The execution engine implements the [execution specification][execution-spec]. -There already many teams who plan to transition their legacy clients into -execution engines. The rollup client will communicate to the engine via a -bidirectional JSON-RPC interface ([WIP][execution-engine-rpc]). +The execution engine implements the [execution specification][execution-spec]. There already many teams who plan to transition their legacy clients into execution engines. The rollup client will communicate to the engine via a bidirectional JSON-RPC interface ([WIP][execution-engine-rpc]). -One of the main goal of the rollup client is to use the exeuction engine -without modification. +One of the main goal of the rollup client is to use the execution engine without modification. ### Miner -The miner assembles the block via the Execution Engine. It injects context -transactions that update the light client to the canon chain and it inject new -depsit transactions. It submits the transaction batch to and waits until the -transaction is mined (potentially bumping fee price if needed). +The miner assembles the block via the Execution Engine. It injects context transactions that update the light client to the canon chain and it inject new deposit transactions. It submits the transaction batch to and waits until the transaction is mined (potentially bumping fee price if needed). #### Database -The database persists the rollup chain and indexed data from the canon chain. -Pruning of canon chain data can be aggressive since indexed data is only relavent -to consensus during the force-inclusion period of deposits. +The database persists the rollup chain and indexed data from the canon chain. Pruning of canon chain data can be aggressive since indexed data is only relevant to consensus during the force-inclusion period of deposits. #### Networking -The Rollup Node should provide proxied access to the Execution Engine's -networking stack. This allows for two main things: +The Rollup Node should provide proxied access to the Execution Engine's networking stack. This allows for two main things: -* Context updates and deposits are injected into the execution engine via - transactions. This means that it's possible for the Execution Engine to - recieve signed system updates in the public mempool. This could cause block - producing rollup nodes to submit bundles with invalid contexts/deposits. -* To provide fast-confirmations, a group of rollup block producers can define a - "unconfirmed" blocks that haven't yet been submitted to mainnet (but will - likely be in the near future). +* Context updates and deposits are injected into the execution engine via transactions. This means that it's possible for the Execution Engine to receive signed system updates in the public mempool. This could cause block producing rollup nodes to submit bundles with invalid contexts/deposits. +* To provide fast-confirmations, a group of rollup block producers can define a "unconfirmed" blocks that haven't yet been submitted to mainnet (but will likely be in the near future). [execution-spec]: https://github.com/ethereum/execution-specs [execution-engine-rpc]: https://hackmd.io/@n0ble/consensus_api_design_space From 82172babee1acdcfe63493ace66f87dfdfa026ef Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Fri, 1 Oct 2021 09:54:57 -0700 Subject: [PATCH 022/585] Add link to dispute game repo --- overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overview.md b/overview.md index 9e82cafb27f3..28cb6e0dfd3f 100644 --- a/overview.md +++ b/overview.md @@ -88,7 +88,7 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - **Challenger Agent**: - Take generated fraud proof (e.g. JSON file) - Submit bond: control spam, challenges get back the bond, if they are actually valid. - - Run dispute game, retrieve disputed step index + - Run dispute game, retrieve disputed step index (WIP implementation [here](https://github.com/statechannels/dispute-game)) - every step before this is agreed on by both parties - the first differing step will be verified by reproducing the correct outcome on-chain - Build witness data: From b82f677bbe1d537d8a03e416468ed2ce0897448c Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Sat, 16 Oct 2021 19:06:10 +0000 Subject: [PATCH 023/585] add: diagrams Add drawio file for now Fix diagram links & address feedback --- assets/network-participants-overview.svg | 4 ++++ assets/sequencer-handling-deposits-and-transactions.svg | 4 ++++ assets/user-withdrawing-to-l1.svg | 4 ++++ assets/verifier-executing-fraud-proof.svg | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 assets/network-participants-overview.svg create mode 100644 assets/sequencer-handling-deposits-and-transactions.svg create mode 100644 assets/user-withdrawing-to-l1.svg create mode 100644 assets/verifier-executing-fraud-proof.svg diff --git a/assets/network-participants-overview.svg b/assets/network-participants-overview.svg new file mode 100644 index 000000000000..602043d58f3c --- /dev/null +++ b/assets/network-participants-overview.svg @@ -0,0 +1,4 @@ + + + +
Ethereum L1 Chain
Ethereum L1 Chain

Network Participants Overview

Network Participants Overview
Query data
(eg. block explorers)
Query data...
Submit transactions
Submit transactions
Submit deposits
Submit deposits
Users
Users
Submit batches and assertions
Submit batches and assertions
P2P Realtime Updates
P2P Realtime Updates
Verifiers
Verifi...
Verify block hash assertions &
submit fraud proofs
Verify block hash assertions &...
Sequencer
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/sequencer-handling-deposits-and-transactions.svg b/assets/sequencer-handling-deposits-and-transactions.svg new file mode 100644 index 000000000000..b9e941bcb94a --- /dev/null +++ b/assets/sequencer-handling-deposits-and-transactions.svg @@ -0,0 +1,4 @@ + + + +
3. Insert deposit block
3. Insert deposit block
Rollup Client
Rollup Client
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to sequencer feed
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the sequencer feed.
Queries for all...
Sequencer Feed
Sequencer Feed

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
Block Hash
Assertion Submitter
Block Hash...
Queries for the next
assertable block hash
& submits it to the
assertion manager.
Queries for the next...
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/user-withdrawing-to-l1.svg b/assets/user-withdrawing-to-l1.svg new file mode 100644 index 000000000000..19cce204a54c --- /dev/null +++ b/assets/user-withdrawing-to-l1.svg @@ -0,0 +1,4 @@ + + + +
Ethereum L1 Chain
Ethereum L1 Chain
Sequencer Feed
Sequencer Feed

User Withdrawing to Layer 1

User Withdrawing to Layer 1
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
3. Assert block hash
containing withdrawal
commitment
3. Assert block hash...
2. Post batch
with withdrawal
transaction data
2. Post batch...
1. Send
initiate
withdrawal

transaction
1. Send...
5. Send
execute
withdrawal

transaction
5. Send...
4. Wait for block
hash to finalize
4. Wait for block...
User
User
ERC20
ERC20
6. Verify
withdrawal
in finalized
block hash
6. Verify...
7.
Transfer
tokens
7....
Bridge
Bridge
Sequencer
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/verifier-executing-fraud-proof.svg b/assets/verifier-executing-fraud-proof.svg new file mode 100644 index 000000000000..47f3a47b542a --- /dev/null +++ b/assets/verifier-executing-fraud-proof.svg @@ -0,0 +1,4 @@ + + + +
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Client
Rollup Client
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 Block Hash Oracle Contract
L2 Block Hash Oracle Contract
Assertion Manager
Assertion...
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Viewer does not support full SVG 1.1
\ No newline at end of file From 29a468cbc57215839e19800f4a7e1c1be4ecaab2 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Mon, 20 Sep 2021 21:21:07 +0000 Subject: [PATCH 024/585] add: roadmap goals --- roadmap.md | 54 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/roadmap.md b/roadmap.md index d527d16130d9..ea2f14e967ed 100644 --- a/roadmap.md +++ b/roadmap.md @@ -1,21 +1,52 @@ # Optimistic Roadmap +This document contains the Optimistic Ethereum protocol roadmap. That includes the project goals and a high level roadmap diagram. + +## Goals +The fundamental goal of the Optimistic Ethereum protocol is to scale Ethereum while preserving the security properties of L1. To achieve this we must create: + +### Ultra-Minimal Rollup Node +A rollup client, expressible as a minimal diff against Ethereum. Minimalism is key because it enables compatibility with existing Ethereum tooling as well as security. + +#### Completion Criteria +1. 1:1 equivalence with the Ethereum yellow paper. + - This may require changes to Ethereum in order to natively support rollups (eg. the merge API). +2. Multi-client support. +3. Minimal batch submission cost including the integration of eth2 sharding when ready. +4. Support for sequencer consensus. + +### Pluggable State Oracle +A set of pluggable contracts for proving L2 rollup state to L1. Pluggability is key because it will allow parallel development across the OE rollup stack. + +#### Completion Criteria +1. Proposal manager capable of being managed by any dispute game. + - Should eventually support validity proofs. +2. Dispute game capable of adjudicating any fraud proof VM. + +### Future Proof Fraud Proof VM +Create a VM built for executing fraud proofs against an EVM equivalent rollup. Future proof-ness is key because the fraud proof must evolve as the Ethereum protocol evolves. + +#### Completion Criteria +1. Must correctly implement the Optimistic Ethereum protocol defined in the Ultra-Minimal Rollup Node specs. +2. Easy to update as Ethereum hard forks are released. +3. Divergences between client implementations and the fraud proof are gracefully handled. + +## Roadmap Diagram +We will be working towards these goals iteratively. The following diagram is an approximation of what the ordering of work will look like and what streams of work can be parallelized: ![Roadmap Diagram](./assets/roadmap.svg) -## Design Goals +The roadmap & abstractions are designed to enable independent development of each component. The 4 major components are: -The roadmap & abstractions are designed to enable the independent development of each component. The 4 major components are: 1. the optimistic mainnet deployment, 2. the fraud proof infrastructure, -3. stateless clients, -4. sharding. +3. stateless clients, +4. sharding. Each component will produce incremental and independent releases, each driving closer to unification and Optimistic Ethereum nirvana. -## Summary of each component - -### Optimism Mainnet +### Summary of each component +#### Optimism Mainnet Optimism mainnet is the first Optimistic Ethereum network. It serves as: 1. A live deployment of the latest stable Optimistic Ethereum spec; and @@ -23,18 +54,15 @@ Optimism mainnet is the first Optimistic Ethereum network. It serves as: This network will start out as being a rollup using eth1 as a data availability engine, and will migrate once sharding is ready. -### Fraud Proof - +#### Fraud Proof The fraud proof contracts and infrastructure are a pluggable set of EVM smart contracts, off-chain witness generators, challenge agents, and more. The near term fraud proof design is a 1:1 implementation of the Ethereum protocol written in the EVM. In the medium to long term, after statelessness is introduced to Ethereum (see the next project), the fraud proof should become entirely native so that Ethereum clients remain fully compatible with layer 2. -### eth1.x stateless clients - +#### eth1.x stateless clients State expiry and stateless clients are key to solving the Ethereum state bloat problem **and** for native EVM fraud proofs. Once stateless clients are ready we can transition the Optimistic Ethereum fraud proof to a native component of the EVM. Note: Although critical to the OE roadmap, this project is tracked [external](https://github.com/ethereum/stateless-ethereum-specs/) to this repository. -### eth2 - +#### eth2 The eth2 merge API and sharding will allow for native integration into execution engines as well as massive scalability ([~100k TPS](https://vitalik.ca/general/2021/01/05/rollup.html)) by greatly increasing Ethereum's data availability bandwidth. Note: Although critical to the OE roadmap, this project is tracked [external](https://github.com/ethereum/consensus-specs) to this repository. From 527dbccfb9b43bf431bb9609d8e8c48d4d5e4ede Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Tue, 26 Oct 2021 15:58:46 -0700 Subject: [PATCH 025/585] Move the ToC to the top of readme (#24) --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b48c9f5a35ce..8d5ec678b108 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,17 @@ This repository holds the open-source specification for Optimistic Ethereum, an Please note that this specification is currently heavily under construction. You will find that several pages are incomplete or [under discussion](https://github.com/ethereum-optimism/optimistic-specs/issues). +## Specification structure + +- [Overview](./overview.md) +- Components: + - [Layer 1 Contracts](./components/layer1.md) + - [Rollup Client](./components/rollup_client.md) + - [Execution Engine](./components/exec_engine.md) + - [Batch Submitter](./components/batch_submitter.md) + - [Witness Generator](./components/witness_gen.md) + - [Challenge Agent](./components/challenge_agent.md) + ## Design Philosophy We believe that **the best optimistic rollup design needs to be minimal, open, and accessible.** @@ -35,17 +46,6 @@ Users, developers, and protocol designers need to be confident that a given opti We believe that this confidence can only truly come from an accessible specification and codebase that developers can reasonably be expected to understand. Without this accessibility we'll always fundamentally have to trust the knowledge and competence of a very small group of core developers, a fact antithetical to the ideal decentralized nature of these systems. -## Specification structure - -- [Overview](./overview.md) -- Components: - - [Layer 1 Contracts](./components/layer1.md) - - [Rollup Client](./components/rollup_client.md) - - [Execution Engine](./components/exec_engine.md) - - [Batch Submitter](./components/batch_submitter.md) - - [Witness Generator](./components/witness_gen.md) - - [Challenge Agent](./components/challenge_agent.md) - ## Contributing ### Basic Contributions Contributing to the Optimistic Ethereum specification is easy. From 9bf4fa0a29aff6c9014645eca63c863e2d17ec9f Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Tue, 26 Oct 2021 19:12:44 -0700 Subject: [PATCH 026/585] update: roadmap progress & readme (#26) - update the progress bars - update naming of components to be consistent - add roadmap to readme --- README.md | 1 + assets/roadmap.svg | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d5ec678b108..1e66168a6eb2 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ You will find that several pages are incomplete or [under discussion](https://gi ## Specification structure - [Overview](./overview.md) +- [Roadmap](./roadmap.md) - Components: - [Layer 1 Contracts](./components/layer1.md) - [Rollup Client](./components/rollup_client.md) diff --git a/assets/roadmap.svg b/assets/roadmap.svg index 6f718461bd03..41534dfc424c 100644 --- a/assets/roadmap.svg +++ b/assets/roadmap.svg @@ -1,3 +1,4 @@ + -
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Client
(DTL replacement)
Rollup Client...
Feed Contracts (CTC replacement)
Feed Contracts (CT...
Minimal Diff Geth
Minimal Diff Geth
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Witness Generator
Witness Generator
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
Rollup Node
Feed Contracts
Feed Contracts
Execution Engine
Execution Engine
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
(Formerly DTL)
Rollup Node...
Feed Contracts
(Formerly CTC)
Feed Contracts...
Execution Engine
(Deposits+mergeAPI)
Execution Engine...
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Assertion Manager
Assertion Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Equivalence Testing...
Fraud Proof <> Client Equivale...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Viewer does not support full SVG 1.1
\ No newline at end of file From 9ed30e6e100763b831773e00d3042ddda4c80ebf Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Thu, 28 Oct 2021 10:10:00 -0700 Subject: [PATCH 027/585] Add high level intro section (#25) Update introduction.md Co-authored-by: Maurelian Update introduction.md Co-authored-by: Maurelian Update introduction.md Co-authored-by: Maurelian Update introduction.md Co-authored-by: Maurelian Update introduction.md Co-authored-by: Maurelian Update introduction.md Co-authored-by: Maurelian Address the rest of the feedback --- README.md | 1 + assets/network-participants-overview.svg | 2 +- ...cer-handling-deposits-and-transactions.svg | 2 +- assets/user-withdrawing-to-l1.svg | 2 +- assets/verifier-executing-fraud-proof.svg | 2 +- introduction.md | 130 ++++++++++++++++++ 6 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 introduction.md diff --git a/README.md b/README.md index 1e66168a6eb2..1967a5ded2d9 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ You will find that several pages are incomplete or [under discussion](https://gi ## Specification structure +- [Introduction](./introduction.md) - [Overview](./overview.md) - [Roadmap](./roadmap.md) - Components: diff --git a/assets/network-participants-overview.svg b/assets/network-participants-overview.svg index 602043d58f3c..d70a983f7b9d 100644 --- a/assets/network-participants-overview.svg +++ b/assets/network-participants-overview.svg @@ -1,4 +1,4 @@ -
Ethereum L1 Chain
Ethereum L1 Chain

Network Participants Overview

Network Participants Overview
Query data
(eg. block explorers)
Query data...
Submit transactions
Submit transactions
Submit deposits
Submit deposits
Users
Users
Submit batches and assertions
Submit batches and assertions
P2P Realtime Updates
P2P Realtime Updates
Verifiers
Verifi...
Verify block hash assertions &
submit fraud proofs
Verify block hash assertions &...
Sequencer
Viewer does not support full SVG 1.1
\ No newline at end of file +
Ethereum L1 Chain
Ethereum L1 Chain

Network Participants Overview

Network Participants Overview
Query data
(eg. block explorers)
Query data...
Submit transactions
Submit transactions
Submit deposits
Submit deposits
Users
Users
Submit batches and assertions
Submit batches and assertions
P2P Realtime Updates
P2P Realtime Updates
Verifiers
Verifi...
Verify block hash assertions &
submit fraud proofs
Verify block hash assertions &...
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/sequencer-handling-deposits-and-transactions.svg b/assets/sequencer-handling-deposits-and-transactions.svg index b9e941bcb94a..924cffb5be43 100644 --- a/assets/sequencer-handling-deposits-and-transactions.svg +++ b/assets/sequencer-handling-deposits-and-transactions.svg @@ -1,4 +1,4 @@ -
3. Insert deposit block
3. Insert deposit block
Rollup Client
Rollup Client
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to sequencer feed
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the sequencer feed.
Queries for all...
Sequencer Feed
Sequencer Feed

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
Block Hash
Assertion Submitter
Block Hash...
Queries for the next
assertable block hash
& submits it to the
assertion manager.
Queries for the next...
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Viewer does not support full SVG 1.1
\ No newline at end of file +
3. Insert deposit block
3. Insert deposit block
Rollup Node
Rollup Node
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to sequencer feed
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the sequencer feed.
Queries for all...
Sequencer Feed
Sequencer Feed

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
Block Hash
Assertion Submitter
Block Hash...
Queries for the next
assertable block hash
& submits it to the
assertion manager.
Queries for the next...
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/user-withdrawing-to-l1.svg b/assets/user-withdrawing-to-l1.svg index 19cce204a54c..ebc9a4540890 100644 --- a/assets/user-withdrawing-to-l1.svg +++ b/assets/user-withdrawing-to-l1.svg @@ -1,4 +1,4 @@ -
Ethereum L1 Chain
Ethereum L1 Chain
Sequencer Feed
Sequencer Feed

User Withdrawing to Layer 1

User Withdrawing to Layer 1
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
3. Assert block hash
containing withdrawal
commitment
3. Assert block hash...
2. Post batch
with withdrawal
transaction data
2. Post batch...
1. Send
initiate
withdrawal

transaction
1. Send...
5. Send
execute
withdrawal

transaction
5. Send...
4. Wait for block
hash to finalize
4. Wait for block...
User
User
ERC20
ERC20
6. Verify
withdrawal
in finalized
block hash
6. Verify...
7.
Transfer
tokens
7....
Bridge
Bridge
Sequencer
Viewer does not support full SVG 1.1
\ No newline at end of file +
Ethereum L1 Chain
Ethereum L1 Chain
Sequencer Feed
Sequencer Feed

User Withdrawing to Layer 1

User Withdrawing to Layer 1
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
3. Assert block hash
containing withdrawal
commitment
3. Assert block hash...
2. Post batch
with withdrawal
transaction data
2. Post batch...
1. Send
initiate
withdrawal

transaction
1. Send...
5. Send
execute
withdrawal

transaction
5. Send...
4. Wait for block
hash to finalize
4. Wait for block...
User
User
ERC20
ERC20
6. Verify
withdrawal
in finalized
block hash
6. Verify...
7.
Transfer
tokens
7....
Bridge
Bridge
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/verifier-executing-fraud-proof.svg b/assets/verifier-executing-fraud-proof.svg index 47f3a47b542a..e3dd824cfa66 100644 --- a/assets/verifier-executing-fraud-proof.svg +++ b/assets/verifier-executing-fraud-proof.svg @@ -1,4 +1,4 @@ -
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Client
Rollup Client
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 Block Hash Oracle Contract
L2 Block Hash Oracle Contract
Assertion Manager
Assertion...
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Viewer does not support full SVG 1.1
\ No newline at end of file +
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Node
Rollup Node
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 Block Hash Oracle Contract
L2 Block Hash Oracle Contract
Assertion Manager
Assertion...
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/introduction.md b/introduction.md new file mode 100644 index 000000000000..f8e76b2b8d10 --- /dev/null +++ b/introduction.md @@ -0,0 +1,130 @@ +# Optimistic Ethereum Introduction + +Optimistic Ethereum is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_ while remaining maximally compatible with existing Ethereum infrastructure. This document provides an overview of the protocol to provide context for the rest of the specification. + +## Table of Contents +1. [Foundations](#foundations) +2. [Protocol Guarantees](#protocol-guarantees) +3. [Network Participants](#network-participants) +4. [Key Interaction Diagrams](#key-interaction-diagrams) + - [Depositing and Transacting](#depositing-and-sending-transactions) + - [Withdrawing](#withdrawing) + - [Verifying the Network](#verifying-the-network) +5. [Next Steps](#next-steps) + +## Foundations + +### What is Ethereum scalability? + +Scaling Ethereum means increasing the number of useful transactions the Ethereum network can process. Ethereum's limited resources, specifically bandwidth, computation, and storage, constrain the number of transactions which can be processed on the network. Of the three resources, computation and storage are currently the most significant bottlenecks. These bottlenecks limit the supply of transactions, leading to extremely high fees. Scaling Ethereum and reducing fees can be achieved by increasing the supply of these limited resources. + +### What is Optimistic Rollup? + +[Optimistic rollup](https://vitalik.ca/general/2021/01/05/rollup.html) is a layer 2 scalability technique which increases the computation & storage capacity of Ethereum without sacrificing security or decentralization. Transaction data is submitted on-chain but executed off-chain. If there is an error in the off-chain execution, a fraud proof can be submitted on-chain to correct the error and protect user funds. In the same way you don't go to court unless there is a dispute, you don't execute transactions on on-chain unless there is an error. + +### What is EVM Equivalence? + +[EVM Equivalence](https://medium.com/ethereum-optimism/introducing-evm-equivalence-5c2021deb306) is complete compliance with the state transition function described in the Ethereum yellow paper, the formal definition of the protocol. By conforming to the Ethereum standard across EVM equivalent rollups, smart contract developers can write once and deploy anywhere. + +### 🎶 All together now 🎶 + +#### Optimistic Ethereum is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_. + +## Protocol Guarantees + +In order to scale Ethereum without sacrificing security, we must preserve 3 critical properties of Ethereum layer 1: liveness, availability, and validity. + +1. **Liveness** - Anyone must be able to extend the rollup chain by sending transactions at any time. + - There are two ways transactions can be sent to the rollup chain: 1) via the sequencer, and 2) directly on layer 1. The sequencer provides low latency & low cost transactions, while sending transactions directly to layer 1 provides censorship resistance. +2. **Availability** - Anyone must be able to download the rollup chain. + - All information required to generate the chain is embedded into layer 1 blocks. That way as long as the layer 1 chain is available, so is the rollup. +3. **Validity** - All transactions must be correctly executed and all withdrawals correctly processed. + - The rollup state and withdrawals are managed on an L1 contract called the `Block Hash Oracle`. This oracle is guaranteed to _only_ finalize correct (ie. valid) rollup block hashes given a **single honest verifier** assumption. If there is ever an invalid block hash asserted on layer 1, an honest verifier will prove it is invalid and win a bond. + +**Footnote**: There are two main ways to enforce validity of a rollup: fraud proofs (optimistic rollup) and validity proofs (zkRollup). For the purposes of this spec we only focus on fraud proofs but it is worth noting that validity proofs can also be plugged in once they have been made feasible. + +## Network Participants + +There are three actors in Optimistic Ethereum: users, sequencers, and verifiers. + +![Network Overview](./assets/network-participants-overview.svg) + +### Users + +At the heart of the network are users (us!). Users can: + +1. Deposit or withdraw tokens by sending transactions to Ethereum mainnet. +2. Use EVM smart contracts on layer 2 by sending transactions to the sequencers. +3. View the status of transactions using block explorers provided by network verifiers. + +### Sequencers + +The sequencers are the primary block producers. They: + +1. Accept user transactions. +2. Validate the transaction fee. +3. Produce sequencer blocks. +4. Propagate sequencer blocks to verifiers. And finally +5. Submit sequencer blocks to layer 1. + +There may be one sequencer **or** many using a consensus protocol. + +### Verifiers + +Verifiers serve two purposes: + +1. Serving rollup data to users; and +2. Verifying rollup integrity and disputing invalid assertions. + +In order for the network to remain secure there must be **at least** one honest verifier who is able to verify the integrity of the rollup chain & serve blockchain data to users. + +## Key Interaction Diagrams + +The following diagrams demonstrate how protocol components are utilized during key user interactions in order to provide context when diving into any particular component specification. + +### Depositing and Sending Transactions + +Users will often begin their L2 journey by depositing ETH from L1. Once they have ETH to pay fees, they'll start sending transactions on L2. The following diagram demonstrates this interaction and all key Optimistic Ethereum components which are utilized: + +![Diagram of Depositing and Sending Transactions](./assets/sequencer-handling-deposits-and-transactions.svg) + +Links to components mentioned in this diagram: + +- Rollup Feeds (WIP) +- Rollup Node (WIP) +- Execution Engine (WIP) +- Sequencer Batch Submitter (WIP) +- L2 Block Hash Oracle (WIP) +- Block Hash Assertion Submitter (WIP) +- Fraud Proof VM (WIP) + +### Withdrawing + +Just as important as depositing, it is critical that users can withdraw from the rollup. Withdrawals are initiated by normal transactions on L2, but then completed using a transaction on L1 after the dispute period has elapsed. + +![Diagram of Withdrawing](./assets/user-withdrawing-to-l1.svg) + +Links to components mentioned in this diagram: + +- Rollup Feeds (WIP) +- Block Hash Oracle (WIP) +- Bridge (WIP) + + +### Verifying The Network + +To ensure only valid withdrawals are processed, it is critical that verifiers check each block hash assertion that the sequencer makes and disputes it if there is an error. The following diagram demonstrates a verifier on the network that detects an invalid assertion and submits a dispute, thereby protecting user funds: + +![Diagram of a verifier disputing an assertion](./assets/verifier-executing-fraud-proof.svg) + +Links to components mentioned in this diagram: + +- Rollup Node (WIP) +- Execution Engine (WIP) +- L2 Block Hash Oracle (WIP) +- Challenger Agent (WIP) +- Fraud Proof VM (WIP) + +## Next Steps + +This is a choose your own adventure. Are you interested in how a verifier works under the hood? Maybe you want to dive deep into the bit flippin' Fraud Proof VM? All key components have been linked at least once in this doc, so you should now have the context you need to dive in deeper. [The world is yours](https://www.youtube.com/watch?v=e5PnuIRnJW8)! \ No newline at end of file From b960eb433274100544e1ea3dbaecdf51d578a1af Mon Sep 17 00:00:00 2001 From: ben-chain Date: Thu, 28 Oct 2021 12:59:50 -0700 Subject: [PATCH 028/585] fix(introduction): minor clarifications around sequencer --- introduction.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/introduction.md b/introduction.md index f8e76b2b8d10..b316abbd05a0 100644 --- a/introduction.md +++ b/introduction.md @@ -59,15 +59,17 @@ At the heart of the network are users (us!). Users can: ### Sequencers -The sequencers are the primary block producers. They: +The sequencer is the primary block producers. There may be one sequencer **or** many using a consensus protocol. For 1.0.0, there is just one sequencer. In general, specifications may use "the sequencer" to be a stand-in term for the consensus protocol operated by multiple sequencers. -1. Accept user transactions. -2. Validate the transaction fee. -3. Produce sequencer blocks. -4. Propagate sequencer blocks to verifiers. And finally -5. Submit sequencer blocks to layer 1. +The sequencer: +1. Accepts user off-chain transactions (exposes `eth_sendRawTransaction`, validates fees, ...) +2. Observes on-chain transactions (primarily, deposit events coming from L1) +3. Consolidates both kinds of transactions into L2 blocks with a specific ordering. +4. Propagates consolidated L2 blocks to L1, by submitting two things as calldata to L1: + - The pending off-chain transactions accepted in step 1. + - Sufficient information about the ordering of the on-chain transactions to successfully reconstruct the blocks from step 3., purely by watching L1. -There may be one sequencer **or** many using a consensus protocol. +The sequencer also provides access to block data as early as step 3., so that users may access real-time state in advance of L1 confirmation if they so choose. ### Verifiers From 961d85f75528f91e59ab2a218a8a3daad636fa2f Mon Sep 17 00:00:00 2001 From: ben-chain Date: Thu, 28 Oct 2021 21:43:14 -0700 Subject: [PATCH 029/585] feat(overview): update overview with improved design goals and resolved caveats --- overview.md | 57 ++++++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/overview.md b/overview.md index 08d8faafdae6..39132fb1b010 100644 --- a/overview.md +++ b/overview.md @@ -1,32 +1,38 @@ -# Optimistic Rollup Overview +# Optimistic Ethereum Overview +*// Note: this section assumes you've read the [introduction](./introduction.md)!* +## Arcitecture Design Goals -TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 tech on Layer 2. (Experimental, active R&D!) - -## Goals - -- 1:1 EVM - - No special compiler - - No unexpected gas cost - - All tooling just works (configure different chain ID, that's it) -- 100% compatibility with Eth1 nodes - - The Merge introduces an Engine API +- Execution-Level EVM Equivalence + - The developer experience should be indentical to L1 except where L2 introduces a fundamental difference. + - No special compiler + - No unexpected gas costs + - Out-of-the-box TX traces + - All tooling "just works"--configure chain ID, good to go + - Fundamental L2 differences are limited to the bare minimum, still use existing L1 standards, and require only block-level modifications. These include: + - Fee logic which accounts for L1 calldata costs (still uses existing L1 tx type) + - A new transaction type for deposits (still uses L1 tx envelope schema) + - EIP1559 algorithm that accounts for L2 blocktimes +- Maximal compatibility with Eth1 nodes + - Uses the ETH2 merge's Engine API for: - Fork-choice: change head based on L1 reorgs of data (and leverage undisputed state-roots for finalized checkpoint) - Block-production: sequencing blocks with any Eth1 node - Block-insertion: Eth1 node has specialized EVM and DB, valuable for L2, instead of reinventing the wheel - - Leverage sync: insert latest blocks from rollup node (pull from L1), but do state-sync via L2 p2p network - - Leverage tx propagation (happy case, if not forcing tx via L1): L2 user sends transaction to any sequencer, via tx pool. Anyone can bond to be a sequencer - - Fee model fit: EIP1559 on L2, on actual L2 block-capacity usage. (note: L2 gas-limit of blocks may adjust based on L1 data cost) + - Leverages sync: verify block inputs based on L1, but do state-sync via L2 p2p network + - Leverage tx propagation: can use existing mempool infrastructure +- Simple, stateless services + - Whenever possible (e.g. in batch submitter and synchronizer), services contributing to the rollup infrastructure do not persist state + - Given an L1 node, and an L2 execution engine, all other services can recover to full operation when started with a fresh DB ## Components ![Architecture Diagram](./assets/architecture.svg) -### L1 Contracts -- **Feeds**: "Data availability layer"--append-only logs (e.g. of deposits, transactions, and batched transactions) which must guarantee that: - - all values and their witnesses are indexable by off-chain parties - - witnesses are verifiable by on-chain dispute contract -- **L2 Block Oracle**: Cryptoeconomic light client of the L2. - - *Contract separation is not yet final. Highest priority interface spec: Single-step verification API* +### L1 Components +- **Feeds**: ("Data availability layer"): A **feed** is an append-only log of data (e.g. of deposits, or sequencer batches) which must guarantee that: + - All entries are deterministically indexable by off-chain parties. + - The fraud proof VM can find any feed entry in a bounded number of steps, such that the off-chain indexing is sufficient to generate a witness for verifing any individual step on-chain. + - Note: a "feed" may not necessarily correspond to an on-chain contract (e.g. which stores a hash of each entry). Instead, a feed refers to the actual log of data which is derivable from L1, which may or may not use a contract. For more info, check out [this discussion.](https://github.com/ethereum-optimism/optimistic-specs/issues/14) +- **L2 Block Oracle**: A cryptoeconomic light client of the L2. Will finalize hashes of the L2 state on L1, once the dispute period has passed. Used to validate withdrawals. *(Note: contract separation is not yet final)* - **Proposal Manager**: Handles conflicting state proposals to determine malicious party - Maintains a set of ongoing optimistic proposals of the L2 state - Ensures that state proposers are sufficiently bonded @@ -101,14 +107,3 @@ TLDR: Push the optimistic-rollup state of the art by leveraging Ethereum Layer 1 - Finalizes pre-confirmed sequencer transactions onto L1 - Writes to sequencer feed - -## Caveats - -- Undecided if the rollup will be committing to state-roots or block-roots, both have pros/cons -- MPT (Merkle Patricia Trie, storage layout of ethereum) is even more complex in this context, - possible to translate into execution steps, but takes dev time -- Receipt trie and transaction trie in the block use MPT too, but do not need witness data, they are write-only -- Some precompiles are harder to implement, possible, but ignored for now -- Generator is essentially an EVM implementation, needs a lot of testing (leverage eth1 testing suite) - - From 32f1204f5ff939390f44a799ff782d0306eef838 Mon Sep 17 00:00:00 2001 From: ben-chain Date: Thu, 28 Oct 2021 21:48:36 -0700 Subject: [PATCH 030/585] feat(components): add exec-engine details --- components/exec_engine.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/components/exec_engine.md b/components/exec_engine.md index 5dd7bd19d481..e4dfa75b30ac 100644 --- a/components/exec_engine.md +++ b/components/exec_engine.md @@ -1,2 +1,14 @@ -# Execution Engine Usage +# Execution Engine +## Overview + +The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal ETH2, the consensus node sends ETH blocks from the beacon chain into the engine. In Optimistic Ethereum, the Consensus Layer (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically generated from L1 into the engine. + +## Differences between L1 and L2 EE + +1. **Deposit TX Type**: There is a new typed transaction which corresponds to deposits. This is a cross-chain message type; not propagated by the mempool, only insertable by the rollup node in correspondence to an on-chain event. This transaction type is also able to mint deposited ETH as new native L2 `account.value`. +2. **Deposit Insertability**: The TX type described above must be L1-authenticated and therefore cannot come from the unauthenticated mempool. This requires adding a `Transaction[]` argument to [`engine_perparePayload`](https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.2/src/engine/interop/specification.md#engine_preparepayload). +3. **Fee payment modification**: ETH is charged in addition to the `gasPrice * gasUsed`, to compensate the sequencer for rolling up the user transaction. +4. **EIP1559 modification**: Updates to the `BASEFEE` on L2 must be handled differently, in accordance to L1 time, as L2 blocktime may not be constant. +5. **L1 Context Information**: The L1 blockhash, L1 blocknumber, and L1 basefee are frequently requested to be accessible within L2. *(TBD: it is possible to expose this information purely in a normal L2 contract, which is updated via the deposit TX type. This may minimize the diff more.)* +6. **Confirmation Status**: The Execution Engine will expose an additional bit per L2 block. This corresponds to whether or not an L2 block has been finalized on L1, or is in the sequencer state and still pending batch submission. \ No newline at end of file From 81ca2463352ac5bc2436463dec57c541a77d7996 Mon Sep 17 00:00:00 2001 From: ben-chain Date: Thu, 28 Oct 2021 21:43:50 -0700 Subject: [PATCH 031/585] feat(components): add README with 5 sub-components of a rollup node --- components/batch_submitter.md | 1 - components/rollup_node.md | 61 ------------------ components/rollup_node/README.md | 64 +++++++++++++++++++ components/rollup_node/batch_submitter.md | 2 + components/rollup_node/block_producer.md | 2 + components/{ => rollup_node}/exec_engine.md | 2 +- components/rollup_node/rollup_driver.md | 2 + .../rollup_node/sequencer_replicator.md | 2 + 8 files changed, 73 insertions(+), 63 deletions(-) delete mode 100644 components/batch_submitter.md delete mode 100644 components/rollup_node.md create mode 100644 components/rollup_node/README.md create mode 100644 components/rollup_node/batch_submitter.md create mode 100644 components/rollup_node/block_producer.md rename components/{ => rollup_node}/exec_engine.md (92%) create mode 100644 components/rollup_node/rollup_driver.md create mode 100644 components/rollup_node/sequencer_replicator.md diff --git a/components/batch_submitter.md b/components/batch_submitter.md deleted file mode 100644 index 4439b8e3c236..000000000000 --- a/components/batch_submitter.md +++ /dev/null @@ -1 +0,0 @@ -# Batch Submitter diff --git a/components/rollup_node.md b/components/rollup_node.md deleted file mode 100644 index 580a2c15faa5..000000000000 --- a/components/rollup_node.md +++ /dev/null @@ -1,61 +0,0 @@ -# Rollup Node - -The consensus module of Optimistic Ethereum. - -## Summary - -The Rollup Node is a consensus client that determines the latest state of the rollup. It reads state from the canon chain (L1) to compute the rollup state. - -## Components - -#### Feed Oracle - -The Feed Oracle is an adapter that monitors the canon chain for new events in the rollup contract. The rollup contract provides the *canonical* order for the rollup chain. - -The Feed Oracle can index the batch submissions and deposits locally into the database. The batch submissions should be converted into equivalent rollup blocks. - -#### Consensus - -Additional checks should be imposed on the execution engine. Roughly: - -```python -def on_block(db, block): - ctx = None - for tx in block.transactions: - # verify context tx updates canon light client with correct data - if tx.is_ctx(): - assert db.is_valid_ctx(tx) - ctx = tx - - # verify deposits are valid in the canon chain and in the context of the ctx tx - if tx.is_deposit(): - assert db.is_valid_deposit(ctx, tx) - - # run the block in the executin engine, if it's valid it's the new head of the - # rollup chain - assert verify_block_in_execution_engine(block) -``` - -#### Execution Engine - -The execution engine implements the [execution specification][execution-spec]. There already many teams who plan to transition their legacy clients into execution engines. The rollup client will communicate to the engine via a bidirectional JSON-RPC interface ([WIP][execution-engine-rpc]). - -One of the main goal of the rollup client is to use the execution engine without modification. - -### Miner - -The miner assembles the block via the Execution Engine. It injects context transactions that update the light client to the canon chain and it inject new deposit transactions. It submits the transaction batch to and waits until the transaction is mined (potentially bumping fee price if needed). - -#### Database - -The database persists the rollup chain and indexed data from the canon chain. Pruning of canon chain data can be aggressive since indexed data is only relevant to consensus during the force-inclusion period of deposits. - -#### Networking - -The Rollup Node should provide proxied access to the Execution Engine's networking stack. This allows for two main things: - -* Context updates and deposits are injected into the execution engine via transactions. This means that it's possible for the Execution Engine to receive signed system updates in the public mempool. This could cause block producing rollup nodes to submit bundles with invalid contexts/deposits. -* To provide fast-confirmations, a group of rollup block producers can define a "unconfirmed" blocks that haven't yet been submitted to mainnet (but will likely be in the near future). - -[execution-spec]: https://github.com/ethereum/execution-specs -[execution-engine-rpc]: https://hackmd.io/@n0ble/consensus_api_design_space diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md new file mode 100644 index 000000000000..a1abc9be8cbb --- /dev/null +++ b/components/rollup_node/README.md @@ -0,0 +1,64 @@ +# Rollup Node + +The consensus module of Optimistic Ethereum. + +## Summary + +The Rollup Node is a consensus client that determines the latest state of the rollup. It reads state from L1, and possibly the sequencer, to compute the L2 state. The [block generation spec][block-gen] defines the rules by which L1 state is converted into L2 blocks. + +## Types of Rollup Nodes +There are three primary classes of rollup nodes, corresponding to different configurations of the software stack. + +1. **Sequencer**: Accepts user-sent and deposit transactions, orders them into L2 blocks, and submits them to L1 in batches. Provides RPC access to pending L2 blocks in advance of L1 submission. +2. **Verifier**: Watches L1 feeds, reconstructs L2 block inputs, and inserts them into the EE to determine the canonical L2 state. May also track pending sequencer state, in some configurations. + +### Subcomponents Used for Each Node Type +Of the components outlined below, different node types use different combinations of them, either manually or optionally. + +| Node Type \ Component | Execution Engine | Rollup Driver | Sequencer Replicator | Block Producer | Batch Submitter | +|-----------------------|------------------|----------------------|----------------------|----------------|-----------------| +| Verifier | X | X | optional | | | +| Sequencer | X | X | | X | X | + +## Components + +### [Execution Engine][exec-engine] + +The execution engine implements the [execution specification][execution-spec]. Most L1 clients will soon be converted into execution engines. The rollup client will communicate to the engine via a JSON-RPC interface ([WIP][execution-engine-rpc]). + +One of the main goal of the rollup client is to use the execution engine without modification. + +### [Rollup Driver][rollup-driver] + +The rollup driver connects to an L1 node, and tracks the feed data comprising of deposits and sequencer batches. Based on the rules of [block generation][block-gen], it is able to compute sets ("epochs") of L2 blocks as a stateless, pure function of ranges of L1 blocks. + +Together with the Execution Engine, it uses the Engine API to progress the L2 state as new data comes in from L1. The rollup driver will reorganize the L2 state if it detects a between the EE and what's on L1, and provides a way for other services to subscribe to reorgs. + +### [Sequencer Replicator][sequencer-replicator] + +The sequencer replicator connects directly to the sequencer. It requests pending L2 blocks which have not yet been batch submitted, and inserts them into the tip of the local EE. + +These blocks are marked in the EE as not yet confirmed on L1. Replicating verifiers still run a CL, which will later mark them as L1-confirmed within the EE. + +### [Block Producer][block-producer] + +The block producer service is run by the sequencer to progress the L2 state in advance of batch submission. The block producer repeatedly calls `engine_preparePayload` to get a new L2 block and then uses `engine_executePayload` to insert the resulting block into the state. When new L1 blocks appear, it passes the corresponding deposit transactions to `engine_preparePayload`. + +### [Batch Submitter][batch-submitter] + +The batch submitter takes the pending blocks which have been inserted into the sequencer's L2 state by the block producer, and sends corresponding transactions in batches to L1. + +The batch submitter encodes these transactions based on the rules of [block generation][block-gen], effectively as the reverse of the process carried out by the rollup driver. As a result: +- Blocks previously inserted by the Block Producer into the Sequencer's EE will now appear in L1 Verifiers' EEs. +- Blocks marked as sequencer-confirmed in both the Sequencer and in Replicating verifiers will now be marked as L1-confirmed. + +TOOD: update block-gen link once PR is merged + +[execution-spec]: https://github.com/ethereum/execution-specs +[execution-engine-rpc]: https://hackmd.io/@n0ble/consensus_api_design_space +[block-gen]: https://github.com/ethereum-optimism/optimistic-specs/pull/16 +[exec-engine]: ./exec_engine.md +[rollup-driver]: ./consensus_layer.md +[sequencer-replicator]: ./sequencer_replicator.md +[block-producer]: ./block_producer.md +[batch-submitter]: ./batch_submitter.md \ No newline at end of file diff --git a/components/rollup_node/batch_submitter.md b/components/rollup_node/batch_submitter.md new file mode 100644 index 000000000000..5bfe907c18db --- /dev/null +++ b/components/rollup_node/batch_submitter.md @@ -0,0 +1,2 @@ +# Batch Submitter +TODO, see README for now. \ No newline at end of file diff --git a/components/rollup_node/block_producer.md b/components/rollup_node/block_producer.md new file mode 100644 index 000000000000..376bbddeb11a --- /dev/null +++ b/components/rollup_node/block_producer.md @@ -0,0 +1,2 @@ +# Block Producer +TODO, see README for now. \ No newline at end of file diff --git a/components/exec_engine.md b/components/rollup_node/exec_engine.md similarity index 92% rename from components/exec_engine.md rename to components/rollup_node/exec_engine.md index e4dfa75b30ac..042a0c710c80 100644 --- a/components/exec_engine.md +++ b/components/rollup_node/exec_engine.md @@ -2,7 +2,7 @@ ## Overview -The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal ETH2, the consensus node sends ETH blocks from the beacon chain into the engine. In Optimistic Ethereum, the Consensus Layer (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically generated from L1 into the engine. +The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal ETH2, the consensus node sends ETH blocks from the beacon chain into the engine. In Optimistic Ethereum, the Rollup Driver (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically generated from L1 into the engine. ## Differences between L1 and L2 EE diff --git a/components/rollup_node/rollup_driver.md b/components/rollup_node/rollup_driver.md new file mode 100644 index 000000000000..d31927cf217e --- /dev/null +++ b/components/rollup_node/rollup_driver.md @@ -0,0 +1,2 @@ +# Rollup Driver +TODO, see README for now. \ No newline at end of file diff --git a/components/rollup_node/sequencer_replicator.md b/components/rollup_node/sequencer_replicator.md new file mode 100644 index 000000000000..46e7ba1c7397 --- /dev/null +++ b/components/rollup_node/sequencer_replicator.md @@ -0,0 +1,2 @@ +# Sequencer Replicator +TODO, see README for now. \ No newline at end of file From 96afa30bb4879ec1714152cd39e15dbdce57f569 Mon Sep 17 00:00:00 2001 From: ben-chain Date: Thu, 28 Oct 2021 23:01:02 -0700 Subject: [PATCH 032/585] feat(components): outline basic L1 sync logic for consensus layer --- components/rollup_node/rollup_driver.md | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/components/rollup_node/rollup_driver.md b/components/rollup_node/rollup_driver.md index d31927cf217e..9108c452af3e 100644 --- a/components/rollup_node/rollup_driver.md +++ b/components/rollup_node/rollup_driver.md @@ -1,2 +1,27 @@ # Rollup Driver -TODO, see README for now. \ No newline at end of file + +The Rollup Driver is the core code which guarantees that the canonical L1 state is accurately reflected in the EE. It does this by connecting to an L1 node, and using the pure function which maps L1 blocks to L2 block inputs as defined by [block generation][block-gen]. Once it knows the block inputs, it checks the EE to make sure that the blocks there all have the correct inputs. + +This is a functionality that is shared between all configurations of the rollup node, including the sequencer. Because block generation defines the L1 block -> L2 block input transformation as a pure function, it can be completely stateless and has no DB. + +## Basic Functionality + +We define the `latestL1ConfirmedL2Block` as the latest L2 block in the EE which is marked as L1-confirmed. This can be found by starting at the head of the L2 EE, and iterating backwards until we find the first L2 block which is marked as L1-confirmed. + +The core logic which the CL executes is as follows. + +1. Find `latestL1ConfirmedL2Block`. Then get `latestL1ConfirmedL2Block.l1BlockNumber` and `latestL1ConfirmedL2Block.l1BlockHash` from the EE. Compare these to L1 with an RPC query to the L1 node's RPC. + - if they DO match, continue to 2. + - if they DO NOT match, then there has been an L1 reorg. In that case: + - Signal the reorg. + - Iterate backwards until we find the latest L2 block whose `l1BlockNumber` and `l1BlockHash` DO match the L1 node RPC. + - Set the EE's head to this L2 block (thereby updating `latestL1ConfirmedL2Block`). +2. Iterate forward through L1 blocks, starting from `latestL1ConfirmedL2Block.l1BlockNumber + 1`. For each: + - Generate the L2 block inputs for this L1 block as defined by [block generation][block-gen]. For each L2 block input: + - If the L2 block DOES NOT exist in the EE already, insert it and update the EE head. + - If the L2 block DOES exist in the EE already (as sequencer confirmed), then compare the generated block input to the existing block input. + - If they DO match, mark the L2 block as L1 confirmed. + - If they DO NOT match, there has been an L2 reorg. Signal the reorg, insert the correct block, and update the EE head. +3. Wait and GOTO 1. + +[block-gen]: TODOPRMERGE \ No newline at end of file From 4c9973a542e004ad9f32a728d5ff5cf65739159b Mon Sep 17 00:00:00 2001 From: ben-chain Date: Thu, 28 Oct 2021 23:55:39 -0700 Subject: [PATCH 033/585] feat(components): add basic replicator service logic --- .../rollup_node/sequencer_replicator.md | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/components/rollup_node/sequencer_replicator.md b/components/rollup_node/sequencer_replicator.md index 46e7ba1c7397..9d8ed29bdbe8 100644 --- a/components/rollup_node/sequencer_replicator.md +++ b/components/rollup_node/sequencer_replicator.md @@ -1,2 +1,23 @@ # Sequencer Replicator -TODO, see README for now. \ No newline at end of file + +The sequencer replicator connects directly to the sequencer. It requests pending L2 blocks which have not yet been batch submitted, and inserts them into the tip of the local EE, marked only as sequencer confirmed (NOT L1 confirmed). The sequencer replicator is connected to the sequencer EE via RPC. + +A rollup node using the replicator will place additional trust in the sequencer's local state being resolved to L1 via batch submission. However, it will still execute all blocks itself, so that the EE state will always be something that *is possible* in the future, even if it doesn't end up manifesting that way on L1. + +## Basic Functionality + +- The sequencer replicator may only modify or add state which is at the end of the EE, and not yet L1 confirmed. + - The replicator is **NEVER** to modify any blocks in the EE which are marked L1 confirmed. + - ONLY sequencer confirmed blocks may written or overwritten by the replicator. +- Halted mode: If a reorg is detected by the [consensus layer][consensus-layer], or if the sequencer sends conflicting data (outlined below), the replicator service should halt. It should do this either for a configured time period, until manual intervention by the node operator, or perhaps until the CL indicates that it has finished syncing. If the replicator is halted, then the Replicating Verifier will subsequently behave identically to the L1 verifier. + +Core logic: + +1. Get the local EE head, and query the corresponding sequencer block via RPC. + - if the blocks DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. +2. Query the sequencer's RPC for the blocks between the local EE head and the sequencer head. For each returned block: + - Get the block input and apply it to the head. (As sequencer confirmed--even if sequencer says L1 confirmed.) + - Make sure the resulting local blockhash and stateroot match what sequencer returned. If they DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. +3. Wait and GOTO 1. + +[consensus-layer]: ./consensus_layer.md \ No newline at end of file From c7dcbb4f86cd0b2e90ec86aa77c5e90f37f57862 Mon Sep 17 00:00:00 2001 From: ben-chain Date: Fri, 29 Oct 2021 12:52:37 -0700 Subject: [PATCH 034/585] fix(rollup_node): address PR feedback --- components/rollup_node/README.md | 4 ++-- components/rollup_node/exec_engine.md | 8 ++++---- introduction.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md index a1abc9be8cbb..49952112a67b 100644 --- a/components/rollup_node/README.md +++ b/components/rollup_node/README.md @@ -22,7 +22,7 @@ Of the components outlined below, different node types use different combination ## Components -### [Execution Engine][exec-engine] +### [L2 Execution Engine][exec-engine] The execution engine implements the [execution specification][execution-spec]. Most L1 clients will soon be converted into execution engines. The rollup client will communicate to the engine via a JSON-RPC interface ([WIP][execution-engine-rpc]). @@ -32,7 +32,7 @@ One of the main goal of the rollup client is to use the execution engine without The rollup driver connects to an L1 node, and tracks the feed data comprising of deposits and sequencer batches. Based on the rules of [block generation][block-gen], it is able to compute sets ("epochs") of L2 blocks as a stateless, pure function of ranges of L1 blocks. -Together with the Execution Engine, it uses the Engine API to progress the L2 state as new data comes in from L1. The rollup driver will reorganize the L2 state if it detects a between the EE and what's on L1, and provides a way for other services to subscribe to reorgs. +While connected to the Execution Engine, it uses the Engine API to progress the L2 state as new data comes in from L1. The rollup driver will reorganize the L2 state if it detects a difference between the EE and what's on L1, and provides a way for other services to subscribe to reorgs. ### [Sequencer Replicator][sequencer-replicator] diff --git a/components/rollup_node/exec_engine.md b/components/rollup_node/exec_engine.md index 042a0c710c80..a81cc3fd1d9d 100644 --- a/components/rollup_node/exec_engine.md +++ b/components/rollup_node/exec_engine.md @@ -1,4 +1,4 @@ -# Execution Engine +# L2 Execution Engine ## Overview @@ -8,7 +8,7 @@ The L2 execution engine is where transaction execution actually takes place, and 1. **Deposit TX Type**: There is a new typed transaction which corresponds to deposits. This is a cross-chain message type; not propagated by the mempool, only insertable by the rollup node in correspondence to an on-chain event. This transaction type is also able to mint deposited ETH as new native L2 `account.value`. 2. **Deposit Insertability**: The TX type described above must be L1-authenticated and therefore cannot come from the unauthenticated mempool. This requires adding a `Transaction[]` argument to [`engine_perparePayload`](https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.2/src/engine/interop/specification.md#engine_preparepayload). -3. **Fee payment modification**: ETH is charged in addition to the `gasPrice * gasUsed`, to compensate the sequencer for rolling up the user transaction. -4. **EIP1559 modification**: Updates to the `BASEFEE` on L2 must be handled differently, in accordance to L1 time, as L2 blocktime may not be constant. +3. **Fee payment modification**: ETH is charged in addition to the `gasPrice * gasUsed`, to compensate the sequencer for rolling up the user transaction. This should be consistent with the [existing OVM 2.0 fee scheme](https://community.optimism.io/docs/users/fees-2.0.html), but using the L1 context information directly instead of via an oracle. +4. **EIP1559 modification**: Updates to the `BASEFEE` on L2 must be handled differently, in accordance to L1 time, as L2 blocktime may not be constant. (*Note: this modification may not be necessary; L1 devs are actively discussing modification of eip-1559 to handle "gap-slots" which would solve for the same timing.*) 5. **L1 Context Information**: The L1 blockhash, L1 blocknumber, and L1 basefee are frequently requested to be accessible within L2. *(TBD: it is possible to expose this information purely in a normal L2 contract, which is updated via the deposit TX type. This may minimize the diff more.)* -6. **Confirmation Status**: The Execution Engine will expose an additional bit per L2 block. This corresponds to whether or not an L2 block has been finalized on L1, or is in the sequencer state and still pending batch submission. \ No newline at end of file +6. **Confirmation Status**: The Execution Engine will repurpose (but not otherwise modify) the three beacon chain confirmation strengths (`finalized, safe, unsafe`) to corresponding to (`l1_finalized, l1_confirmed, sequencer_confirmed`). \ No newline at end of file diff --git a/introduction.md b/introduction.md index b316abbd05a0..ab72b7ffd3ef 100644 --- a/introduction.md +++ b/introduction.md @@ -59,7 +59,7 @@ At the heart of the network are users (us!). Users can: ### Sequencers -The sequencer is the primary block producers. There may be one sequencer **or** many using a consensus protocol. For 1.0.0, there is just one sequencer. In general, specifications may use "the sequencer" to be a stand-in term for the consensus protocol operated by multiple sequencers. +The sequencer is the primary block producer. There may be one sequencer **or** many using a consensus protocol. For 1.0.0, there is just one sequencer. In general, specifications may use "the sequencer" to be a stand-in term for the consensus protocol operated by multiple sequencers. The sequencer: 1. Accepts user off-chain transactions (exposes `eth_sendRawTransaction`, validates fees, ...) From 7e4aba192aa7681b7d2d2d012f9d8306b5b82044 Mon Sep 17 00:00:00 2001 From: ben-chain Date: Fri, 29 Oct 2021 14:06:35 -0700 Subject: [PATCH 035/585] feat(overview): updated diagram and explanations --- assets/architecture.svg | 2 +- overview.md | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/assets/architecture.svg b/assets/architecture.svg index d353b0ea73af..247e80d5a5bf 100644 --- a/assets/architecture.svg +++ b/assets/architecture.svg @@ -1,4 +1,4 @@ -
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L1
L1
L2
L2
reads
reads
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
uses
uses
Challenger Agent
Challenger Agent
reads
reads
Witness Generator
Witness Generator
reads
reads
provides consensus
provides consensus
Rollup Client
Rollup Client
writes
writes
reads
reads
Batch Submitter
Batch Submitter
Execution Engine
Execution Engine
L2 Block Oracle
L2 Block Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
Viewer does not support full SVG 1.1
\ No newline at end of file +
L1
L1
L2
L2
reads
(withdrawals)
reads...
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
gets proofs
gets proofs
Challenger Agent
Challenger Agent
canonical L2 state
canonical L2 state
Witness Generator
Witness Generator
reads canonical
block inputs
reads canonical...
canonical L1
consensus
canonical L1...
Rollup Driver
Rollup Driver
submits
pending
blocks
submits...
reads pending
blocks
reads pending...
Batch Submitter
Batch Submi...
Execution Engine
Execution Engine
L2 Block Oracle
L2 Block Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
writes pending
blocks
writes pending...
reads
pending
deposits
reads...
Block Producer
Block Produ...
pending
sequencer
blocks
pending...
Sequencer Replicator
Sequencer R...
Node TypeSequencerVerifier
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L2 Block Feed
L2 Bloc...
+
+
=
=
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/overview.md b/overview.md index 39132fb1b010..91bb8c776ad7 100644 --- a/overview.md +++ b/overview.md @@ -28,9 +28,14 @@ ![Architecture Diagram](./assets/architecture.svg) ### L1 Components -- **Feeds**: ("Data availability layer"): A **feed** is an append-only log of data (e.g. of deposits, or sequencer batches) which must guarantee that: - - All entries are deterministically indexable by off-chain parties. - - The fraud proof VM can find any feed entry in a bounded number of steps, such that the off-chain indexing is sufficient to generate a witness for verifing any individual step on-chain. +- **Feeds**: ("Data availability layer"): A **feed** is an append-only log of data (e.g. of deposits, or sequencer batches). Feeds can be computed as functions of L1 block data. The definition of these functions can be found in the [block generation spec][block-gen]. Optimistic Ethereum has three primary feeds: + - **Deposit Feed**: A feed of L2 transactions which originated as smart contract calls in the L1 state which emitted an event. Deposits are guaranteed to be reflected in the L2 state within the *sequencing window*. + - **Sequencer Feed**: A feed of L2 transactions which are submitted by the sequencer to L1 in batches. Includes L2 tx calldata, *as well as time and ordering information.* + - **L2 Block Feed**: A feed of canonical L2 block inputs (i.e. L2 blocks, but without the `stateRoot`, `receiptsRoot`, `gasUsed`, ...) which should be executed by L2 nodes and enforced in fraud proofs. + - ***The L2 Block Feed is a pure function of the Deposit Feed and Sequencer Feed.*** That is, given the Deposit Feed and Sequencer Feed, the L2 Block Feed can be reconstructed, even without full L1 blockdata. + - In general, all feeds must enforce that: + - All entries are deterministically indexable by off-chain parties. + - The fraud proof VM can find any feed entry in a bounded number of steps, such that the off-chain indexing is sufficient to generate a witness for verifing any individual step on-chain. - Note: a "feed" may not necessarily correspond to an on-chain contract (e.g. which stores a hash of each entry). Instead, a feed refers to the actual log of data which is derivable from L1, which may or may not use a contract. For more info, check out [this discussion.](https://github.com/ethereum-optimism/optimistic-specs/issues/14) - **L2 Block Oracle**: A cryptoeconomic light client of the L2. Will finalize hashes of the L2 state on L1, once the dispute period has passed. Used to validate withdrawals. *(Note: contract separation is not yet final)* - **Proposal Manager**: Handles conflicting state proposals to determine malicious party @@ -50,9 +55,8 @@ - Runs verification step - Registers result in bond-manager (slash sequencer, reward challenger, or vice-versa if spam attempt) - **Cross-domain Messenger**: Message-passing abstraction contract used by applications developers (e.g. token bridge implementations) - - Sends messages into L2, reads messages out from L1 - - Log authorized calls as forced L2 transactions (deposits) - - Verify L2 data statelessly with MPT proof to undisputed state-root (withdrawals) + - Sends messages into L2 (deposits) by adding to the deposit feed + - Relays messages out of L2 (withdrawals) by MPT proof to undisputed state-root ### L2 Components @@ -107,3 +111,4 @@ - Finalizes pre-confirmed sequencer transactions onto L1 - Writes to sequencer feed +[block-gen]: TODOPR \ No newline at end of file From 78901d10fd65dd1d0d07bbeb57b0b678487f3632 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Fri, 29 Oct 2021 23:16:24 +0100 Subject: [PATCH 036/585] Apply suggestions from code review --- components/rollup_node/README.md | 2 +- components/rollup_node/exec_engine.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md index 49952112a67b..091b201b1d94 100644 --- a/components/rollup_node/README.md +++ b/components/rollup_node/README.md @@ -7,7 +7,7 @@ The consensus module of Optimistic Ethereum. The Rollup Node is a consensus client that determines the latest state of the rollup. It reads state from L1, and possibly the sequencer, to compute the L2 state. The [block generation spec][block-gen] defines the rules by which L1 state is converted into L2 blocks. ## Types of Rollup Nodes -There are three primary classes of rollup nodes, corresponding to different configurations of the software stack. +There are two primary classes of rollup nodes, corresponding to different configurations of the software stack. 1. **Sequencer**: Accepts user-sent and deposit transactions, orders them into L2 blocks, and submits them to L1 in batches. Provides RPC access to pending L2 blocks in advance of L1 submission. 2. **Verifier**: Watches L1 feeds, reconstructs L2 block inputs, and inserts them into the EE to determine the canonical L2 state. May also track pending sequencer state, in some configurations. diff --git a/components/rollup_node/exec_engine.md b/components/rollup_node/exec_engine.md index a81cc3fd1d9d..a3bdd4db8bdc 100644 --- a/components/rollup_node/exec_engine.md +++ b/components/rollup_node/exec_engine.md @@ -2,12 +2,12 @@ ## Overview -The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal ETH2, the consensus node sends ETH blocks from the beacon chain into the engine. In Optimistic Ethereum, the Rollup Driver (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically generated from L1 into the engine. +The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal Eth2, the consensus node sends execution payloads (essentially eth1 blocks, without proof of work) from the beacon chain into the engine. In Optimistic Ethereum, the Rollup Driver (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically generated from L1 into the engine. ## Differences between L1 and L2 EE 1. **Deposit TX Type**: There is a new typed transaction which corresponds to deposits. This is a cross-chain message type; not propagated by the mempool, only insertable by the rollup node in correspondence to an on-chain event. This transaction type is also able to mint deposited ETH as new native L2 `account.value`. -2. **Deposit Insertability**: The TX type described above must be L1-authenticated and therefore cannot come from the unauthenticated mempool. This requires adding a `Transaction[]` argument to [`engine_perparePayload`](https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.2/src/engine/interop/specification.md#engine_preparepayload). +2. **Deposit Insertability**: The TX type described above must be L1-authenticated and deterministically applied, and therefore cannot come from the unauthenticated mempool. This requires adding a `Transaction[]` argument to [`engine_perparePayload`](https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.2/src/engine/interop/specification.md#engine_preparepayload). 3. **Fee payment modification**: ETH is charged in addition to the `gasPrice * gasUsed`, to compensate the sequencer for rolling up the user transaction. This should be consistent with the [existing OVM 2.0 fee scheme](https://community.optimism.io/docs/users/fees-2.0.html), but using the L1 context information directly instead of via an oracle. 4. **EIP1559 modification**: Updates to the `BASEFEE` on L2 must be handled differently, in accordance to L1 time, as L2 blocktime may not be constant. (*Note: this modification may not be necessary; L1 devs are actively discussing modification of eip-1559 to handle "gap-slots" which would solve for the same timing.*) 5. **L1 Context Information**: The L1 blockhash, L1 blocknumber, and L1 basefee are frequently requested to be accessible within L2. *(TBD: it is possible to expose this information purely in a normal L2 contract, which is updated via the deposit TX type. This may minimize the diff more.)* From e4ae2b63cfd9a92a5f574b8239cac5adc741ba6c Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Thu, 4 Nov 2021 11:18:33 -0700 Subject: [PATCH 037/585] Update roadmap diagram (#28) - Add infrastructure stability after v0.5 regenesis - Simplify the separation of concerns for v1.0 - Add some "future optimizations" to reflect a more accurate list of what we might want to do to push the chain to the next level. - Update the terminology in the fraud proof track. - Moved the boxes around so they are more chronologically ordered --- assets/roadmap.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/roadmap.svg b/assets/roadmap.svg index 41534dfc424c..02d69f0a1395 100644 --- a/assets/roadmap.svg +++ b/assets/roadmap.svg @@ -1,4 +1,4 @@ -
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
Rollup Node
Feed Contracts
Feed Contracts
Execution Engine
Execution Engine
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
(Formerly DTL)
Rollup Node...
Feed Contracts
(Formerly CTC)
Feed Contracts...
Execution Engine
(Deposits+mergeAPI)
Execution Engine...
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Assertion Manager
Assertion Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Equivalence Testing...
Fraud Proof <> Client Equivale...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
Rollup Node
Feed Contracts
Feed Contracts
Execution Engine
Execution Engine
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Contracts
Rollup Cont...
v0.5 Stability Infrastructure
v0.5 Stability Infrastructure
Rollup Client
Rollup Clie...
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
Dispute Game
Dispute Game
L2 State Oracle
L2 State Oracle
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof VM Audits
Fraud Proof VM Audits
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Decentralized Sequencer consensus
Decentralized Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Fraud Proof VM Optimization
Fraud Proof VM Optimization
Dispute Game Audits & Proofs
Dispute Game Audits & Proofs
v1.0 Spec
(Executable)
v1.0 Spec...
Geth Optimizations
(eg. EVM Parallelism)
Geth Optimizations...
State Expiry
State Expiry
Begin v2 Scalability Research
Begin v2 Sc...
Viewer does not support full SVG 1.1
\ No newline at end of file From e09a4e76dc4991a77b489f57066e7455f5d1002e Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Tue, 2 Nov 2021 23:48:29 +0000 Subject: [PATCH 038/585] Add block generation writeup --- assets/sequencer-block-gen.svg | 4 + assets/simple-block-gen.svg | 4 + components/rollup_node/README.md | 4 +- components/rollup_node/block_gen.md | 147 ++++++++++++++++++++++++ components/rollup_node/rollup_driver.md | 2 +- overview.md | 4 +- 6 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 assets/sequencer-block-gen.svg create mode 100644 assets/simple-block-gen.svg create mode 100644 components/rollup_node/block_gen.md diff --git a/assets/sequencer-block-gen.svg b/assets/sequencer-block-gen.svg new file mode 100644 index 000000000000..7debdbe1b0be --- /dev/null +++ b/assets/sequencer-block-gen.svg @@ -0,0 +1,4 @@ + + + +
L1
L1
L2
L2
D
D
S0
S0
S1
S1
D
D
D
D
D
D
S0
S0
S1
S1
Epoch 1
Epoch 1
Epoch 2
Epoch 2
Epoch 3
Epoch 3
Epoch 4
Epoch 4
....
....
Sequencer Rollup
Sequencer Rollup
!
!
Note: Epochs may not contain sequencer blocks
Note: Epochs may no...
Sequencer Block Submission Windows
Sequencer Block Submission Windows
Sequencing Window = 2 blocks
Sequencing Window = 2 blocks
S3
S3
S5
S5
S4
S4
S3
S3
S4
S4
S5
S5
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/simple-block-gen.svg b/assets/simple-block-gen.svg new file mode 100644 index 000000000000..00ec754999ea --- /dev/null +++ b/assets/simple-block-gen.svg @@ -0,0 +1,4 @@ + + + +
L1
L1
L2
L2
D
D
D
D
D
D
D
D
Epoch 1
Epoch 1
Epoch 2
Epoch 2
Epoch 3
Epoch 3
Epoch 4
Epoch 4
....
....
Simple Rollup
Simple Rollup
Sequencer timeout = 0 blocks
Sequencer timeout = 0 blocks
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md index 091b201b1d94..43fb567bbd7d 100644 --- a/components/rollup_node/README.md +++ b/components/rollup_node/README.md @@ -52,11 +52,9 @@ The batch submitter encodes these transactions based on the rules of [block gene - Blocks previously inserted by the Block Producer into the Sequencer's EE will now appear in L1 Verifiers' EEs. - Blocks marked as sequencer-confirmed in both the Sequencer and in Replicating verifiers will now be marked as L1-confirmed. -TOOD: update block-gen link once PR is merged - [execution-spec]: https://github.com/ethereum/execution-specs [execution-engine-rpc]: https://hackmd.io/@n0ble/consensus_api_design_space -[block-gen]: https://github.com/ethereum-optimism/optimistic-specs/pull/16 +[block-gen]: ./components/rollup_node/block_gen.md [exec-engine]: ./exec_engine.md [rollup-driver]: ./consensus_layer.md [sequencer-replicator]: ./sequencer_replicator.md diff --git a/components/rollup_node/block_gen.md b/components/rollup_node/block_gen.md new file mode 100644 index 000000000000..bbd7be6e352d --- /dev/null +++ b/components/rollup_node/block_gen.md @@ -0,0 +1,147 @@ +# Block Generation + +The logic which is used to generate the rollup chain from L1. + +## Glossary + +- **Block Inputs**: All information required to generate a full Ethereum block, given the pre-state and previous block. For example, does NOT include a state root for that block's input. +- **Rollup Blockchain**: The rollup blocks generated by performing the rollup's state transition function over all block inputs. For example, DOES include a state root for that block's input. + +## Summary + +The rollup chain can be deterministically generated given an L1 Ethereum chain. The fact that the entire rollup chain can be generated based on L1 blocks is _what makes OE a rollup_. This process can be represented as: + +```python +f(l1_blockchain) -> rollup_blockchain +``` + +In this document we define a block generation function which is designed to be: + +1. Context independent given a constant sized subset of the L1 chain. +2. Support sequencers and sequencer consensus. +3. Resilient sequencer censorship. + +## Rollup Epochs + +The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers. For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be generated after L1 block number `n` is added to the L1 chain. Epoch contain one to many rollup blocks. + +### Types of Blocks within Epochs + +Within these epochs, there are two block types: + +1. Deposit block +2. Sequencer block + +Deposit blocks contain contextual information about L1 such as the block hash. They also contain transactions initiated on L1 by any user or contract. + +Sequencer blocks are submitted by the sequencer and target _future_ epochs which satisfy the following two conditions: + +1. Target epoch is larger than the current L1 block number. +2. Target epoch is less than the current L1 block number PLUS `sequencing_window_size`. + +The ability for the sequencer to append sequencer blocks to future epochs allows the sequencer to predict and influence the state of the epoch before the L1 chain has mined it. This property is what enables _fast transaction confirmations_ via the sequencer replicator. + +### Epoch Structure + +Each epoch contains **1** deposit block and zero to many sequencer blocks. For epoch `n` the deposit block is generated using L1 block number `n - (sequencing_window_size + 1)`. The epoch's sequencer blocks are contained in any of the L1 blocks ranging from `n - sequencing_window_size` to `n`. This a range of blocks is called the "sequencing window". + +The following diagram demonstrates the correspondence between L1 blocks and rollup blocks (ie L2 blocks): + +![Sequencer block generation diagram](../../assets/sequencer-block-gen.svg) + +## Deposit Blocks in Depth + +For every L1 block (after the rollup's genesis) an L2 deposit block is created. These deposit blocks contain both a `ContextDeposit` and any number of `UserDeposit`s. Context deposits set contextual information about the latest L1 block (eg. `blockHash` and `timestamp`), and user deposits are L1 user initiated L2 transactions which guarantee liveness of the rollup chain even with a censoring sequencer. + +The types of deposit blocks are as follows: + +```python +class DepositBlock: + deposits: List[Deposit] + +class Deposit: + feedIndex: uint64 + GasLimit: uint64 + +class UserDeposit(Deposit): + isEOA: bool + l1TxOrigin: Address + target: Address + data: bytes + +class ContextDeposit(Deposit): + blockHash: bytes32 + blockNumber: uint64 + timestamp: uint64 + baseFee: uint64 +``` + +### Deposit Block Generation + +The function `generate_deposit_block(l1_block_number)` is defined as: + +- Generate the `ContextDeposit` using the L1 block body. Specifically the L1 block's `blockHash`, `blockNumber`, `timestamp`, and `baseFee`. +- Get all events emitted by the `DepositFeed` contract at block `l1_block_number`. + - For each event, generate a new `UserDeposit` based on the emitted calldata. All fields should be emitted by DepositFeed contract. + +#### **Footnote**: The DepositFeed ensures that no matter the size of the event it is possible to prove the deposit data to the fraud proof. See the DepositFeed spec for details. + +## Sequencer Blocks in Depth + +Sequencer blocks contain a majority of the transactions submitted to the rollup chain. Sequencer blocks can also influence the current timestamp of L2 which is exposed to contracts & is used in the EIP1559 fee pricing calculations. + +Sequencer blocks are of the following form: + +```python +class SequencerBlock: + target_epoch: uint64 # epoch number that this block is intended for + sequencer_suggested_timestamp: uint64 # a timestamp suggested by the sequencer + transactions: List[Transaction] # A list of transactions in the block +``` + +These sequencer blocks must be validated as properly formatted. These validity checks are: + +1. `target_epoch` must be within the sequencing window (introduced in the previous sections) +2. `sequencer_suggested_timestamp` must be monotonic & within an acceptable range. +3. `transactions` must all be correctly formatted (eg. contain valid signatures). + +If any of these checks fail the block must be skipped or ignored. Otherwise, all transactions in the sequencer block will be executed. + +## Timestamps in Depth + +Time can be manipulated by the sequencer; however, it must stay within reasonable bounds and must be monotonic (ie. can never go backwards). The specific conditions that must be met are: + +```python +# last_l1_timestamp is the L1 timestamp set during the last ContextDeposit +# last_timestamp is the timestamp from the previous rollup block +# average_l1_block_time is the average time between two L1 blocks +# sequencing_window_size is the number of L1 blocks the sequencer has to submit their blocks +min_timestamp = max(last_l1_timestamp, last_timestamp) +max_timestamp = last_l1_timestamp + sequencing_window_size * average_l1_block_time + +assert sequencer_suggested_timestamp >= min_timestamp +assert sequencer_suggested_timestamp <= max_timestamp +``` + +The timestamp exposed on the rollup chain is: + +```python +# last_sequencer_suggested_timestamp is the most recent valid sequencer_suggested_timestamp +def timestamp(): + max(last_l1_timestamp, last_sequencer_suggested_timestamp) +``` + + +## Epoch Block Input Generation +An epoch's block inputs can be generated using the following function: + +- To generate the blocks in epoch `n`, supply L1 blocks `n - (sequencing_window_size + 1)` through `n`. This function returns a list of all rollup blocks in epoch `n`. We will call this list `epoch_rollup_blocks`. +- The first block input for the epoch is always the deposit block. + - Generate the block input with `generate_deposit_block(l1_blocks[0])` (function defined above). + - Append the deposit block to `epoch_rollup_blocks` +- To generate all of the sequencer blocks, for each block in `l1_blocks`: + - Extract the valid sequencer blocks + - If they are targeting epoch `n`, append the sequencer block to `epoch_rollup_blocks`. +- Return `epoch_rollup_blocks`. + +After having generated each epoch it is possible to stich all epochs together to form the full rollup chain. \ No newline at end of file diff --git a/components/rollup_node/rollup_driver.md b/components/rollup_node/rollup_driver.md index 9108c452af3e..057bf2f9ceb5 100644 --- a/components/rollup_node/rollup_driver.md +++ b/components/rollup_node/rollup_driver.md @@ -24,4 +24,4 @@ The core logic which the CL executes is as follows. - If they DO NOT match, there has been an L2 reorg. Signal the reorg, insert the correct block, and update the EE head. 3. Wait and GOTO 1. -[block-gen]: TODOPRMERGE \ No newline at end of file +[block-gen]: ./components/rollup_node/block_gen.md \ No newline at end of file diff --git a/overview.md b/overview.md index 91bb8c776ad7..dc3808c41c55 100644 --- a/overview.md +++ b/overview.md @@ -32,7 +32,7 @@ - **Deposit Feed**: A feed of L2 transactions which originated as smart contract calls in the L1 state which emitted an event. Deposits are guaranteed to be reflected in the L2 state within the *sequencing window*. - **Sequencer Feed**: A feed of L2 transactions which are submitted by the sequencer to L1 in batches. Includes L2 tx calldata, *as well as time and ordering information.* - **L2 Block Feed**: A feed of canonical L2 block inputs (i.e. L2 blocks, but without the `stateRoot`, `receiptsRoot`, `gasUsed`, ...) which should be executed by L2 nodes and enforced in fraud proofs. - - ***The L2 Block Feed is a pure function of the Deposit Feed and Sequencer Feed.*** That is, given the Deposit Feed and Sequencer Feed, the L2 Block Feed can be reconstructed, even without full L1 blockdata. + - ***The L2 Block Feed is a pure function of the Deposit Feed and Sequencer Feed.*** That is, given the Deposit Feed and Sequencer Feed, the L2 Block Feed can be reconstructed, even without full L1 blockdata. - In general, all feeds must enforce that: - All entries are deterministically indexable by off-chain parties. - The fraud proof VM can find any feed entry in a bounded number of steps, such that the off-chain indexing is sufficient to generate a witness for verifing any individual step on-chain. @@ -111,4 +111,4 @@ - Finalizes pre-confirmed sequencer transactions onto L1 - Writes to sequencer feed -[block-gen]: TODOPR \ No newline at end of file +[block-gen]: ./components/rollup_node/block_gen.md \ No newline at end of file From 5b59f98b758e53121ec61be45416e0ada8d4cce6 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Sat, 6 Nov 2021 00:11:37 +0000 Subject: [PATCH 039/585] Edit algorithm for improved clarity --- components/rollup_node/block_gen.md | 59 ++++++++++++++++------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/components/rollup_node/block_gen.md b/components/rollup_node/block_gen.md index bbd7be6e352d..4c197778ac92 100644 --- a/components/rollup_node/block_gen.md +++ b/components/rollup_node/block_gen.md @@ -1,29 +1,31 @@ # Block Generation -The logic which is used to generate the rollup chain from L1. +The logic which is used to generate the rollup chain from an L1 availability layer. ## Glossary -- **Block Inputs**: All information required to generate a full Ethereum block, given the pre-state and previous block. For example, does NOT include a state root for that block's input. -- **Rollup Blockchain**: The rollup blocks generated by performing the rollup's state transition function over all block inputs. For example, DOES include a state root for that block's input. +- **Feed**: An append only list of available data. +- **Deposit Feed**: The feed which consists of deposits, each element in this feed will be used to generate a "deposit block". +- **Sequencer Feed**: The feed which consists of sequencer submitted blocks, each element in this feed will be used to generate a "sequencer block". +- **Rollup Blockchain**: The rollup blocks generated by performing the rollup's state transition function over all inputs sourced from the various feeds. ## Summary The rollup chain can be deterministically generated given an L1 Ethereum chain. The fact that the entire rollup chain can be generated based on L1 blocks is _what makes OE a rollup_. This process can be represented as: -```python -f(l1_blockchain) -> rollup_blockchain +``` +generate_rollup_chain(l1_blockchain) -> rollup_blockchain ``` -In this document we define a block generation function which is designed to be: +In this document we define a block generation function which is designed to: -1. Context independent given a constant sized subset of the L1 chain. +1. Require no state other than what is easily accessible using L1 and L2 execution engine APIs. 2. Support sequencers and sequencer consensus. 3. Resilient sequencer censorship. ## Rollup Epochs -The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers. For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be generated after L1 block number `n` is added to the L1 chain. Epoch contain one to many rollup blocks. +The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers. For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be generated after L1 block number `n` is added to the L1 chain. An epoch contains one to many rollup blocks. ### Types of Blocks within Epochs @@ -32,7 +34,7 @@ Within these epochs, there are two block types: 1. Deposit block 2. Sequencer block -Deposit blocks contain contextual information about L1 such as the block hash. They also contain transactions initiated on L1 by any user or contract. +Deposit blocks contain contextual information about L1 such as the block hash. They also contain transactions initiated on L1 by any user or contract that execute on L2. Sequencer blocks are submitted by the sequencer and target _future_ epochs which satisfy the following two conditions: @@ -53,10 +55,10 @@ The following diagram demonstrates the correspondence between L1 blocks and roll For every L1 block (after the rollup's genesis) an L2 deposit block is created. These deposit blocks contain both a `ContextDeposit` and any number of `UserDeposit`s. Context deposits set contextual information about the latest L1 block (eg. `blockHash` and `timestamp`), and user deposits are L1 user initiated L2 transactions which guarantee liveness of the rollup chain even with a censoring sequencer. -The types of deposit blocks are as follows: +The deposit block types are as follows: ```python -class DepositBlock: +class DepositBlock(Block): deposits: List[Deposit] class Deposit: @@ -93,7 +95,7 @@ Sequencer blocks contain a majority of the transactions submitted to the rollup Sequencer blocks are of the following form: ```python -class SequencerBlock: +class SequencerBlock(Block): target_epoch: uint64 # epoch number that this block is intended for sequencer_suggested_timestamp: uint64 # a timestamp suggested by the sequencer transactions: List[Transaction] # A list of transactions in the block @@ -109,7 +111,7 @@ If any of these checks fail the block must be skipped or ignored. Otherwise, all ## Timestamps in Depth -Time can be manipulated by the sequencer; however, it must stay within reasonable bounds and must be monotonic (ie. can never go backwards). The specific conditions that must be met are: +Time can be set by the sequencer; however, it must stay within reasonable bounds and must be monotonic (ie. can never go backwards). The specific conditions that must be met are: ```python # last_l1_timestamp is the L1 timestamp set during the last ContextDeposit @@ -132,16 +134,21 @@ def timestamp(): ``` -## Epoch Block Input Generation -An epoch's block inputs can be generated using the following function: - -- To generate the blocks in epoch `n`, supply L1 blocks `n - (sequencing_window_size + 1)` through `n`. This function returns a list of all rollup blocks in epoch `n`. We will call this list `epoch_rollup_blocks`. -- The first block input for the epoch is always the deposit block. - - Generate the block input with `generate_deposit_block(l1_blocks[0])` (function defined above). - - Append the deposit block to `epoch_rollup_blocks` -- To generate all of the sequencer blocks, for each block in `l1_blocks`: - - Extract the valid sequencer blocks - - If they are targeting epoch `n`, append the sequencer block to `epoch_rollup_blocks`. -- Return `epoch_rollup_blocks`. - -After having generated each epoch it is possible to stich all epochs together to form the full rollup chain. \ No newline at end of file +## Rollup Epoch Generation + +- To generate the blocks in epoch `n`, query L1 blocks `n - (sequencing_window_size + 1)` through `n`. Store the result in an array `l1_blocks`. +- The first block in the epoch is always the deposit block. + - Generate the deposit block with `generate_deposit_block(l1_blocks[0])` (function defined above). + - Append the deposit block the rollup chain. +- The rest of the blocks in the epoch are sequencer blocks. To generate these sequencer blocks, for each block in `l1_blocks`: + - Extract the sequencer feed elements. + - For each sequencer feed element in the L1 block: + - Assert the target epoch is correct (`target_epoch == n`). If not skip over this feed element. + - If the feed element is targetting the correct epoch, check that the sequencer feed element produces a valid block: + - Assert the sequencer feed element was appended by the current sequencer public key (the current public key may exist in L2 state). + - Assert the `sequencer_suggested_timestamp` is valid (see timestamp section for details) + - Assert all transactions included in the sequencer feed element are valid. + - If all checks pass, append the sequencer block to the rollup chain. Otherwise throw out the invalid feed element. +- At this point we will have appended all rollup blocks in epoch `n` to the rollup chain. + +In order to generate the full rollup chain, repeat this process until `n==latest_l1_block_number` indicating that we have reached the tip of L1. \ No newline at end of file From 1c383cd4535e3ff86a833437853f88006f2e74d4 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Mon, 8 Nov 2021 20:34:23 +0000 Subject: [PATCH 040/585] Add fraud proof VM & program writeup --- .../fraud-proof-vm/fraud_proof_program.md | 43 ++++++++++++++++ components/fraud-proof-vm/fraud_proof_vm.md | 50 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 components/fraud-proof-vm/fraud_proof_program.md create mode 100644 components/fraud-proof-vm/fraud_proof_vm.md diff --git a/components/fraud-proof-vm/fraud_proof_program.md b/components/fraud-proof-vm/fraud_proof_program.md new file mode 100644 index 000000000000..027a1b0a99c6 --- /dev/null +++ b/components/fraud-proof-vm/fraud_proof_program.md @@ -0,0 +1,43 @@ +# Fraud Proof Program + +The fraud proof program is the specific program which is run on a [fraud proof VM](./fraud_proof_vm.md) during a dispute. This program is designed to evaluate any subset of the Optimistic Ethereum chain. + +## Initialization + +The OE fraud proof program is used to weed out invalid block hash assertions in the `Block Hash Oracle`. The fraud proof program is initialized using values which are recorded at the time of block hash assertions. This is all handled within the `AssertionManager` contract. + +Every time an L2 block hash is asserted using the `AssertionManager`, the following information is hashed together and recorded: + +- Latest L1 block hash at the time of assertion. +- Asserted next L2 block hash. +- The previous assertion this assertion builds upon. +- Epoch number of the L2 block hash. + +The fraud proof program takes in as input the hash of all these values. + +## Execution + +The fraud proof program is designed to execute the full state transition between any two epochs. The epochs used for a dispute are the previous assertion epoch & the new assertion epoch number in the `AssertionManager`. The fraud proof program will execute the state transition between these epochs and determine the final epoch block hash (ie. the one valid assertion). If the asserted L2 block hash is deemed incorrect over the course of a dispute game, the `AssertionManager` will delete the invalid assertion and forfeit the asserter's bond. + +In practice, the fraud proof program is broken up into two separate processes: + +1. Block generation +2. Block processing + +We split the program into these two distinct parts to isolate the complexity of block processing. This way if there is an error which causes a single block to fail (see [this discussion](https://github.com/ethereum-optimism/optimistic-specs/discussions/22) for details), it does not break the entire assertion game. While the block processing may fail, it is critically important that the block generation process never fails. + +### Block Generation + +The fraud proof program starts out running the block generation process. Block generation uses the same algorithm which is laid out in the [block generation document](../rollup_node/block_gen.md). However, it is worth highlighting: + +1. In the FPVM, all chain data is queried using the preimage oracle. The program will use the L1 block hash at the time of assertion to search backwards on L1 to find all information required for block generation. This can be done by recursively calling `get_preimage(block.previous_block_hash)` until all required block information is loaded into the FPVM memory. +2. The block generation document outlines the process to generate a single epoch. For the purposes of this fraud proof program we will need to generate **all** epochs between the previous assertion and the next assertion. +3. The final step in the block generation algorithm where blocks are **processed** is **not** handled in this top level program. Instead a sub-process is spawned to execute that single block. + +### Block Processing + +For every block which needs to be processed in the block generation algorithm, a sub-process is spawned. This process accepts the block inputs and returns the `block hash` computed by executing the block inputs. The specifics of the block processing algorithm is laid out in the [block processing document] [TODO]. + +## Termination + +Once the fraud proof program has generated and processed all blocks between the last asserted L2 block hash and the newly asserted L2 block hash, it will return the **valid** L2 block hash that should have been asserted. In the proposal manager it will compare the value returned by the fraud proof with the value asserted, and if it is incorrect delete the invalid assertion and slash the asserter's bond. \ No newline at end of file diff --git a/components/fraud-proof-vm/fraud_proof_vm.md b/components/fraud-proof-vm/fraud_proof_vm.md new file mode 100644 index 000000000000..a4ff7529efc7 --- /dev/null +++ b/components/fraud-proof-vm/fraud_proof_vm.md @@ -0,0 +1,50 @@ +# Fraud Proof VM + +A fraud proof VM (FPVM) is a virtual machine which can be evaluated on-chain to settle a disputed block hash assertion. In this spec we assume the fraud proof VM is evaluated using a multi-round dispute game similar to [Truebit](https://people.cs.uchicago.edu/~teutsch/papers/truebit.pdf). + +## Key Properties + +A Fraud proof VM must satisfy the following properties to be suitable for a multi-round dispute game: +1. Program execution can be split up into deterministic state transitions. +2. Each state transition can be evaluated on-chain with less than or equal to a constant size gas allocation (eg. 10 million L1 gas). +3. The FPVM must be executable off-chain in such a way that state checkpoints (ie. merklized commitments to the VM state) can be generated. + +## Usage + +### Initialization + +The fraud proof VM is initialized with: +1. an executable binary; and +2. an initialization hash for the preimage oracle. + +The executable binary defines the program which is executed during a fraud proof, and the initialization hash is used to load data from the FPVM's database called the `Preimage Oracle`. + + +The fraud proof VM does not have access to a traditional database. Instead, it has access to the "preimage oracle". The preimage oracle is simply a database which exposes the function `get_preimage(hash: bytes)`: + +```python +def get_preimage(hash: bytes) -> bytes: + # The preimage is looked up from a local database held by the fraud prover + preimage = fetch_preimage(hash) + assert keccak256(preimage) == hash + return preimage +``` + +The preimage oracle must be populated with all `hash->preimage` mappings before they are queried by the FPVM. These preimages are committed to in the initialization hash which is supplied as one of the two inputs to the FPVM. During the course of execution, the FPVM must **never** request a preimage which is unavailable as that would result in the FPVM being indeterminate. In this way, a valid executable binary must account for the structure of the initialization hash and only query available preimages. + +### Termination + +The fraud proof VM must terminate with either: + +1. SUCCESS +2. FAIL +3. INDETERMINATE + +If the FPVM returns SUCCESS it may also return a 32 byte value (eg. the valid block hash). If the FPVM returns FAIL it must be handled by the dispute game. + +There are a few conditions under which the FPVM may return FAIL: + +1. Out of memory -- Too much memory was used during execution. +2. Too many instructions -- Too many instructions were consumed (there is a fixed max instructions to prevent DOS attacks on the FPVM). + +The only time in which the FPVM returns INDETERMINATE is when an unavailable preimage is queried. \ No newline at end of file From a205b36e1c0036062b21c0535e12cadb279574ca Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Tue, 16 Nov 2021 21:06:58 -0600 Subject: [PATCH 041/585] Update roadmap progress bars (#36) --- assets/roadmap.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/roadmap.svg b/assets/roadmap.svg index 02d69f0a1395..a5022a03311e 100644 --- a/assets/roadmap.svg +++ b/assets/roadmap.svg @@ -1,4 +1,4 @@ -
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
Rollup Node
Feed Contracts
Feed Contracts
Execution Engine
Execution Engine
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Contracts
Rollup Cont...
v0.5 Stability Infrastructure
v0.5 Stability Infrastructure
Rollup Client
Rollup Clie...
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
Dispute Game
Dispute Game
L2 State Oracle
L2 State Oracle
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof VM Audits
Fraud Proof VM Audits
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Decentralized Sequencer consensus
Decentralized Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Fraud Proof VM Optimization
Fraud Proof VM Optimization
Dispute Game Audits & Proofs
Dispute Game Audits & Proofs
v1.0 Spec
(Executable)
v1.0 Spec...
Geth Optimizations
(eg. EVM Parallelism)
Geth Optimizations...
State Expiry
State Expiry
Begin v2 Scalability Research
Begin v2 Sc...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
Rollup Node
Feed Contracts
Feed Contracts
Execution Engine
Execution Engine
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Contracts
Rollup Contr...
v0.5 Stability Infrastructure
v0.5 Stability Infrastructure
Rollup Client
Rollup Client
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
Dispute Game
Dispute Game
L2 State Oracle
L2 State Oracle
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof VM Audits
Fraud Proof VM Audits
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Decentralized Sequencer consensus
Decentralized Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Fraud Proof VM Optimization
Fraud Proof VM Optimization
Dispute Game Audits & Proofs
Dispute Game Audits & Proofs
v1.0 Spec
(Executable)
v1.0 Spec...
Geth Optimizations
(eg. EVM Parallelism)
Geth Optimizations...
State Expiry
State Expiry
Begin v2 Scalability Research
Begin v2 Sc...
Viewer does not support full SVG 1.1
\ No newline at end of file From fb99795cb716ac8752b550880481db9136d02e9e Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 17 Nov 2021 10:03:03 -0600 Subject: [PATCH 042/585] Use better words (#37) * Use 'Block Derivation' rather than 'Block Generation' * Use 'L2 State Oracle' instead of 'L2 Block Hash Oracle' --- assets/architecture.svg | 2 +- ...cer-handling-deposits-and-transactions.svg | 2 +- assets/user-withdrawing-to-l1.svg | 2 +- assets/verifier-executing-fraud-proof.svg | 2 +- components/rollup_node/README.md | 8 ++-- .../{block_gen.md => block_derivation.md} | 38 +++++++++---------- components/rollup_node/exec_engine.md | 2 +- components/rollup_node/rollup_driver.md | 10 ++--- introduction.md | 10 ++--- layer-1-contracts/README.md | 2 +- overview.md | 6 +-- 11 files changed, 42 insertions(+), 42 deletions(-) rename components/rollup_node/{block_gen.md => block_derivation.md} (73%) diff --git a/assets/architecture.svg b/assets/architecture.svg index 247e80d5a5bf..3d8af1053fcd 100644 --- a/assets/architecture.svg +++ b/assets/architecture.svg @@ -1,4 +1,4 @@ -
L1
L1
L2
L2
reads
(withdrawals)
reads...
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
gets proofs
gets proofs
Challenger Agent
Challenger Agent
canonical L2 state
canonical L2 state
Witness Generator
Witness Generator
reads canonical
block inputs
reads canonical...
canonical L1
consensus
canonical L1...
Rollup Driver
Rollup Driver
submits
pending
blocks
submits...
reads pending
blocks
reads pending...
Batch Submitter
Batch Submi...
Execution Engine
Execution Engine
L2 Block Oracle
L2 Block Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
writes pending
blocks
writes pending...
reads
pending
deposits
reads...
Block Producer
Block Produ...
pending
sequencer
blocks
pending...
Sequencer Replicator
Sequencer R...
Node TypeSequencerVerifier
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L2 Block Feed
L2 Bloc...
+
+
=
=
Viewer does not support full SVG 1.1
\ No newline at end of file +
L1
L1
L2
L2
reads
(withdrawals)
reads...
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
gets proofs
gets proofs
Challenger Agent
Challenger Agent
canonical L2 state
canonical L2 state
Witness Generator
Witness Generator
reads canonical
block inputs
reads canonical...
canonical L1
consensus
canonical L1...
Rollup Driver
Rollup Driver
submits
pending
blocks
submits...
reads pending
blocks
reads pending...
Batch Submitter
Batch Submi...
Execution Engine
Execution Engine
L2 State Oracle
L2 State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
writes pending
blocks
writes pending...
reads
pending
deposits
reads...
Block Producer
Block Produ...
pending
sequencer
blocks
pending...
Sequencer Replicator
Sequencer R...
Node TypeSequencerVerifier
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L2 Block Feed
L2 Bloc...
+
+
=
=
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/sequencer-handling-deposits-and-transactions.svg b/assets/sequencer-handling-deposits-and-transactions.svg index 924cffb5be43..f2c90407e73c 100644 --- a/assets/sequencer-handling-deposits-and-transactions.svg +++ b/assets/sequencer-handling-deposits-and-transactions.svg @@ -1,4 +1,4 @@ -
3. Insert deposit block
3. Insert deposit block
Rollup Node
Rollup Node
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to sequencer feed
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the sequencer feed.
Queries for all...
Sequencer Feed
Sequencer Feed

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
Block Hash
Assertion Submitter
Block Hash...
Queries for the next
assertable block hash
& submits it to the
assertion manager.
Queries for the next...
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Viewer does not support full SVG 1.1
\ No newline at end of file +
3. Insert deposit block
3. Insert deposit block
Rollup Node
Rollup Node
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to sequencer feed
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the sequencer feed.
Queries for all...
Sequencer Feed
Sequencer Feed

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
Block Hash
Assertion Submitter
Block Hash...
Queries for the next
assertable block hash
& submits it to the
assertion manager.
Queries for the next...
L2 State Oracle
L2 State Oracle
Assertion Manager
Assertion...
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/user-withdrawing-to-l1.svg b/assets/user-withdrawing-to-l1.svg index ebc9a4540890..259e1ecd8716 100644 --- a/assets/user-withdrawing-to-l1.svg +++ b/assets/user-withdrawing-to-l1.svg @@ -1,4 +1,4 @@ -
Ethereum L1 Chain
Ethereum L1 Chain
Sequencer Feed
Sequencer Feed

User Withdrawing to Layer 1

User Withdrawing to Layer 1
L2 Block Hash Oracle
L2 Block Hash Oracle
Assertion Manager
Assertion...
3. Assert block hash
containing withdrawal
commitment
3. Assert block hash...
2. Post batch
with withdrawal
transaction data
2. Post batch...
1. Send
initiate
withdrawal

transaction
1. Send...
5. Send
execute
withdrawal

transaction
5. Send...
4. Wait for block
hash to finalize
4. Wait for block...
User
User
ERC20
ERC20
6. Verify
withdrawal
in finalized
block hash
6. Verify...
7.
Transfer
tokens
7....
Bridge
Bridge
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file +
Ethereum L1 Chain
Ethereum L1 Chain
Sequencer Feed
Sequencer Feed

User Withdrawing to Layer 1

User Withdrawing to Layer 1
L2 State Oracle
L2 State Oracle
Assertion Manager
Assertion...
3. Assert block hash
containing withdrawal
commitment
3. Assert block hash...
2. Post batch
with withdrawal
transaction data
2. Post batch...
1. Send
initiate
withdrawal

transaction
1. Send...
5. Send
execute
withdrawal

transaction
5. Send...
4. Wait for block
hash to finalize
4. Wait for block...
User
User
ERC20
ERC20
6. Verify
withdrawal
in finalized
block hash
6. Verify...
7.
Transfer
tokens
7....
Bridge
Bridge
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/verifier-executing-fraud-proof.svg b/assets/verifier-executing-fraud-proof.svg index e3dd824cfa66..2f40a7869f6c 100644 --- a/assets/verifier-executing-fraud-proof.svg +++ b/assets/verifier-executing-fraud-proof.svg @@ -1,4 +1,4 @@ -
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Node
Rollup Node
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 Block Hash Oracle Contract
L2 Block Hash Oracle Contract
Assertion Manager
Assertion...
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Viewer does not support full SVG 1.1
\ No newline at end of file +
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Node
Rollup Node
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 State Oracle Contract
L2 State Oracle Contract
Assertion Manager
Assertion...
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md index 43fb567bbd7d..de6dbd5c6d10 100644 --- a/components/rollup_node/README.md +++ b/components/rollup_node/README.md @@ -4,7 +4,7 @@ The consensus module of Optimistic Ethereum. ## Summary -The Rollup Node is a consensus client that determines the latest state of the rollup. It reads state from L1, and possibly the sequencer, to compute the L2 state. The [block generation spec][block-gen] defines the rules by which L1 state is converted into L2 blocks. +The Rollup Node is a consensus client that determines the latest state of the rollup. It reads state from L1, and possibly the sequencer, to compute the L2 state. The [block derivation spec][block-derivation] defines the rules by which L1 state is converted into L2 blocks. ## Types of Rollup Nodes There are two primary classes of rollup nodes, corresponding to different configurations of the software stack. @@ -30,7 +30,7 @@ One of the main goal of the rollup client is to use the execution engine without ### [Rollup Driver][rollup-driver] -The rollup driver connects to an L1 node, and tracks the feed data comprising of deposits and sequencer batches. Based on the rules of [block generation][block-gen], it is able to compute sets ("epochs") of L2 blocks as a stateless, pure function of ranges of L1 blocks. +The rollup driver connects to an L1 node, and tracks the feed data comprising of deposits and sequencer batches. Based on the rules of [block derivation][block-derivation], it is able to compute sets ("epochs") of L2 blocks as a stateless, pure function of ranges of L1 blocks. While connected to the Execution Engine, it uses the Engine API to progress the L2 state as new data comes in from L1. The rollup driver will reorganize the L2 state if it detects a difference between the EE and what's on L1, and provides a way for other services to subscribe to reorgs. @@ -48,13 +48,13 @@ The block producer service is run by the sequencer to progress the L2 state in a The batch submitter takes the pending blocks which have been inserted into the sequencer's L2 state by the block producer, and sends corresponding transactions in batches to L1. -The batch submitter encodes these transactions based on the rules of [block generation][block-gen], effectively as the reverse of the process carried out by the rollup driver. As a result: +The batch submitter encodes these transactions based on the rules of [block derivation][block-derivation], effectively as the reverse of the process carried out by the rollup driver. As a result: - Blocks previously inserted by the Block Producer into the Sequencer's EE will now appear in L1 Verifiers' EEs. - Blocks marked as sequencer-confirmed in both the Sequencer and in Replicating verifiers will now be marked as L1-confirmed. [execution-spec]: https://github.com/ethereum/execution-specs [execution-engine-rpc]: https://hackmd.io/@n0ble/consensus_api_design_space -[block-gen]: ./components/rollup_node/block_gen.md +[block-derivation]: ./components/rollup_node/block_derivation.md [exec-engine]: ./exec_engine.md [rollup-driver]: ./consensus_layer.md [sequencer-replicator]: ./sequencer_replicator.md diff --git a/components/rollup_node/block_gen.md b/components/rollup_node/block_derivation.md similarity index 73% rename from components/rollup_node/block_gen.md rename to components/rollup_node/block_derivation.md index 4c197778ac92..63d71bcd03fc 100644 --- a/components/rollup_node/block_gen.md +++ b/components/rollup_node/block_derivation.md @@ -1,23 +1,23 @@ -# Block Generation +# Block derivation -The logic which is used to generate the rollup chain from an L1 availability layer. +The logic which is used to derive the rollup chain from an L1 availability layer. ## Glossary - **Feed**: An append only list of available data. -- **Deposit Feed**: The feed which consists of deposits, each element in this feed will be used to generate a "deposit block". -- **Sequencer Feed**: The feed which consists of sequencer submitted blocks, each element in this feed will be used to generate a "sequencer block". -- **Rollup Blockchain**: The rollup blocks generated by performing the rollup's state transition function over all inputs sourced from the various feeds. +- **Deposit Feed**: The feed which consists of deposits, each element in this feed will be used to derive a "deposit block". +- **Sequencer Feed**: The feed which consists of sequencer submitted blocks, each element in this feed will be used to derive a "sequencer block". +- **Rollup Blockchain**: The rollup blocks derived by performing the rollup's state transition function over all inputs sourced from the various feeds. ## Summary -The rollup chain can be deterministically generated given an L1 Ethereum chain. The fact that the entire rollup chain can be generated based on L1 blocks is _what makes OE a rollup_. This process can be represented as: +The rollup chain can be deterministically derived given an L1 Ethereum chain. The fact that the entire rollup chain can be derived based on L1 blocks is _what makes OE a rollup_. This process can be represented as: ``` -generate_rollup_chain(l1_blockchain) -> rollup_blockchain +derive_rollup_chain(l1_blockchain) -> rollup_blockchain ``` -In this document we define a block generation function which is designed to: +In this document we define a block derivation function which is designed to: 1. Require no state other than what is easily accessible using L1 and L2 execution engine APIs. 2. Support sequencers and sequencer consensus. @@ -25,7 +25,7 @@ In this document we define a block generation function which is designed to: ## Rollup Epochs -The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers. For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be generated after L1 block number `n` is added to the L1 chain. An epoch contains one to many rollup blocks. +The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers. For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be derived after L1 block number `n` is added to the L1 chain. An epoch contains one to many rollup blocks. ### Types of Blocks within Epochs @@ -45,11 +45,11 @@ The ability for the sequencer to append sequencer blocks to future epochs allows ### Epoch Structure -Each epoch contains **1** deposit block and zero to many sequencer blocks. For epoch `n` the deposit block is generated using L1 block number `n - (sequencing_window_size + 1)`. The epoch's sequencer blocks are contained in any of the L1 blocks ranging from `n - sequencing_window_size` to `n`. This a range of blocks is called the "sequencing window". +Each epoch contains **1** deposit block and zero to many sequencer blocks. For epoch `n` the deposit block is derived using L1 block number `n - (sequencing_window_size + 1)`. The epoch's sequencer blocks are contained in any of the L1 blocks ranging from `n - sequencing_window_size` to `n`. This a range of blocks is called the "sequencing window". The following diagram demonstrates the correspondence between L1 blocks and rollup blocks (ie L2 blocks): -![Sequencer block generation diagram](../../assets/sequencer-block-gen.svg) +![Sequencer block derivation diagram](../../assets/sequencer-block-derivation.svg) ## Deposit Blocks in Depth @@ -78,13 +78,13 @@ class ContextDeposit(Deposit): baseFee: uint64 ``` -### Deposit Block Generation +### Deposit Block derivation -The function `generate_deposit_block(l1_block_number)` is defined as: +The function `derive_deposit_block(l1_block_number)` is defined as: -- Generate the `ContextDeposit` using the L1 block body. Specifically the L1 block's `blockHash`, `blockNumber`, `timestamp`, and `baseFee`. +- Derive the `ContextDeposit` using the L1 block body. Specifically the L1 block's `blockHash`, `blockNumber`, `timestamp`, and `baseFee`. - Get all events emitted by the `DepositFeed` contract at block `l1_block_number`. - - For each event, generate a new `UserDeposit` based on the emitted calldata. All fields should be emitted by DepositFeed contract. + - For each event, derive a new `UserDeposit` based on the emitted calldata. All fields should be emitted by DepositFeed contract. #### **Footnote**: The DepositFeed ensures that no matter the size of the event it is possible to prove the deposit data to the fraud proof. See the DepositFeed spec for details. @@ -136,11 +136,11 @@ def timestamp(): ## Rollup Epoch Generation -- To generate the blocks in epoch `n`, query L1 blocks `n - (sequencing_window_size + 1)` through `n`. Store the result in an array `l1_blocks`. +- To derive the blocks in epoch `n`, query L1 blocks `n - (sequencing_window_size + 1)` through `n`. Store the result in an array `l1_blocks`. - The first block in the epoch is always the deposit block. - - Generate the deposit block with `generate_deposit_block(l1_blocks[0])` (function defined above). + - Derive the deposit block with `derive_deposit_block(l1_blocks[0])` (function defined above). - Append the deposit block the rollup chain. -- The rest of the blocks in the epoch are sequencer blocks. To generate these sequencer blocks, for each block in `l1_blocks`: +- The rest of the blocks in the epoch are sequencer blocks. To derive these sequencer blocks, for each block in `l1_blocks`: - Extract the sequencer feed elements. - For each sequencer feed element in the L1 block: - Assert the target epoch is correct (`target_epoch == n`). If not skip over this feed element. @@ -151,4 +151,4 @@ def timestamp(): - If all checks pass, append the sequencer block to the rollup chain. Otherwise throw out the invalid feed element. - At this point we will have appended all rollup blocks in epoch `n` to the rollup chain. -In order to generate the full rollup chain, repeat this process until `n==latest_l1_block_number` indicating that we have reached the tip of L1. \ No newline at end of file +In order to derive the full rollup chain, repeat this process until `n==latest_l1_block_number` indicating that we have reached the tip of L1. \ No newline at end of file diff --git a/components/rollup_node/exec_engine.md b/components/rollup_node/exec_engine.md index a3bdd4db8bdc..63a2221a97d8 100644 --- a/components/rollup_node/exec_engine.md +++ b/components/rollup_node/exec_engine.md @@ -2,7 +2,7 @@ ## Overview -The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal Eth2, the consensus node sends execution payloads (essentially eth1 blocks, without proof of work) from the beacon chain into the engine. In Optimistic Ethereum, the Rollup Driver (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically generated from L1 into the engine. +The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal Eth2, the consensus node sends execution payloads (essentially eth1 blocks, without proof of work) from the beacon chain into the engine. In Optimistic Ethereum, the Rollup Driver (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically derived from L1 into the engine. ## Differences between L1 and L2 EE diff --git a/components/rollup_node/rollup_driver.md b/components/rollup_node/rollup_driver.md index 057bf2f9ceb5..79ceff1b5563 100644 --- a/components/rollup_node/rollup_driver.md +++ b/components/rollup_node/rollup_driver.md @@ -1,8 +1,8 @@ # Rollup Driver -The Rollup Driver is the core code which guarantees that the canonical L1 state is accurately reflected in the EE. It does this by connecting to an L1 node, and using the pure function which maps L1 blocks to L2 block inputs as defined by [block generation][block-gen]. Once it knows the block inputs, it checks the EE to make sure that the blocks there all have the correct inputs. +The Rollup Driver is the core code which guarantees that the canonical L1 state is accurately reflected in the EE. It does this by connecting to an L1 node, and using the pure function which maps L1 blocks to L2 block inputs as defined by [block derivation][block-derivation]. Once it knows the block inputs, it checks the EE to make sure that the blocks there all have the correct inputs. -This is a functionality that is shared between all configurations of the rollup node, including the sequencer. Because block generation defines the L1 block -> L2 block input transformation as a pure function, it can be completely stateless and has no DB. +This is a functionality that is shared between all configurations of the rollup node, including the sequencer. Because block derivation defines the L1 block -> L2 block input transformation as a pure function, it can be completely stateless and has no DB. ## Basic Functionality @@ -17,11 +17,11 @@ The core logic which the CL executes is as follows. - Iterate backwards until we find the latest L2 block whose `l1BlockNumber` and `l1BlockHash` DO match the L1 node RPC. - Set the EE's head to this L2 block (thereby updating `latestL1ConfirmedL2Block`). 2. Iterate forward through L1 blocks, starting from `latestL1ConfirmedL2Block.l1BlockNumber + 1`. For each: - - Generate the L2 block inputs for this L1 block as defined by [block generation][block-gen]. For each L2 block input: + - Derive the L2 block inputs for this L1 block as defined by [block derivation][block-derivation]. For each L2 block input: - If the L2 block DOES NOT exist in the EE already, insert it and update the EE head. - - If the L2 block DOES exist in the EE already (as sequencer confirmed), then compare the generated block input to the existing block input. + - If the L2 block DOES exist in the EE already (as sequencer confirmed), then compare the derived block input to the existing block input. - If they DO match, mark the L2 block as L1 confirmed. - If they DO NOT match, there has been an L2 reorg. Signal the reorg, insert the correct block, and update the EE head. 3. Wait and GOTO 1. -[block-gen]: ./components/rollup_node/block_gen.md \ No newline at end of file +[block-derivation]: ./components/rollup_node/block_derivation.md \ No newline at end of file diff --git a/introduction.md b/introduction.md index ab72b7ffd3ef..a9f75267a63f 100644 --- a/introduction.md +++ b/introduction.md @@ -37,9 +37,9 @@ In order to scale Ethereum without sacrificing security, we must preserve 3 crit 1. **Liveness** - Anyone must be able to extend the rollup chain by sending transactions at any time. - There are two ways transactions can be sent to the rollup chain: 1) via the sequencer, and 2) directly on layer 1. The sequencer provides low latency & low cost transactions, while sending transactions directly to layer 1 provides censorship resistance. 2. **Availability** - Anyone must be able to download the rollup chain. - - All information required to generate the chain is embedded into layer 1 blocks. That way as long as the layer 1 chain is available, so is the rollup. + - All information required to derive the chain is embedded into layer 1 blocks. That way as long as the layer 1 chain is available, so is the rollup. 3. **Validity** - All transactions must be correctly executed and all withdrawals correctly processed. - - The rollup state and withdrawals are managed on an L1 contract called the `Block Hash Oracle`. This oracle is guaranteed to _only_ finalize correct (ie. valid) rollup block hashes given a **single honest verifier** assumption. If there is ever an invalid block hash asserted on layer 1, an honest verifier will prove it is invalid and win a bond. + - The rollup state and withdrawals are managed on an L1 contract called the `L2 State Oracle`. This oracle is guaranteed to _only_ finalize correct (ie. valid) rollup block hashes given a **single honest verifier** assumption. If there is ever an invalid block hash asserted on layer 1, an honest verifier will prove it is invalid and win a bond. **Footnote**: There are two main ways to enforce validity of a rollup: fraud proofs (optimistic rollup) and validity proofs (zkRollup). For the purposes of this spec we only focus on fraud proofs but it is worth noting that validity proofs can also be plugged in once they have been made feasible. @@ -96,7 +96,7 @@ Links to components mentioned in this diagram: - Rollup Node (WIP) - Execution Engine (WIP) - Sequencer Batch Submitter (WIP) -- L2 Block Hash Oracle (WIP) +- L2 State Oracle (WIP) - Block Hash Assertion Submitter (WIP) - Fraud Proof VM (WIP) @@ -109,7 +109,7 @@ Just as important as depositing, it is critical that users can withdraw from the Links to components mentioned in this diagram: - Rollup Feeds (WIP) -- Block Hash Oracle (WIP) +- L2 State Oracle (WIP) - Bridge (WIP) @@ -123,7 +123,7 @@ Links to components mentioned in this diagram: - Rollup Node (WIP) - Execution Engine (WIP) -- L2 Block Hash Oracle (WIP) +- L2 State Oracle (WIP) - Challenger Agent (WIP) - Fraud Proof VM (WIP) diff --git a/layer-1-contracts/README.md b/layer-1-contracts/README.md index 1f09ece995d4..a112044a8614 100644 --- a/layer-1-contracts/README.md +++ b/layer-1-contracts/README.md @@ -5,7 +5,7 @@ We want our ORU contracts to be built in compliance with the following goals: - A **pluggable state machine** which: - allows separation of concerns and parallelizable work - is fully stateless, i.e. all state transitions can be expressed in the form `bytes32 _inputHash, bytes _witness => bytes32 _outputhash` and are only dependent on the immediately preceding pre-state -- A cryptoeconomic **L2 Block Oracle** which: +- A cryptoeconomic **L2 State Oracle** which: - Provides a cryptoeconomic mechanism to propose, assert, challenge, and finalize optimistic states of the L2 machine - Does NOT require that the entire execution trace is provable, just the execution output - i.e. an honest party may not necessarily ever post a hash of the full trace diff --git a/overview.md b/overview.md index dc3808c41c55..55b9cf7507d8 100644 --- a/overview.md +++ b/overview.md @@ -28,7 +28,7 @@ ![Architecture Diagram](./assets/architecture.svg) ### L1 Components -- **Feeds**: ("Data availability layer"): A **feed** is an append-only log of data (e.g. of deposits, or sequencer batches). Feeds can be computed as functions of L1 block data. The definition of these functions can be found in the [block generation spec][block-gen]. Optimistic Ethereum has three primary feeds: +- **Feeds**: ("Data availability layer"): A **feed** is an append-only log of data (e.g. of deposits, or sequencer batches). Feeds can be computed as functions of L1 block data. The definition of these functions can be found in the [block derivation spec][block-derivation]. Optimistic Ethereum has three primary feeds: - **Deposit Feed**: A feed of L2 transactions which originated as smart contract calls in the L1 state which emitted an event. Deposits are guaranteed to be reflected in the L2 state within the *sequencing window*. - **Sequencer Feed**: A feed of L2 transactions which are submitted by the sequencer to L1 in batches. Includes L2 tx calldata, *as well as time and ordering information.* - **L2 Block Feed**: A feed of canonical L2 block inputs (i.e. L2 blocks, but without the `stateRoot`, `receiptsRoot`, `gasUsed`, ...) which should be executed by L2 nodes and enforced in fraud proofs. @@ -37,7 +37,7 @@ - All entries are deterministically indexable by off-chain parties. - The fraud proof VM can find any feed entry in a bounded number of steps, such that the off-chain indexing is sufficient to generate a witness for verifing any individual step on-chain. - Note: a "feed" may not necessarily correspond to an on-chain contract (e.g. which stores a hash of each entry). Instead, a feed refers to the actual log of data which is derivable from L1, which may or may not use a contract. For more info, check out [this discussion.](https://github.com/ethereum-optimism/optimistic-specs/issues/14) -- **L2 Block Oracle**: A cryptoeconomic light client of the L2. Will finalize hashes of the L2 state on L1, once the dispute period has passed. Used to validate withdrawals. *(Note: contract separation is not yet final)* +- **L2 State Oracle**: A cryptoeconomic light client of the L2. Will finalize hashes of the L2 state on L1, once the dispute period has passed. Used to validate withdrawals. *(Note: contract separation is not yet final)* - **Proposal Manager**: Handles conflicting state proposals to determine malicious party - Maintains a set of ongoing optimistic proposals of the L2 state - Ensures that state proposers are sufficiently bonded @@ -111,4 +111,4 @@ - Finalizes pre-confirmed sequencer transactions onto L1 - Writes to sequencer feed -[block-gen]: ./components/rollup_node/block_gen.md \ No newline at end of file +[block-derivation]: ./components/rollup_node/block_derivation.md \ No newline at end of file From 64ceee87f0e22c07269974c3a1b8780ef503dac9 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 16 Nov 2021 18:54:41 -0600 Subject: [PATCH 043/585] Add glossary --- components/rollup_node/block_derivation.md | 7 -- glossary.md | 89 ++++++++++++++++++++++ 2 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 glossary.md diff --git a/components/rollup_node/block_derivation.md b/components/rollup_node/block_derivation.md index 63d71bcd03fc..1ec72676d3db 100644 --- a/components/rollup_node/block_derivation.md +++ b/components/rollup_node/block_derivation.md @@ -2,13 +2,6 @@ The logic which is used to derive the rollup chain from an L1 availability layer. -## Glossary - -- **Feed**: An append only list of available data. -- **Deposit Feed**: The feed which consists of deposits, each element in this feed will be used to derive a "deposit block". -- **Sequencer Feed**: The feed which consists of sequencer submitted blocks, each element in this feed will be used to derive a "sequencer block". -- **Rollup Blockchain**: The rollup blocks derived by performing the rollup's state transition function over all inputs sourced from the various feeds. - ## Summary The rollup chain can be deterministically derived given an L1 Ethereum chain. The fact that the entire rollup chain can be derived based on L1 blocks is _what makes OE a rollup_. This process can be represented as: diff --git a/glossary.md b/glossary.md new file mode 100644 index 000000000000..8b802d0ce34d --- /dev/null +++ b/glossary.md @@ -0,0 +1,89 @@ +# Glossary of Optimistic Ethereum Terms + +### Layer 1 (L1) + +The Ethereum Mainnet. + +### Layer 2 (L2) + +The Optimistic Ethereum Network. + +### State Root Oracle + +A smart contract on L1, providing access to historical L1 block hashes. The existence of this contract makes it possible to prove the existence of a particular L2 state root within a previous L1 block. + +### Block Generation (AKA Block Derivation) + +All of the data necessary to reconstruct the history and state of L2 is contained within L1 blocks. Block Generation is the process of converting data contained in L1 blocks into L2 blocks. + +### Epoch + +A continuous sequence of 0 or more L2 blocks. There is a one to one correspondence between L2 Epochs, and L1 blocks. + +**Example usage:** "Epoch 20 corresponds to L1 block 637, epoch 21 corresponds to block 638, etc". + +### Feeds + +Feeds are append only lists, each of which is contained in a smart contract on Layer 1. The state of the Rollup Chain is determined by the data written to these contracts. + +### Sequencer Feed + +The Sequencer Feed is a contract which contains the data representing sequencer submitted blocks, each element in this feed will be used to generate a "sequencer block". + +### Deposit Feed + +The Deposit Feed is a contract which contains deposit data. Each element in this feed will be used to generate a "deposit block". + +### Sequencing Window + +The number of L1 blocks during which the Sequencer _may_ insert Sequencer blocks before a Deposit block. + +If the Sequencer Window is 2 blocks, and Alice makes a Deposit in Block 420, her deposit WILL be included (by the Block Generation process) at block 422. + +### Execution Environment (EE) + +The virtual machine in which transactions are applied to the pre-state to generate the post-state. + +### Rollup Node AKA Rollup Driver + +The core client software which reads data from an L1 node, and transforms it into L2 data. Both the Sequencer, and Verifier nodes run a Rollup Node, albeit in different configurations. + +### Consensus Layer + +By analogy to the architecture of ETH2 we can also describe Layer 1 as the "Consensus Layer", as it defines the canonical history and state of the Layer 2 chain. + +### Sequencer + +The privileged entity which accepts L2 transactions from users, and determines the ordering of those transactions with respect to each other and deposit transactions. + + +### Verifier + +A verifier is any Rollup Node operator who is not the Sequencer. Verifiers compute the state of the L2 chain, and compare it to the states proposed by the Sequencer. + +### Deposit transaction (via the Deposit Feed) + +A transaction which originates on L1, by way of a message sent to the Deposit Feed contract. This message can be sent either by a contract or an externally owned account. + +### Sequencer transaction (via the Sequencer feed) + +A transaction which is sent directly to the sequencer from user. + +### L2 State Oracle (AKA L2 Block Oracle) + +The on-chain component to which the Sequencer writes the L2 state roots. +The L2 State oracle also implements the k-section game, and single step verifier. + +### Single Step Verifier + +An on-chain + +### Dispute game + +The Dispute Game is the process by which a verifier + + +### Preimage +### Pure function + + From 6d517595ce0d40d427ecaea8b41b01c4a64e9adc Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 19 Nov 2021 13:40:14 -0600 Subject: [PATCH 044/585] Update glossary.md Co-authored-by: Mark Tyneway --- glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary.md b/glossary.md index 8b802d0ce34d..002e28c23223 100644 --- a/glossary.md +++ b/glossary.md @@ -2,7 +2,7 @@ ### Layer 1 (L1) -The Ethereum Mainnet. +An Ethereum network with its own native security mechanism (ie. proof of work, proof of stake or proof of authority). ### Layer 2 (L2) From 59788153e967fc0d5ced53a71c4a9c7525bbd312 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 19 Nov 2021 13:40:30 -0600 Subject: [PATCH 045/585] Update glossary.md Co-authored-by: Mark Tyneway --- glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary.md b/glossary.md index 002e28c23223..812313674287 100644 --- a/glossary.md +++ b/glossary.md @@ -6,7 +6,7 @@ An Ethereum network with its own native security mechanism (ie. proof of work, p ### Layer 2 (L2) -The Optimistic Ethereum Network. +A network that derives its security from a layer one. ### State Root Oracle From 1877c7b0b318c619dfdbd142969fdcae7d9fb8f0 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 19 Nov 2021 13:44:15 -0600 Subject: [PATCH 046/585] Update glossary.md Co-authored-by: Mark Tyneway --- glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary.md b/glossary.md index 812313674287..a3df223cc0b7 100644 --- a/glossary.md +++ b/glossary.md @@ -8,7 +8,7 @@ An Ethereum network with its own native security mechanism (ie. proof of work, p A network that derives its security from a layer one. -### State Root Oracle +### L2 State Root Oracle A smart contract on L1, providing access to historical L1 block hashes. The existence of this contract makes it possible to prove the existence of a particular L2 state root within a previous L1 block. From f33f4cda61c983e49476c46e646d480eda1a4410 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Wed, 24 Nov 2021 13:39:11 +0100 Subject: [PATCH 047/585] Update definition of epoch --- glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary.md b/glossary.md index a3df223cc0b7..5443b67fd457 100644 --- a/glossary.md +++ b/glossary.md @@ -19,7 +19,7 @@ All of the data necessary to reconstruct the history and state of L2 is containe ### Epoch A continuous sequence of 0 or more L2 blocks. There is a one to one correspondence between L2 Epochs, and L1 blocks. - +A continuous sequence of L2 blocks, including a single deposit block, followed by 0 or more L2 blocks. There is a one to one correspondence between L2 Epochs, and L1 blocks.``` **Example usage:** "Epoch 20 corresponds to L1 block 637, epoch 21 corresponds to block 638, etc". ### Feeds From cce2602af313e47ac71a24f82c2db8994a060a3e Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Wed, 24 Nov 2021 13:39:27 +0100 Subject: [PATCH 048/585] s/ie./e.g. Co-authored-by: Liam Horne --- glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary.md b/glossary.md index 5443b67fd457..8828b10a0f2f 100644 --- a/glossary.md +++ b/glossary.md @@ -2,7 +2,7 @@ ### Layer 1 (L1) -An Ethereum network with its own native security mechanism (ie. proof of work, proof of stake or proof of authority). +An Ethereum network with its own native security mechanism (e.g., proof of work, proof of stake or proof of authority). ### Layer 2 (L2) From 02c9a6cabc0f7257da194fdff17bf7781c7e32b8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 10 Nov 2021 17:00:31 +0100 Subject: [PATCH 049/585] Update rollup node readme, replicator -> p2p sync, clarify services --- components/rollup_node/README.md | 105 +++++++++++++----- components/rollup_node/p2p_interface.md | 40 +++++++ .../rollup_node/sequencer_replicator.md | 23 ---- 3 files changed, 115 insertions(+), 53 deletions(-) create mode 100644 components/rollup_node/p2p_interface.md delete mode 100644 components/rollup_node/sequencer_replicator.md diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md index de6dbd5c6d10..208ae5e96dd7 100644 --- a/components/rollup_node/README.md +++ b/components/rollup_node/README.md @@ -1,62 +1,107 @@ # Rollup Node -The consensus module of Optimistic Ethereum. +The consensus-layer of Optimism. + +This design mirrors the separation of L1 consensus- and execution-layer to L2, +for maximum compatibility and minimal complexity. ## Summary -The Rollup Node is a consensus client that determines the latest state of the rollup. It reads state from L1, and possibly the sequencer, to compute the L2 state. The [block derivation spec][block-derivation] defines the rules by which L1 state is converted into L2 blocks. +The Rollup Node is a consensus client that tracks the rollup: +- Fork-choice: following L1 +- Input Data: deposits and sequencer data extracted from L1 +- Latest blocks: optimistically via L2 p2p, overrideable by L1 + +The input data and forkchoice information collected from L1 (and optimistically via p2p) +are then forwarded to the execution-layer, also known as "execution engine", +via the standard [Engine API][engine-api]. + +The design is minimalist: +- The rollup consensus-layer is largely derived from L1 properties, enabling a simple and stateless L2 consensus. +- The rollup execution-layer is largely shared with L1, equivalent in all ways except the addition of rollup-deposits. ## Types of Rollup Nodes + There are two primary classes of rollup nodes, corresponding to different configurations of the software stack. -1. **Sequencer**: Accepts user-sent and deposit transactions, orders them into L2 blocks, and submits them to L1 in batches. Provides RPC access to pending L2 blocks in advance of L1 submission. -2. **Verifier**: Watches L1 feeds, reconstructs L2 block inputs, and inserts them into the EE to determine the canonical L2 state. May also track pending sequencer state, in some configurations. +1. **Sequencer**: Accepts user-sent and deposit transactions, orders them into L2 blocks, and submits them to L1 in batches. +2. **Verifier**: Watches L1 feeds, reconstructs L2 block inputs, and inserts them into the EE to determine the canonical L2 state. + +**Both** update their coupled execution-engine with L2 blocks and fork-choice instructions, to maintain their view of the rollup state. + +Optionally the sequencer(s) may share the L2 blocks via the L2 p2p network before the L1 can confirm them, +which verifiers can optionally use to sync to the very tip (marked "unsafe" in JSON-RPC) of the rollup. +This enables permissionless L1-like latency for users, but not canonical until available on the L1. -### Subcomponents Used for Each Node Type -Of the components outlined below, different node types use different combinations of them, either manually or optionally. +## Services -| Node Type \ Component | Execution Engine | Rollup Driver | Sequencer Replicator | Block Producer | Batch Submitter | -|-----------------------|------------------|----------------------|----------------------|----------------|-----------------| -| Verifier | X | X | optional | | | -| Sequencer | X | X | | X | X | +### L2 Execution Engine -## Components +The [Execution Engine][exec-engine] (EE) is *separated from the rollup node*, following the separated consensus/execution layer design of L1. +The rollup node communicates to the engine via the [Engine JSON-RPC interface][engine-api] +(Secured and separated from the regular user JSON-RPC). -### [L2 Execution Engine][exec-engine] +Most L1 clients are working on conversion to execution engines, as part of the [The Merge][the-merge]. -The execution engine implements the [execution specification][execution-spec]. Most L1 clients will soon be converted into execution engines. The rollup client will communicate to the engine via a JSON-RPC interface ([WIP][execution-engine-rpc]). +Every execution-engine that is built for L1 can be used, with a minimal set of changes: +- Support a Deposit-transaction type: clean and efficient separation from regular transactions, following [EIP 2718][EIP-2718], similar to EIP-1559 transactions. +- Enable the consensus-layer to specify transactions during payload preparation: L2 blocks can then be formed on just the inputs, and deposits can be processed. +- Adjustment to Fee metering -One of the main goal of the rollup client is to use the execution engine without modification. +All three of these features overlap with forthcoming L1 updates and may be unified at a later stage: +Validator withdrawals, system-transactions, and time-aware base fee calculation [EIP 4396][EIP-4396]. -### [Rollup Driver][rollup-driver] +### Rollup Driver -The rollup driver connects to an L1 node, and tracks the feed data comprising of deposits and sequencer batches. Based on the rules of [block derivation][block-derivation], it is able to compute sets ("epochs") of L2 blocks as a stateless, pure function of ranges of L1 blocks. +The [Rollup Driver][rollup-driver] is the main service *within the rollup node*, mapping L1 data to L2 chain progress. -While connected to the Execution Engine, it uses the Engine API to progress the L2 state as new data comes in from L1. The rollup driver will reorganize the L2 state if it detects a difference between the EE and what's on L1, and provides a way for other services to subscribe to reorgs. +Based on the rules of [block generation][block-gen], it is able to compute sets ("epochs") of L2 blocks as a stateless, pure function of ranges of L1 blocks. -### [Sequencer Replicator][sequencer-replicator] +While connected to the Execution Engine, it uses the Engine API to progress the L2 state as new data comes in from L1. +The rollup driver will instruct the engine to reorganize the L2 state if it detects a difference between the local chain and remote chain as confirmed on L1, +and provides a way for other services to subscribe to reorgs. -The sequencer replicator connects directly to the sequencer. It requests pending L2 blocks which have not yet been batch submitted, and inserts them into the tip of the local EE. +### Block Producer -These blocks are marked in the EE as not yet confirmed on L1. Replicating verifiers still run a CL, which will later mark them as L1-confirmed within the EE. +The [Block Producer][block-producer] is an optional service to run as sequencer, *within the rollup node*, +to progress the L2 state in advance of batch submission. -### [Block Producer][block-producer] +When tasked to produce a new rollup block, the rollup node adds `PayloadAttributesV1` to the `engine_forkchoiceUpdated` +call to instruct the engine to start sequencing a block of pending contents from the transaction pool. -The block producer service is run by the sequencer to progress the L2 state in advance of batch submission. The block producer repeatedly calls `engine_preparePayload` to get a new L2 block and then uses `engine_executePayload` to insert the resulting block into the state. When new L1 blocks appear, it passes the corresponding deposit transactions to `engine_preparePayload`. +This execution block is then retrieved with `engine_getPayload`, to then be pushed to L1 for availability, +and optionally directly the L2 network for faster tip updates. -### [Batch Submitter][batch-submitter] +### Batch Submitter -The batch submitter takes the pending blocks which have been inserted into the sequencer's L2 state by the block producer, and sends corresponding transactions in batches to L1. +The [Batch Submitter][batch-submitter] service takes a queue of locally produced payloads, +and submits the corresponding transactions in batches to L1. The batch submitter encodes these transactions based on the rules of [block derivation][block-derivation], effectively as the reverse of the process carried out by the rollup driver. As a result: - Blocks previously inserted by the Block Producer into the Sequencer's EE will now appear in L1 Verifiers' EEs. -- Blocks marked as sequencer-confirmed in both the Sequencer and in Replicating verifiers will now be marked as L1-confirmed. +- Blocks marked as sequencer-confirmed in both the Sequencer and in Replicating verifiers will now be recognized as L1-confirmed. + +### P2P Interface + +The [P2P Interface][p2p-interface] service enables verifiers to stay in sync with the tip of the rollup with lower latency, and sequencers to distribute the server work. + +Staying in sync with the tip requires rollup nodes to learn about data more directly, faster than the L1 can make them available. + +This is solved with an optimistic process: +1. Sequencer publishes the L2 block through a lightweight L2 P2P network (single gossip topic) +2. Verifier listens on the P2P network, verifies sequencer signature, and applies the block to their L2 EE. +3. If the data cannot be confirmed on L1, or if conflicting data is confirmed, then the bad L2 block is reorganized away. + +The amount of L2 blocks that can be optimistically applied to the L2 EE is constrained by the supported reorg-depth by the execution engine: +ultimately the L1 chain determines the canonical rollup chain. + -[execution-spec]: https://github.com/ethereum/execution-specs -[execution-engine-rpc]: https://hackmd.io/@n0ble/consensus_api_design_space -[block-derivation]: ./components/rollup_node/block_derivation.md +[engine-api]: https://github.com/ethereum/execution-apis/tree/main/src/engine +[the-merge]: https://eips.ethereum.org/EIPS/eip-3675 +[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 +[EIP-4396]: https://eips.ethereum.org/EIPS/eip-4396 +[block-gen]: ./components/rollup_node/block_gen.md [exec-engine]: ./exec_engine.md [rollup-driver]: ./consensus_layer.md -[sequencer-replicator]: ./sequencer_replicator.md [block-producer]: ./block_producer.md -[batch-submitter]: ./batch_submitter.md \ No newline at end of file +[batch-submitter]: ./batch_submitter.md diff --git a/components/rollup_node/p2p_interface.md b/components/rollup_node/p2p_interface.md new file mode 100644 index 000000000000..a61d5352f98e --- /dev/null +++ b/components/rollup_node/p2p_interface.md @@ -0,0 +1,40 @@ +# P2P Interface + +Previously known as the "sequencer replicator", Work In progress. + +Design direction: +- distribute workload of L2 sequencer +- create redundancy +- permissionless access to head of the L2 chain +- access to unconfirmed data in user RPC +- mirror forkchoice boundaries separation in user RPC, with new post-merge standard: + - finalized == undisputed + - safe (previously known as "latest") = confirmed data on L1, might be disputed or reorged via L1, but safe w.r.t. L2. + - unsafe = unconfirmed, pending on L1, but known via P2P on L2 ahead of time. + +---- + + + +The sequencer replicator connects directly to the sequencer. It requests pending L2 blocks which have not yet been batch submitted, +and inserts them into the tip of the local EE, marked only as sequencer confirmed (NOT L1 confirmed). The sequencer replicator is connected to the sequencer EE via RPC. + +A rollup node using the replicator will place additional trust in the sequencer's local state being resolved to L1 via batch submission. However, it will still execute all blocks itself, so that the EE state will always be something that *is possible* in the future, even if it doesn't end up manifesting that way on L1. + +## Basic Functionality + +- The sequencer replicator may only modify or add state which is at the end of the EE, and not yet L1 confirmed. + - The replicator is **NEVER** to modify any blocks in the EE which are marked L1 confirmed. + - ONLY sequencer confirmed blocks may written or overwritten by the replicator. +- Halted mode: If a reorg is detected by the [consensus layer][consensus-layer], or if the sequencer sends conflicting data (outlined below), the replicator service should halt. It should do this either for a configured time period, until manual intervention by the node operator, or perhaps until the CL indicates that it has finished syncing. If the replicator is halted, then the Replicating Verifier will subsequently behave identically to the L1 verifier. + +Core logic: + +1. Get the local EE head, and query the corresponding sequencer block via RPC. + - if the blocks DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. +2. Query the sequencer's RPC for the blocks between the local EE head and the sequencer head. For each returned block: + - Get the block input and apply it to the head. (As sequencer confirmed--even if sequencer says L1 confirmed.) + - Make sure the resulting local blockhash and stateroot match what sequencer returned. If they DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. +3. Wait and GOTO 1. + +[consensus-layer]: ./consensus_layer.md \ No newline at end of file diff --git a/components/rollup_node/sequencer_replicator.md b/components/rollup_node/sequencer_replicator.md deleted file mode 100644 index 9d8ed29bdbe8..000000000000 --- a/components/rollup_node/sequencer_replicator.md +++ /dev/null @@ -1,23 +0,0 @@ -# Sequencer Replicator - -The sequencer replicator connects directly to the sequencer. It requests pending L2 blocks which have not yet been batch submitted, and inserts them into the tip of the local EE, marked only as sequencer confirmed (NOT L1 confirmed). The sequencer replicator is connected to the sequencer EE via RPC. - -A rollup node using the replicator will place additional trust in the sequencer's local state being resolved to L1 via batch submission. However, it will still execute all blocks itself, so that the EE state will always be something that *is possible* in the future, even if it doesn't end up manifesting that way on L1. - -## Basic Functionality - -- The sequencer replicator may only modify or add state which is at the end of the EE, and not yet L1 confirmed. - - The replicator is **NEVER** to modify any blocks in the EE which are marked L1 confirmed. - - ONLY sequencer confirmed blocks may written or overwritten by the replicator. -- Halted mode: If a reorg is detected by the [consensus layer][consensus-layer], or if the sequencer sends conflicting data (outlined below), the replicator service should halt. It should do this either for a configured time period, until manual intervention by the node operator, or perhaps until the CL indicates that it has finished syncing. If the replicator is halted, then the Replicating Verifier will subsequently behave identically to the L1 verifier. - -Core logic: - -1. Get the local EE head, and query the corresponding sequencer block via RPC. - - if the blocks DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. -2. Query the sequencer's RPC for the blocks between the local EE head and the sequencer head. For each returned block: - - Get the block input and apply it to the head. (As sequencer confirmed--even if sequencer says L1 confirmed.) - - Make sure the resulting local blockhash and stateroot match what sequencer returned. If they DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. -3. Wait and GOTO 1. - -[consensus-layer]: ./consensus_layer.md \ No newline at end of file From 6a0abe0528ec0a485a27c7c2f208f485442dedff Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 11 Nov 2021 19:06:32 +0100 Subject: [PATCH 050/585] initial L2 network spec --- components/rollup_node/exec_engine.md | 17 +- components/rollup_node/p2p_interface.md | 222 +++++++++++++++++++++--- 2 files changed, 210 insertions(+), 29 deletions(-) diff --git a/components/rollup_node/exec_engine.md b/components/rollup_node/exec_engine.md index 63a2221a97d8..111eccd58b09 100644 --- a/components/rollup_node/exec_engine.md +++ b/components/rollup_node/exec_engine.md @@ -11,4 +11,19 @@ The L2 execution engine is where transaction execution actually takes place, and 3. **Fee payment modification**: ETH is charged in addition to the `gasPrice * gasUsed`, to compensate the sequencer for rolling up the user transaction. This should be consistent with the [existing OVM 2.0 fee scheme](https://community.optimism.io/docs/users/fees-2.0.html), but using the L1 context information directly instead of via an oracle. 4. **EIP1559 modification**: Updates to the `BASEFEE` on L2 must be handled differently, in accordance to L1 time, as L2 blocktime may not be constant. (*Note: this modification may not be necessary; L1 devs are actively discussing modification of eip-1559 to handle "gap-slots" which would solve for the same timing.*) 5. **L1 Context Information**: The L1 blockhash, L1 blocknumber, and L1 basefee are frequently requested to be accessible within L2. *(TBD: it is possible to expose this information purely in a normal L2 contract, which is updated via the deposit TX type. This may minimize the diff more.)* -6. **Confirmation Status**: The Execution Engine will repurpose (but not otherwise modify) the three beacon chain confirmation strengths (`finalized, safe, unsafe`) to corresponding to (`l1_finalized, l1_confirmed, sequencer_confirmed`). \ No newline at end of file +6. **Confirmation Status**: The Execution Engine will repurpose (but not otherwise modify) the three beacon chain confirmation strengths (`finalized, safe, unsafe`) to corresponding to (`l1_finalized, l1_confirmed, sequencer_confirmed`). + +## Engine usage + +### `engine_forkchoiceUpdatedV1` + +TODO + +### `engine_getPayloadV1` + +TODO + +### `engine_executePayloadV1` + +TODO + diff --git a/components/rollup_node/p2p_interface.md b/components/rollup_node/p2p_interface.md index a61d5352f98e..59b7964a6549 100644 --- a/components/rollup_node/p2p_interface.md +++ b/components/rollup_node/p2p_interface.md @@ -1,40 +1,206 @@ # P2P Interface -Previously known as the "sequencer replicator", Work In progress. - -Design direction: -- distribute workload of L2 sequencer -- create redundancy -- permissionless access to head of the L2 chain -- access to unconfirmed data in user RPC -- mirror forkchoice boundaries separation in user RPC, with new post-merge standard: - - finalized == undisputed - - safe (previously known as "latest") = confirmed data on L1, might be disputed or reorged via L1, but safe w.r.t. L2. - - unsafe = unconfirmed, pending on L1, but known via P2P on L2 ahead of time. +This peer-to-peer (P2P) network service in the rollup node is optional, +but greatly improves the latency between the view of sequencers and the rest of the network, +as well as enabling faster historical sync to be bootstrapped, without relying on a single endpoint. ----- +In summary, the P2P stack looks like: +- Discovery to find peers: [Discv5][discv5] +- Connections, peering, transport security, multi-plexing, gossip: [LibP2P][libp2p] + +This document only specifies the composition and configuration of these network libraries. +These components have their own standards, implementations in Go/Rust/Java/Nim/JS/more, +and adopted several other blockchains, most notably the [L1 consensus layer (Eth2)][eth2-p2p]. + +## P2P configuration + +### Identification + +Nodes have a **separate** network- and consensus-identity. +The network identity is a `secp256k1` key, used for both discovery and active LibP2P connections. + +Common representations of network identity: +- `PeerID`: a LibP2P specific ID derived from the pubkey (through protobuf encoding, typing and hashing) +- `NodeID`: a Discv5 specific ID derived from the pubkey (through hashing, used in the DHT) +- `Multi-address`: an unsigned address, containing: IP, TCP port, PeerID +- `ENR`: a signed record used for discovery, containing: IP, TCP port, UDP port, signature (pubkey can be derived) and L2 network identification. Generally encoded in base64. + +### Discv5 + +#### Structure + +The Ethereum Node Record (ENR) for an Optimism rollup node must contain keyed values: + +- An IPv4 address (`ip` field) and/or IPv6 address (`ip6` field). +- A TCP port (`tcp` field) representing the local libp2p listening port. +- A UDP port (`udp` field) representing the local discv5 listening port. +- An Optimism (`optimism` field) L2 network identifier + +The `optimism` value is encoded as the concatenation of: +- chain ID (`varint`) +- fork ID (`varint`) + +Note that DiscV5 is a shared DHT: the L1 consensus and execution nodes, as well as testnet nodes, +and even external IOT nodes, all communicate records in this large common DHT. + +The discovery process in Optimism is a pipeline of node records: +1. Fill the table with `FINDNODES` if necessary +2. Pull additional records with searches to random Node IDs if necessary +3. Pull records from the DiscV5 module when looking for peers +4. Check if the record contains the `optimism` entry, verify it matches the chain ID and current or future fork number +5. If not already connected, and not recently disconnected or put on deny-list, attempt to dial. + +### LibP2P + +#### Transport + +TCP transport. Additional transports are supported by LibP2P, but not required. + +#### Dialing + +Nodes should be publicly dialable, not rely on relay extensions, and able to dial both IPv4 and IPv6. + +#### NAT + +The listening endpoint must be publicly facing, but may be configured behind a NAT. +LibP2P has optional automation for this. + +#### Peergating and pruning + +TODO: max-peers, grace periods, pruning + +#### Transport security + +[Libp2p-noise][libp2p-noise], `XX` handshake, with the the `secp256k1` P2P identity, as popularized in Eth2. + +#### Protocol negotiation + +[Multistream-select 1.0][multistream-select] (`/multistream/1.0.0`) is an interactive protocol +used to negotiate sub-protocols supported in LibP2P peers. Multistream-select 2.0 may be used in the future. + +#### Identify + +LibP2P offers a minimal identification module to share client version and language. +This is optional and can be disabled for enhanced privacy. +It also includes the same protocol information, which can speed up initial connections. + +#### Multiplexing +For async communication over different channels over the same connection, multiplexing is used. +[mplex][mplex] (`/mplex/6.7.0`) is required, and [yamux][yamux] (`/yamux/1.0.0`) is recommended but optional +#### GossipSub -The sequencer replicator connects directly to the sequencer. It requests pending L2 blocks which have not yet been batch submitted, -and inserts them into the tip of the local EE, marked only as sequencer confirmed (NOT L1 confirmed). The sequencer replicator is connected to the sequencer EE via RPC. +[GossipSub 1.1](gossipsub) (`/meshsub/1.1.0`, i.e. with peer-scoring extension) is a pubsub protocol for mesh-networks, +deployed on L1 consensus (Eth2) and other protocols such as Filecoin, offering lots of customization options. -A rollup node using the replicator will place additional trust in the sequencer's local state being resolved to L1 via batch submission. However, it will still execute all blocks itself, so that the EE state will always be something that *is possible* in the future, even if it doesn't end up manifesting that way on L1. +##### Content-based message identification -## Basic Functionality +Messages are deduplicated, and filtered through application-layer signature verification. +Thus origin-stamping is disabled and published messages must only contain application data, +enforced through a [`StrictNoSign` Signature Policy][signature-policy] -- The sequencer replicator may only modify or add state which is at the end of the EE, and not yet L1 confirmed. - - The replicator is **NEVER** to modify any blocks in the EE which are marked L1 confirmed. - - ONLY sequencer confirmed blocks may written or overwritten by the replicator. -- Halted mode: If a reorg is detected by the [consensus layer][consensus-layer], or if the sequencer sends conflicting data (outlined below), the replicator service should halt. It should do this either for a configured time period, until manual intervention by the node operator, or perhaps until the CL indicates that it has finished syncing. If the replicator is halted, then the Replicating Verifier will subsequently behave identically to the L1 verifier. +This provides greater privacy, and allows sequencers (consensus identity) to maintain +multiple network identities for redundancy. -Core logic: +##### Message compression and limits + +The application contents are compressed with [snappy][snappy] single-block-compression +(as opposed to frame-compression), and constrained to 10 MiB. + +##### Message ID computation + +[Same as L1][l1-message-id], with recognition of compression: +* If `message.data` has a valid snappy decompression, set `message-id` to the first 20 bytes of the `SHA256` hash of + the concatenation of `MESSAGE_DOMAIN_VALID_SNAPPY` with the snappy decompressed message data, + i.e. `SHA256(MESSAGE_DOMAIN_VALID_SNAPPY + snappy_decompress(message.data))[:20]`. +* Otherwise, set `message-id` to the first 20 bytes of the `SHA256` hash of + the concatenation of `MESSAGE_DOMAIN_INVALID_SNAPPY` with the raw message data, + i.e. `SHA256(MESSAGE_DOMAIN_INVALID_SNAPPY + message.data)[:20]`. + +#### Heartbeat and parameters + +GossipSub [parameters][gossip-parameters]: + +- `D` (topic stable mesh target count): 8 +- `D_low` (topic stable mesh low watermark): 6 +- `D_high` (topic stable mesh high watermark): 12 +- `D_lazy` (gossip target): 6 +- `heartbeat_interval` (frequency of heartbeat, seconds): 1.0 +- `fanout_ttl` (ttl for fanout maps for topics we are not subscribed to but have published to, seconds): 24 +- `mcache_len` (number of windows to retain full messages in cache for `IWANT` responses): 6 +- `mcache_gossip` (number of windows to gossip about): 3 +- `seen_ttl` (number of heartbeat intervals to retain message IDs): 40 + +Notable differences from L1 consensus (Eth2): +- `seen_ttl` does not need to cover a full L1 epoch (6.4 minutes), but rather just a small window covering latest blocks +- `fanout_ttl` adjusted to lower than `seen_ttl` +- `heartbeat_interval` lowered for bandwidth saving, since there are less messages per second (no 600 attestations every second) + + +#### Topic configuration + +Topics have string identifiers and are communicated with messages and subscriptions. +`/optimism/chain_id/hardfork_version/Name` + +- `chain_id`: replace with decimal representation of chain ID +- `hardfork_version`: replace with decimal representation of hardfork +- `Name`: topic application-name + +Note that the topic encoding depends on the topic, unlike L1, since there are less topics, and all are snappy-compressed. + +## Gossip Topics + +### `blocks` + +The primary topic of the L2, to distribute blocks to other nodes faster than proxying through L1 would. + +#### Block encoding + +TODO: encode execution payload (SSZ or RLP), with sequencer identifier and signature. + +TODO: signature type and verification (options: `secp256k1` like transactions, or `BLS12-381` with pubkeys on G1, like L1) + +#### Block validation + +To ensure malicious peers get scored based on application behavior the validation signals +`ACCEPT` (valid), `IGNORE` (like inactivity) or `REJECT` (score penalties). + +In order of operation: +- `[REJECT]` if the encoding or compression is not valid +- `[REJECT]` if the block timestamp is older than 20 seconds in the past (graceful boundary for worst-case propagation and clock skew) +- `[REJECT]` if the block timestamp is more than 5 seconds into the future (graceful boundary for clock skew) +- `[REJECT]` if the signature by the sequencer is not valid +- `[REJECT]` if more than 5 blocks have been seen with the same block height +- `[IGNORE]` if a conflicting block was already seen on L1. It may not be malicious due to racing between L1 confirmation and L2 propagation, but should be filtered out. + +The block is signed by the corresponding sequencer, to filter malicious messages. +The sequencer model is singular but may change to multiple sequencers in the future. +A default sequencer pubkey is distributed with rollup nodes and should be configurable. + +##### Block processing + +A node may apply the block to their local engine ahead of L1 availability, if it ensures that: +- The application of the block is reversible, in case of a conflict with delayed L1 information +- The subsequent forkchoice-update ensures this block is recognized as "unsafe" (see [`engine_forkchoiceUpdatedV1`](./exec_engine.md#engine_forkchoiceupdatedv1)) + +##### Block topic scoring parameters + +TODO: GossipSub per-topic scoring to fine-tune incentives for ideal propagation delay and bandwidth usage. + +---- -1. Get the local EE head, and query the corresponding sequencer block via RPC. - - if the blocks DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. -2. Query the sequencer's RPC for the blocks between the local EE head and the sequencer head. For each returned block: - - Get the block input and apply it to the head. (As sequencer confirmed--even if sequencer says L1 confirmed.) - - Make sure the resulting local blockhash and stateroot match what sequencer returned. If they DO NOT agree, something is up with the sequencer. Set the head to `latestL1ConfirmedL2Block`, and halt. -3. Wait and GOTO 1. +[consensus-layer]: ./consensus_layer.md +[libp2p]: https://libp2p.io/ +[discv5]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md +[eth2-p2p]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md +[libp2p-noise]: https://github.com/libp2p/specs/tree/master/noise +[multistream-select]: https://github.com/multiformats/multistream-select/ +[mplex]: https://github.com/libp2p/specs/tree/master/mplex +[yamux]: https://github.com/hashicorp/yamux/blob/master/spec.md +[gossipsub]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md +[signature-policy]: https://github.com/libp2p/specs/blob/master/pubsub/README.md#signature-policy-options +[snappy]: https://github.com/google/snappy +[l1-message-id]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#topics-and-messages +[gossip-parameters]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.0.md#parameters -[consensus-layer]: ./consensus_layer.md \ No newline at end of file From 35c741f6337ad9c9fff4cbe93158ac701c8ba11b Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 17 Nov 2021 03:37:43 -0600 Subject: [PATCH 051/585] rollup node readme: address PR feedback from norswap, part 1 --- components/rollup_node/README.md | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md index 208ae5e96dd7..3ade978ff7a6 100644 --- a/components/rollup_node/README.md +++ b/components/rollup_node/README.md @@ -8,9 +8,9 @@ for maximum compatibility and minimal complexity. ## Summary The Rollup Node is a consensus client that tracks the rollup: -- Fork-choice: following L1 +- Fork-choice: following L1, a reorg on L1 results in a reorg of L2 - Input Data: deposits and sequencer data extracted from L1 -- Latest blocks: optimistically via L2 p2p, overrideable by L1 +- Latest blocks: propagate optimistically via p2p interface, overrideable by L1 The input data and forkchoice information collected from L1 (and optimistically via p2p) are then forwarded to the execution-layer, also known as "execution engine", @@ -24,8 +24,8 @@ The design is minimalist: There are two primary classes of rollup nodes, corresponding to different configurations of the software stack. -1. **Sequencer**: Accepts user-sent and deposit transactions, orders them into L2 blocks, and submits them to L1 in batches. -2. **Verifier**: Watches L1 feeds, reconstructs L2 block inputs, and inserts them into the EE to determine the canonical L2 state. +1. **Sequencer**: Accepts user-sent and deposit transactions, orders them into L2 blocks, and [submits them in batches][batch-submitter] to L1. +2. **Verifier**: Watches L1 feeds, [reconstructs L2 blocks from inputs][block-gen], and inserts them into the EE to determine the canonical L2 state. **Both** update their coupled execution-engine with L2 blocks and fork-choice instructions, to maintain their view of the rollup state. @@ -38,6 +38,8 @@ This enables permissionless L1-like latency for users, but not canonical until a ### L2 Execution Engine The [Execution Engine][exec-engine] (EE) is *separated from the rollup node*, following the separated consensus/execution layer design of L1. + +Execution tasks of the engine include EVM execution, transaction-pool and state sync. The rollup node communicates to the engine via the [Engine JSON-RPC interface][engine-api] (Secured and separated from the regular user JSON-RPC). @@ -67,9 +69,10 @@ The [Block Producer][block-producer] is an optional service to run as sequencer, to progress the L2 state in advance of batch submission. When tasked to produce a new rollup block, the rollup node adds `PayloadAttributesV1` to the `engine_forkchoiceUpdated` -call to instruct the engine to start sequencing a block of pending contents from the transaction pool. +call (see [Engine api][engine-API]) to instruct the engine to start sequencing a block of pending contents from the transaction pool. -This execution block is then retrieved with `engine_getPayload`, to then be pushed to L1 for availability, +This execution block is then retrieved with `engine_getPayload`, to then be pushed to L1 for availability by the +[Batch submitter][batch-submitter] (optionally packed together with other L2 blocks), and optionally directly the L2 network for faster tip updates. ### Batch Submitter @@ -83,16 +86,20 @@ The batch submitter encodes these transactions based on the rules of [block deri ### P2P Interface -The [P2P Interface][p2p-interface] service enables verifiers to stay in sync with the tip of the rollup with lower latency, and sequencers to distribute the server work. - -Staying in sync with the tip requires rollup nodes to learn about data more directly, faster than the L1 can make them available. +The [P2P Interface][p2p-interface] service offers an additional method of syncing the latest L2 blocks, +faster than the L1 can make them available. -This is solved with an optimistic process: +This is implemented with an optimistic process: 1. Sequencer publishes the L2 block through a lightweight L2 P2P network (single gossip topic) 2. Verifier listens on the P2P network, verifies sequencer signature, and applies the block to their L2 EE. 3. If the data cannot be confirmed on L1, or if conflicting data is confirmed, then the bad L2 block is reorganized away. -The amount of L2 blocks that can be optimistically applied to the L2 EE is constrained by the supported reorg-depth by the execution engine: +This service is optional: while the worst-case data-retrieval is covered by L1 in the same way, the happy-path improves: +- Verifiers can stay in sync with the tip of the rollup with lower latency +- Sequencers can distribute the server work + +The amount of L2 blocks that can be optimistically applied to the L2 EE is constrained +by the supported reorg-depth by the execution engine, to preserve the ability to process reorgs of the L2 by L1: ultimately the L1 chain determines the canonical rollup chain. @@ -100,8 +107,9 @@ ultimately the L1 chain determines the canonical rollup chain. [the-merge]: https://eips.ethereum.org/EIPS/eip-3675 [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 [EIP-4396]: https://eips.ethereum.org/EIPS/eip-4396 -[block-gen]: ./components/rollup_node/block_gen.md +[block-gen]: ./block_gen.md [exec-engine]: ./exec_engine.md [rollup-driver]: ./consensus_layer.md [block-producer]: ./block_producer.md [batch-submitter]: ./batch_submitter.md +[p2p-interface]: ./p2p_interface.md From 1a1525682362ee9cc33173506cddd65d955b2fdc Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 17 Nov 2021 04:29:38 -0600 Subject: [PATCH 052/585] rollup node / p2p: more PR review updates --- components/rollup_node/README.md | 11 +++++++++-- components/rollup_node/p2p_interface.md | 12 +++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md index 3ade978ff7a6..87f19da3480f 100644 --- a/components/rollup_node/README.md +++ b/components/rollup_node/README.md @@ -30,8 +30,14 @@ There are two primary classes of rollup nodes, corresponding to different config **Both** update their coupled execution-engine with L2 blocks and fork-choice instructions, to maintain their view of the rollup state. Optionally the sequencer(s) may share the L2 blocks via the L2 p2p network before the L1 can confirm them, -which verifiers can optionally use to sync to the very tip (marked "unsafe" in JSON-RPC) of the rollup. -This enables permissionless L1-like latency for users, but not canonical until available on the L1. +which verifiers can optionally use to sync to the very tip of the rollup. +This enables permissionless L1-like latency for users, but not the default until available on the L1. + +The User JSON-RPC exposes these levels of confirmation, +matching the labels in the [Engine API specifications][engine-forkchoice-unsafe-safe-finalized]: +- `unsafe`: when the data is not yet on L1, but known through L2 P2P propagation +- `safe` ("latest" is an alias to this): when the data has been seen to be published to L1, but not undisputed yet +- `finalized`: when the data is irreversibly canonical ## Services @@ -107,6 +113,7 @@ ultimately the L1 chain determines the canonical rollup chain. [the-merge]: https://eips.ethereum.org/EIPS/eip-3675 [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 [EIP-4396]: https://eips.ethereum.org/EIPS/eip-4396 +[engine-forkchoice-unsafe-safe-finalized]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#forkchoicestatev1 [block-gen]: ./block_gen.md [exec-engine]: ./exec_engine.md [rollup-driver]: ./consensus_layer.md diff --git a/components/rollup_node/p2p_interface.md b/components/rollup_node/p2p_interface.md index 59b7964a6549..bc7ade7579a3 100644 --- a/components/rollup_node/p2p_interface.md +++ b/components/rollup_node/p2p_interface.md @@ -29,7 +29,7 @@ Common representations of network identity: #### Structure -The Ethereum Node Record (ENR) for an Optimism rollup node must contain keyed values: +The Ethereum Node Record (ENR) for an Optimism rollup node must contain the following values, identified by unique keys: - An IPv4 address (`ip` field) and/or IPv6 address (`ip6` field). - A TCP port (`tcp` field) representing the local libp2p listening port. @@ -40,12 +40,13 @@ The `optimism` value is encoded as the concatenation of: - chain ID (`varint`) - fork ID (`varint`) -Note that DiscV5 is a shared DHT: the L1 consensus and execution nodes, as well as testnet nodes, +Note that DiscV5 is a shared DHT (Distributed Hash Table): the L1 consensus and execution nodes, as well as testnet nodes, and even external IOT nodes, all communicate records in this large common DHT. +This makes it more difficult to censor the discovery of node records. The discovery process in Optimism is a pipeline of node records: -1. Fill the table with `FINDNODES` if necessary -2. Pull additional records with searches to random Node IDs if necessary +1. Fill the table with `FINDNODES` if necessary (Performed by Discv5 library) +2. Pull additional records with searches to random Node IDs if necessary (e.g. iterate [`RandomNodes()`][discv5-random-nodes] in Go implementation) 3. Pull records from the DiscV5 module when looking for peers 4. Check if the record contains the `optimism` entry, verify it matches the chain ID and current or future fork number 5. If not already connected, and not recently disconnected or put on deny-list, attempt to dial. @@ -80,7 +81,7 @@ used to negotiate sub-protocols supported in LibP2P peers. Multistream-select 2. #### Identify -LibP2P offers a minimal identification module to share client version and language. +LibP2P offers a minimal identification module to share client version and programming language. This is optional and can be disabled for enhanced privacy. It also includes the same protocol information, which can speed up initial connections. @@ -193,6 +194,7 @@ TODO: GossipSub per-topic scoring to fine-tune incentives for ideal propagation [consensus-layer]: ./consensus_layer.md [libp2p]: https://libp2p.io/ [discv5]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md +[discv5-random-nodes]: https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.10.12/p2p/discover#UDPv5.RandomNodes [eth2-p2p]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md [libp2p-noise]: https://github.com/libp2p/specs/tree/master/noise [multistream-select]: https://github.com/multiformats/multistream-select/ From 0338c599a11e37a0b589dc18205ea9a85d74a711 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 19 Nov 2021 13:35:02 -0600 Subject: [PATCH 053/585] Reset repo to restart from scratch Prior to this commit, the specs in this repo have grown somewhat hapharzardly, making them hard to edit and evolve in the desired direction. We've agreed to start fresh. Much of the content can and will be reused as we begin filling in these specs again, though it will be subjected to review again before merging. --- README.md | 53 +---- assets/architecture.svg | 4 - assets/network-participants-overview.svg | 4 - assets/roadmap.svg | 4 - assets/sequencer-block-gen.svg | 4 - ...cer-handling-deposits-and-transactions.svg | 4 - assets/simple-block-gen.svg | 4 - assets/user-withdrawing-to-l1.svg | 4 - assets/verifier-executing-fraud-proof.svg | 4 - components/challenge_agent.md | 1 - .../fraud-proof-vm/fraud_proof_program.md | 43 ---- components/fraud-proof-vm/fraud_proof_vm.md | 50 ----- components/rollup_node/README.md | 122 ---------- components/rollup_node/batch_submitter.md | 2 - components/rollup_node/block_derivation.md | 147 ------------- components/rollup_node/block_producer.md | 2 - components/rollup_node/exec_engine.md | 29 --- components/rollup_node/p2p_interface.md | 208 ------------------ components/rollup_node/rollup_driver.md | 27 --- components/witness_gen.md | 1 - glossary.md | 89 -------- introduction.md | 132 ----------- layer-1-contracts/README.md | 20 -- overview.md | 114 ---------- roadmap.md | 70 ------ 25 files changed, 7 insertions(+), 1135 deletions(-) delete mode 100644 assets/architecture.svg delete mode 100644 assets/network-participants-overview.svg delete mode 100644 assets/roadmap.svg delete mode 100644 assets/sequencer-block-gen.svg delete mode 100644 assets/sequencer-handling-deposits-and-transactions.svg delete mode 100644 assets/simple-block-gen.svg delete mode 100644 assets/user-withdrawing-to-l1.svg delete mode 100644 assets/verifier-executing-fraud-proof.svg delete mode 100644 components/challenge_agent.md delete mode 100644 components/fraud-proof-vm/fraud_proof_program.md delete mode 100644 components/fraud-proof-vm/fraud_proof_vm.md delete mode 100644 components/rollup_node/README.md delete mode 100644 components/rollup_node/batch_submitter.md delete mode 100644 components/rollup_node/block_derivation.md delete mode 100644 components/rollup_node/block_producer.md delete mode 100644 components/rollup_node/exec_engine.md delete mode 100644 components/rollup_node/p2p_interface.md delete mode 100644 components/rollup_node/rollup_driver.md delete mode 100644 components/witness_gen.md delete mode 100644 glossary.md delete mode 100644 introduction.md delete mode 100644 layer-1-contracts/README.md delete mode 100644 overview.md delete mode 100644 roadmap.md diff --git a/README.md b/README.md index 1967a5ded2d9..b25194ca1e90 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,23 @@ # The Optimistic Ethereum Spec -This repository holds the open-source specification for Optimistic Ethereum, an ultra-minimal optimistic rollup protocol that maintains 1:1 compatibility with Ethereum. +This repository holds the work-in-progress specification for a "Simple Optimistic Rollup"; a minimum viable +version of the Optimistic Ethereum protocol. -## Work in Progress - -Please note that this specification is currently heavily under construction. -You will find that several pages are incomplete or [under discussion](https://github.com/ethereum-optimism/optimistic-specs/issues). - -## Specification structure - -- [Introduction](./introduction.md) -- [Overview](./overview.md) -- [Roadmap](./roadmap.md) -- Components: - - [Layer 1 Contracts](./components/layer1.md) - - [Rollup Client](./components/rollup_client.md) - - [Execution Engine](./components/exec_engine.md) - - [Batch Submitter](./components/batch_submitter.md) - - [Witness Generator](./components/witness_gen.md) - - [Challenge Agent](./components/challenge_agent.md) - -## Design Philosophy - -We believe that **the best optimistic rollup design needs to be minimal, open, and accessible.** - -### Minimalism +A more detailed, though potentially out of date specification can be found on the `alpha` branch. -Ethereum-focused optimistic rollups should be minimal to best take advantage of the battle-tested infrastructure (like Geth) that already runs Ethereum. -An ideal optimistic rollup design should be representable as a *diff* against Ethereum client software. -We imagine a world in which any Ethereum client can, with only minor modifications, participate in an Optimistic Ethereum network. - -### Openness - -We think it's time to coordinate the Ethereum community around a well-specified optimistic rollup design. -We acknowledge that this is only possible if the design process remains open to the feedback of the many teams already working on optimistic rollup architectures. -We aim to make this both this specification and the process by which this specification is built available to anyone interesting in building their own ORU system. - -Anyone interested in contributing to this specification should refer to the [Contributing](#contributing) section. -You will find multiple options for contributing to this project. - -This repository is distributed under the [Creative Commons Zero v1.0 Universal](https://github.com/ethereum-optimism/optimistic-specs/blob/main/LICENSE) license which dedicates this work to the public domain. -An MIT licensed implementation of this protocol can be found [here](https://github.com/ethereum-optimism/optimism). - -### Accessibility +## Work in Progress -Users, developers, and protocol designers need to be confident that a given optimistic rollup is robust and secure. -We believe that this confidence can only truly come from an accessible specification and codebase that developers can reasonably be expected to understand. -Without this accessibility we'll always fundamentally have to trust the knowledge and competence of a very small group of core developers, a fact antithetical to the ideal decentralized nature of these systems. +Please note that this specification is currently under heavy construction. ## Contributing ### Basic Contributions Contributing to the Optimistic Ethereum specification is easy. -You'll find a list of open questions and active research topics over on the [Fellowship of Ethereum Magicians](https://ethereum-magicians.org) forum. +You'll find a list of open questions and active research topics over on the [discussions](https://github.com/ethereum-optimism/optimistic-specs/discussions) page for this rep. Specific tasks and TODOs can be found on the [Issues](https://github.com/ethereum-optimism/optimistic-specs/issues) page. You can edit content or add new pages by creating a [Pull Request](https://github.com/ethereum-optimism/optimistic-specs/pulls). ### R&D Calls -We hold weekly R&D calls that are open to anyone interested in contributing to the Optimistic Ethereum spec. +We hold bi-weekly R&D calls that are open to anyone interested in contributing to the Optimistic Ethereum spec. Contact [@karlfloersch](https://twitter.com/karl_dot_tech/), [@protolambda](https://github.com/protolambda/), or [@kelvinfichter](https://twitter.com/kelvinfichter) if you'd like to join these calls. Please note that these calls may be recorded and shared publicly (we will ask for consent before recording). diff --git a/assets/architecture.svg b/assets/architecture.svg deleted file mode 100644 index 3d8af1053fcd..000000000000 --- a/assets/architecture.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
L1
L1
L2
L2
reads
(withdrawals)
reads...
Cross-Domain
Messenger
Cross-Domain...
writes
writes
reads & writes
reads & writes
plays
plays
eventually runs
eventually runs
gets proofs
gets proofs
Challenger Agent
Challenger Agent
canonical L2 state
canonical L2 state
Witness Generator
Witness Generator
reads canonical
block inputs
reads canonical...
canonical L1
consensus
canonical L1...
Rollup Driver
Rollup Driver
submits
pending
blocks
submits...
reads pending
blocks
reads pending...
Batch Submitter
Batch Submi...
Execution Engine
Execution Engine
L2 State Oracle
L2 State Oracle
Single step
verifier
Single...
k-section Game
k-secti...
Proposal Manager
Proposa...
writes pending
blocks
writes pending...
reads
pending
deposits
reads...
Block Producer
Block Produ...
pending
sequencer
blocks
pending...
Sequencer Replicator
Sequencer R...
Node TypeSequencerVerifier
Feeds
Feeds
Deposit Feed
Deposit...
Sequencer Feed
Sequenc...
L2 Block Feed
L2 Bloc...
+
+
=
=
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/network-participants-overview.svg b/assets/network-participants-overview.svg deleted file mode 100644 index d70a983f7b9d..000000000000 --- a/assets/network-participants-overview.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
Ethereum L1 Chain
Ethereum L1 Chain

Network Participants Overview

Network Participants Overview
Query data
(eg. block explorers)
Query data...
Submit transactions
Submit transactions
Submit deposits
Submit deposits
Users
Users
Submit batches and assertions
Submit batches and assertions
P2P Realtime Updates
P2P Realtime Updates
Verifiers
Verifi...
Verify block hash assertions &
submit fraud proofs
Verify block hash assertions &...
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/roadmap.svg b/assets/roadmap.svg deleted file mode 100644 index a5022a03311e..000000000000 --- a/assets/roadmap.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Node
Rollup Node
Feed Contracts
Feed Contracts
Execution Engine
Execution Engine
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
k-section Game
k-section Game
Proposal Manager
Proposal Manager
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof <> Client Compatibility Testing...
Fraud Proof <> Client Compatib...
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Sequencer consensus
Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
(eth2 feeds)
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Prehistory
(research, etc)
Prehistory...
DTL & Batch Submitter
DTL & Batch Submit...
Geth OVM v1
Geth OVM v1
CTC & SCC contracts
CTC & SCC contracts
Rollup Contracts
Rollup Contr...
v0.5 Stability Infrastructure
v0.5 Stability Infrastructure
Rollup Client
Rollup Client
Mainnet
v0 Launch
Mainnet...
Geth OVM v2
Geth OVM v2
v0.5 Regenesis
v0.5 Regenesis
v1.0
Release
v1.0...
OVM v1
single step verifier
OVM v1...
Bond Manager
Bond Manager
Begin
 minimal diff fraud proof
Begin...
Opcode
single step verifier
Opcode...
Dispute Game
Dispute Game
L2 State Oracle
L2 State Oracle
Challenger Agent
Challenger Agent
Fraud Proof VM
Fraud Proof VM
Fraud Proof VM Audits
Fraud Proof VM Audits
Bonded Sequencer
Bonded Sequencer
Fraud Proof Security Drill v0
Fraud Proof S...
Merge API interface finalization
Merge API interface finalization
Sharding research and development
Sharding research and development
Sharding launch
Sharding laun...
Decentralized Sequencer consensus
Decentralized Sequencer consensus
eth2 Feed Support
eth2 Feed Support
Sequencer is now fully decentralized
Sequencer is now fully dec...
Core Optimistic Ethereum technology has been completed. Eth is L2 native. Further improvements include parallelism & cross rollup communication.
Core Optimistic Ethereum tec...
Statelessness & state expiry R&D
Statelessness & state expiry R&D
Native EVM containerization
(eg. EIP726)
Native EVM containerization...
Migrate to native EVM fraud proof
Migrate to na...
eth2
eth2
eth1.x stateless
clients
eth1.x statel...
Ultra scalable rollups
 are now possible.
Ultra scalable rollups...
v2.0
Release
v2.0...

Legend

Legend
Work in progress
(gradient)
Work in progress...
Completed (green)
Completed (gree...
Not Started
(white)
Not Started...

Status

Status

Type

Type
Project
Project
Event
Event
Comment
Comment
  Optimism
  Mainnet
Optimism...
  Fraud
  Proof
Fraud...
External component
External comp...
Core Component

Core Componen...
Fraud Proof VM Optimization
Fraud Proof VM Optimization
Dispute Game Audits & Proofs
Dispute Game Audits & Proofs
v1.0 Spec
(Executable)
v1.0 Spec...
Geth Optimizations
(eg. EVM Parallelism)
Geth Optimizations...
State Expiry
State Expiry
Begin v2 Scalability Research
Begin v2 Sc...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/sequencer-block-gen.svg b/assets/sequencer-block-gen.svg deleted file mode 100644 index 7debdbe1b0be..000000000000 --- a/assets/sequencer-block-gen.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
L1
L1
L2
L2
D
D
S0
S0
S1
S1
D
D
D
D
D
D
S0
S0
S1
S1
Epoch 1
Epoch 1
Epoch 2
Epoch 2
Epoch 3
Epoch 3
Epoch 4
Epoch 4
....
....
Sequencer Rollup
Sequencer Rollup
!
!
Note: Epochs may not contain sequencer blocks
Note: Epochs may no...
Sequencer Block Submission Windows
Sequencer Block Submission Windows
Sequencing Window = 2 blocks
Sequencing Window = 2 blocks
S3
S3
S5
S5
S4
S4
S3
S3
S4
S4
S5
S5
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/sequencer-handling-deposits-and-transactions.svg b/assets/sequencer-handling-deposits-and-transactions.svg deleted file mode 100644 index f2c90407e73c..000000000000 --- a/assets/sequencer-handling-deposits-and-transactions.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
3. Insert deposit block
3. Insert deposit block
Rollup Node
Rollup Node
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to sequencer feed
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the sequencer feed.
Queries for all...
Sequencer Feed
Sequencer Feed

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
Block Hash
Assertion Submitter
Block Hash...
Queries for the next
assertable block hash
& submits it to the
assertion manager.
Queries for the next...
L2 State Oracle
L2 State Oracle
Assertion Manager
Assertion...
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/simple-block-gen.svg b/assets/simple-block-gen.svg deleted file mode 100644 index 00ec754999ea..000000000000 --- a/assets/simple-block-gen.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
L1
L1
L2
L2
D
D
D
D
D
D
D
D
Epoch 1
Epoch 1
Epoch 2
Epoch 2
Epoch 3
Epoch 3
Epoch 4
Epoch 4
....
....
Simple Rollup
Simple Rollup
Sequencer timeout = 0 blocks
Sequencer timeout = 0 blocks
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/user-withdrawing-to-l1.svg b/assets/user-withdrawing-to-l1.svg deleted file mode 100644 index 259e1ecd8716..000000000000 --- a/assets/user-withdrawing-to-l1.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
Ethereum L1 Chain
Ethereum L1 Chain
Sequencer Feed
Sequencer Feed

User Withdrawing to Layer 1

User Withdrawing to Layer 1
L2 State Oracle
L2 State Oracle
Assertion Manager
Assertion...
3. Assert block hash
containing withdrawal
commitment
3. Assert block hash...
2. Post batch
with withdrawal
transaction data
2. Post batch...
1. Send
initiate
withdrawal

transaction
1. Send...
5. Send
execute
withdrawal

transaction
5. Send...
4. Wait for block
hash to finalize
4. Wait for block...
User
User
ERC20
ERC20
6. Verify
withdrawal
in finalized
block hash
6. Verify...
7.
Transfer
tokens
7....
Bridge
Bridge
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/verifier-executing-fraud-proof.svg b/assets/verifier-executing-fraud-proof.svg deleted file mode 100644 index 2f40a7869f6c..000000000000 --- a/assets/verifier-executing-fraud-proof.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Node
Rollup Node
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 State Oracle Contract
L2 State Oracle Contract
Assertion Manager
Assertion...
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/components/challenge_agent.md b/components/challenge_agent.md deleted file mode 100644 index 437c937f9d81..000000000000 --- a/components/challenge_agent.md +++ /dev/null @@ -1 +0,0 @@ -# Challenge Agent diff --git a/components/fraud-proof-vm/fraud_proof_program.md b/components/fraud-proof-vm/fraud_proof_program.md deleted file mode 100644 index 027a1b0a99c6..000000000000 --- a/components/fraud-proof-vm/fraud_proof_program.md +++ /dev/null @@ -1,43 +0,0 @@ -# Fraud Proof Program - -The fraud proof program is the specific program which is run on a [fraud proof VM](./fraud_proof_vm.md) during a dispute. This program is designed to evaluate any subset of the Optimistic Ethereum chain. - -## Initialization - -The OE fraud proof program is used to weed out invalid block hash assertions in the `Block Hash Oracle`. The fraud proof program is initialized using values which are recorded at the time of block hash assertions. This is all handled within the `AssertionManager` contract. - -Every time an L2 block hash is asserted using the `AssertionManager`, the following information is hashed together and recorded: - -- Latest L1 block hash at the time of assertion. -- Asserted next L2 block hash. -- The previous assertion this assertion builds upon. -- Epoch number of the L2 block hash. - -The fraud proof program takes in as input the hash of all these values. - -## Execution - -The fraud proof program is designed to execute the full state transition between any two epochs. The epochs used for a dispute are the previous assertion epoch & the new assertion epoch number in the `AssertionManager`. The fraud proof program will execute the state transition between these epochs and determine the final epoch block hash (ie. the one valid assertion). If the asserted L2 block hash is deemed incorrect over the course of a dispute game, the `AssertionManager` will delete the invalid assertion and forfeit the asserter's bond. - -In practice, the fraud proof program is broken up into two separate processes: - -1. Block generation -2. Block processing - -We split the program into these two distinct parts to isolate the complexity of block processing. This way if there is an error which causes a single block to fail (see [this discussion](https://github.com/ethereum-optimism/optimistic-specs/discussions/22) for details), it does not break the entire assertion game. While the block processing may fail, it is critically important that the block generation process never fails. - -### Block Generation - -The fraud proof program starts out running the block generation process. Block generation uses the same algorithm which is laid out in the [block generation document](../rollup_node/block_gen.md). However, it is worth highlighting: - -1. In the FPVM, all chain data is queried using the preimage oracle. The program will use the L1 block hash at the time of assertion to search backwards on L1 to find all information required for block generation. This can be done by recursively calling `get_preimage(block.previous_block_hash)` until all required block information is loaded into the FPVM memory. -2. The block generation document outlines the process to generate a single epoch. For the purposes of this fraud proof program we will need to generate **all** epochs between the previous assertion and the next assertion. -3. The final step in the block generation algorithm where blocks are **processed** is **not** handled in this top level program. Instead a sub-process is spawned to execute that single block. - -### Block Processing - -For every block which needs to be processed in the block generation algorithm, a sub-process is spawned. This process accepts the block inputs and returns the `block hash` computed by executing the block inputs. The specifics of the block processing algorithm is laid out in the [block processing document] [TODO]. - -## Termination - -Once the fraud proof program has generated and processed all blocks between the last asserted L2 block hash and the newly asserted L2 block hash, it will return the **valid** L2 block hash that should have been asserted. In the proposal manager it will compare the value returned by the fraud proof with the value asserted, and if it is incorrect delete the invalid assertion and slash the asserter's bond. \ No newline at end of file diff --git a/components/fraud-proof-vm/fraud_proof_vm.md b/components/fraud-proof-vm/fraud_proof_vm.md deleted file mode 100644 index a4ff7529efc7..000000000000 --- a/components/fraud-proof-vm/fraud_proof_vm.md +++ /dev/null @@ -1,50 +0,0 @@ -# Fraud Proof VM - -A fraud proof VM (FPVM) is a virtual machine which can be evaluated on-chain to settle a disputed block hash assertion. In this spec we assume the fraud proof VM is evaluated using a multi-round dispute game similar to [Truebit](https://people.cs.uchicago.edu/~teutsch/papers/truebit.pdf). - -## Key Properties - -A Fraud proof VM must satisfy the following properties to be suitable for a multi-round dispute game: -1. Program execution can be split up into deterministic state transitions. -2. Each state transition can be evaluated on-chain with less than or equal to a constant size gas allocation (eg. 10 million L1 gas). -3. The FPVM must be executable off-chain in such a way that state checkpoints (ie. merklized commitments to the VM state) can be generated. - -## Usage - -### Initialization - -The fraud proof VM is initialized with: -1. an executable binary; and -2. an initialization hash for the preimage oracle. - -The executable binary defines the program which is executed during a fraud proof, and the initialization hash is used to load data from the FPVM's database called the `Preimage Oracle`. - - -The fraud proof VM does not have access to a traditional database. Instead, it has access to the "preimage oracle". The preimage oracle is simply a database which exposes the function `get_preimage(hash: bytes)`: - -```python -def get_preimage(hash: bytes) -> bytes: - # The preimage is looked up from a local database held by the fraud prover - preimage = fetch_preimage(hash) - assert keccak256(preimage) == hash - return preimage -``` - -The preimage oracle must be populated with all `hash->preimage` mappings before they are queried by the FPVM. These preimages are committed to in the initialization hash which is supplied as one of the two inputs to the FPVM. During the course of execution, the FPVM must **never** request a preimage which is unavailable as that would result in the FPVM being indeterminate. In this way, a valid executable binary must account for the structure of the initialization hash and only query available preimages. - -### Termination - -The fraud proof VM must terminate with either: - -1. SUCCESS -2. FAIL -3. INDETERMINATE - -If the FPVM returns SUCCESS it may also return a 32 byte value (eg. the valid block hash). If the FPVM returns FAIL it must be handled by the dispute game. - -There are a few conditions under which the FPVM may return FAIL: - -1. Out of memory -- Too much memory was used during execution. -2. Too many instructions -- Too many instructions were consumed (there is a fixed max instructions to prevent DOS attacks on the FPVM). - -The only time in which the FPVM returns INDETERMINATE is when an unavailable preimage is queried. \ No newline at end of file diff --git a/components/rollup_node/README.md b/components/rollup_node/README.md deleted file mode 100644 index 87f19da3480f..000000000000 --- a/components/rollup_node/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# Rollup Node - -The consensus-layer of Optimism. - -This design mirrors the separation of L1 consensus- and execution-layer to L2, -for maximum compatibility and minimal complexity. - -## Summary - -The Rollup Node is a consensus client that tracks the rollup: -- Fork-choice: following L1, a reorg on L1 results in a reorg of L2 -- Input Data: deposits and sequencer data extracted from L1 -- Latest blocks: propagate optimistically via p2p interface, overrideable by L1 - -The input data and forkchoice information collected from L1 (and optimistically via p2p) -are then forwarded to the execution-layer, also known as "execution engine", -via the standard [Engine API][engine-api]. - -The design is minimalist: -- The rollup consensus-layer is largely derived from L1 properties, enabling a simple and stateless L2 consensus. -- The rollup execution-layer is largely shared with L1, equivalent in all ways except the addition of rollup-deposits. - -## Types of Rollup Nodes - -There are two primary classes of rollup nodes, corresponding to different configurations of the software stack. - -1. **Sequencer**: Accepts user-sent and deposit transactions, orders them into L2 blocks, and [submits them in batches][batch-submitter] to L1. -2. **Verifier**: Watches L1 feeds, [reconstructs L2 blocks from inputs][block-gen], and inserts them into the EE to determine the canonical L2 state. - -**Both** update their coupled execution-engine with L2 blocks and fork-choice instructions, to maintain their view of the rollup state. - -Optionally the sequencer(s) may share the L2 blocks via the L2 p2p network before the L1 can confirm them, -which verifiers can optionally use to sync to the very tip of the rollup. -This enables permissionless L1-like latency for users, but not the default until available on the L1. - -The User JSON-RPC exposes these levels of confirmation, -matching the labels in the [Engine API specifications][engine-forkchoice-unsafe-safe-finalized]: -- `unsafe`: when the data is not yet on L1, but known through L2 P2P propagation -- `safe` ("latest" is an alias to this): when the data has been seen to be published to L1, but not undisputed yet -- `finalized`: when the data is irreversibly canonical - -## Services - -### L2 Execution Engine - -The [Execution Engine][exec-engine] (EE) is *separated from the rollup node*, following the separated consensus/execution layer design of L1. - -Execution tasks of the engine include EVM execution, transaction-pool and state sync. -The rollup node communicates to the engine via the [Engine JSON-RPC interface][engine-api] -(Secured and separated from the regular user JSON-RPC). - -Most L1 clients are working on conversion to execution engines, as part of the [The Merge][the-merge]. - -Every execution-engine that is built for L1 can be used, with a minimal set of changes: -- Support a Deposit-transaction type: clean and efficient separation from regular transactions, following [EIP 2718][EIP-2718], similar to EIP-1559 transactions. -- Enable the consensus-layer to specify transactions during payload preparation: L2 blocks can then be formed on just the inputs, and deposits can be processed. -- Adjustment to Fee metering - -All three of these features overlap with forthcoming L1 updates and may be unified at a later stage: -Validator withdrawals, system-transactions, and time-aware base fee calculation [EIP 4396][EIP-4396]. - -### Rollup Driver - -The [Rollup Driver][rollup-driver] is the main service *within the rollup node*, mapping L1 data to L2 chain progress. - -Based on the rules of [block generation][block-gen], it is able to compute sets ("epochs") of L2 blocks as a stateless, pure function of ranges of L1 blocks. - -While connected to the Execution Engine, it uses the Engine API to progress the L2 state as new data comes in from L1. -The rollup driver will instruct the engine to reorganize the L2 state if it detects a difference between the local chain and remote chain as confirmed on L1, -and provides a way for other services to subscribe to reorgs. - -### Block Producer - -The [Block Producer][block-producer] is an optional service to run as sequencer, *within the rollup node*, -to progress the L2 state in advance of batch submission. - -When tasked to produce a new rollup block, the rollup node adds `PayloadAttributesV1` to the `engine_forkchoiceUpdated` -call (see [Engine api][engine-API]) to instruct the engine to start sequencing a block of pending contents from the transaction pool. - -This execution block is then retrieved with `engine_getPayload`, to then be pushed to L1 for availability by the -[Batch submitter][batch-submitter] (optionally packed together with other L2 blocks), -and optionally directly the L2 network for faster tip updates. - -### Batch Submitter - -The [Batch Submitter][batch-submitter] service takes a queue of locally produced payloads, -and submits the corresponding transactions in batches to L1. - -The batch submitter encodes these transactions based on the rules of [block derivation][block-derivation], effectively as the reverse of the process carried out by the rollup driver. As a result: -- Blocks previously inserted by the Block Producer into the Sequencer's EE will now appear in L1 Verifiers' EEs. -- Blocks marked as sequencer-confirmed in both the Sequencer and in Replicating verifiers will now be recognized as L1-confirmed. - -### P2P Interface - -The [P2P Interface][p2p-interface] service offers an additional method of syncing the latest L2 blocks, -faster than the L1 can make them available. - -This is implemented with an optimistic process: -1. Sequencer publishes the L2 block through a lightweight L2 P2P network (single gossip topic) -2. Verifier listens on the P2P network, verifies sequencer signature, and applies the block to their L2 EE. -3. If the data cannot be confirmed on L1, or if conflicting data is confirmed, then the bad L2 block is reorganized away. - -This service is optional: while the worst-case data-retrieval is covered by L1 in the same way, the happy-path improves: -- Verifiers can stay in sync with the tip of the rollup with lower latency -- Sequencers can distribute the server work - -The amount of L2 blocks that can be optimistically applied to the L2 EE is constrained -by the supported reorg-depth by the execution engine, to preserve the ability to process reorgs of the L2 by L1: -ultimately the L1 chain determines the canonical rollup chain. - - -[engine-api]: https://github.com/ethereum/execution-apis/tree/main/src/engine -[the-merge]: https://eips.ethereum.org/EIPS/eip-3675 -[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -[EIP-4396]: https://eips.ethereum.org/EIPS/eip-4396 -[engine-forkchoice-unsafe-safe-finalized]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#forkchoicestatev1 -[block-gen]: ./block_gen.md -[exec-engine]: ./exec_engine.md -[rollup-driver]: ./consensus_layer.md -[block-producer]: ./block_producer.md -[batch-submitter]: ./batch_submitter.md -[p2p-interface]: ./p2p_interface.md diff --git a/components/rollup_node/batch_submitter.md b/components/rollup_node/batch_submitter.md deleted file mode 100644 index 5bfe907c18db..000000000000 --- a/components/rollup_node/batch_submitter.md +++ /dev/null @@ -1,2 +0,0 @@ -# Batch Submitter -TODO, see README for now. \ No newline at end of file diff --git a/components/rollup_node/block_derivation.md b/components/rollup_node/block_derivation.md deleted file mode 100644 index 1ec72676d3db..000000000000 --- a/components/rollup_node/block_derivation.md +++ /dev/null @@ -1,147 +0,0 @@ -# Block derivation - -The logic which is used to derive the rollup chain from an L1 availability layer. - -## Summary - -The rollup chain can be deterministically derived given an L1 Ethereum chain. The fact that the entire rollup chain can be derived based on L1 blocks is _what makes OE a rollup_. This process can be represented as: - -``` -derive_rollup_chain(l1_blockchain) -> rollup_blockchain -``` - -In this document we define a block derivation function which is designed to: - -1. Require no state other than what is easily accessible using L1 and L2 execution engine APIs. -2. Support sequencers and sequencer consensus. -3. Resilient sequencer censorship. - -## Rollup Epochs - -The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers. For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be derived after L1 block number `n` is added to the L1 chain. An epoch contains one to many rollup blocks. - -### Types of Blocks within Epochs - -Within these epochs, there are two block types: - -1. Deposit block -2. Sequencer block - -Deposit blocks contain contextual information about L1 such as the block hash. They also contain transactions initiated on L1 by any user or contract that execute on L2. - -Sequencer blocks are submitted by the sequencer and target _future_ epochs which satisfy the following two conditions: - -1. Target epoch is larger than the current L1 block number. -2. Target epoch is less than the current L1 block number PLUS `sequencing_window_size`. - -The ability for the sequencer to append sequencer blocks to future epochs allows the sequencer to predict and influence the state of the epoch before the L1 chain has mined it. This property is what enables _fast transaction confirmations_ via the sequencer replicator. - -### Epoch Structure - -Each epoch contains **1** deposit block and zero to many sequencer blocks. For epoch `n` the deposit block is derived using L1 block number `n - (sequencing_window_size + 1)`. The epoch's sequencer blocks are contained in any of the L1 blocks ranging from `n - sequencing_window_size` to `n`. This a range of blocks is called the "sequencing window". - -The following diagram demonstrates the correspondence between L1 blocks and rollup blocks (ie L2 blocks): - -![Sequencer block derivation diagram](../../assets/sequencer-block-derivation.svg) - -## Deposit Blocks in Depth - -For every L1 block (after the rollup's genesis) an L2 deposit block is created. These deposit blocks contain both a `ContextDeposit` and any number of `UserDeposit`s. Context deposits set contextual information about the latest L1 block (eg. `blockHash` and `timestamp`), and user deposits are L1 user initiated L2 transactions which guarantee liveness of the rollup chain even with a censoring sequencer. - -The deposit block types are as follows: - -```python -class DepositBlock(Block): - deposits: List[Deposit] - -class Deposit: - feedIndex: uint64 - GasLimit: uint64 - -class UserDeposit(Deposit): - isEOA: bool - l1TxOrigin: Address - target: Address - data: bytes - -class ContextDeposit(Deposit): - blockHash: bytes32 - blockNumber: uint64 - timestamp: uint64 - baseFee: uint64 -``` - -### Deposit Block derivation - -The function `derive_deposit_block(l1_block_number)` is defined as: - -- Derive the `ContextDeposit` using the L1 block body. Specifically the L1 block's `blockHash`, `blockNumber`, `timestamp`, and `baseFee`. -- Get all events emitted by the `DepositFeed` contract at block `l1_block_number`. - - For each event, derive a new `UserDeposit` based on the emitted calldata. All fields should be emitted by DepositFeed contract. - -#### **Footnote**: The DepositFeed ensures that no matter the size of the event it is possible to prove the deposit data to the fraud proof. See the DepositFeed spec for details. - -## Sequencer Blocks in Depth - -Sequencer blocks contain a majority of the transactions submitted to the rollup chain. Sequencer blocks can also influence the current timestamp of L2 which is exposed to contracts & is used in the EIP1559 fee pricing calculations. - -Sequencer blocks are of the following form: - -```python -class SequencerBlock(Block): - target_epoch: uint64 # epoch number that this block is intended for - sequencer_suggested_timestamp: uint64 # a timestamp suggested by the sequencer - transactions: List[Transaction] # A list of transactions in the block -``` - -These sequencer blocks must be validated as properly formatted. These validity checks are: - -1. `target_epoch` must be within the sequencing window (introduced in the previous sections) -2. `sequencer_suggested_timestamp` must be monotonic & within an acceptable range. -3. `transactions` must all be correctly formatted (eg. contain valid signatures). - -If any of these checks fail the block must be skipped or ignored. Otherwise, all transactions in the sequencer block will be executed. - -## Timestamps in Depth - -Time can be set by the sequencer; however, it must stay within reasonable bounds and must be monotonic (ie. can never go backwards). The specific conditions that must be met are: - -```python -# last_l1_timestamp is the L1 timestamp set during the last ContextDeposit -# last_timestamp is the timestamp from the previous rollup block -# average_l1_block_time is the average time between two L1 blocks -# sequencing_window_size is the number of L1 blocks the sequencer has to submit their blocks -min_timestamp = max(last_l1_timestamp, last_timestamp) -max_timestamp = last_l1_timestamp + sequencing_window_size * average_l1_block_time - -assert sequencer_suggested_timestamp >= min_timestamp -assert sequencer_suggested_timestamp <= max_timestamp -``` - -The timestamp exposed on the rollup chain is: - -```python -# last_sequencer_suggested_timestamp is the most recent valid sequencer_suggested_timestamp -def timestamp(): - max(last_l1_timestamp, last_sequencer_suggested_timestamp) -``` - - -## Rollup Epoch Generation - -- To derive the blocks in epoch `n`, query L1 blocks `n - (sequencing_window_size + 1)` through `n`. Store the result in an array `l1_blocks`. -- The first block in the epoch is always the deposit block. - - Derive the deposit block with `derive_deposit_block(l1_blocks[0])` (function defined above). - - Append the deposit block the rollup chain. -- The rest of the blocks in the epoch are sequencer blocks. To derive these sequencer blocks, for each block in `l1_blocks`: - - Extract the sequencer feed elements. - - For each sequencer feed element in the L1 block: - - Assert the target epoch is correct (`target_epoch == n`). If not skip over this feed element. - - If the feed element is targetting the correct epoch, check that the sequencer feed element produces a valid block: - - Assert the sequencer feed element was appended by the current sequencer public key (the current public key may exist in L2 state). - - Assert the `sequencer_suggested_timestamp` is valid (see timestamp section for details) - - Assert all transactions included in the sequencer feed element are valid. - - If all checks pass, append the sequencer block to the rollup chain. Otherwise throw out the invalid feed element. -- At this point we will have appended all rollup blocks in epoch `n` to the rollup chain. - -In order to derive the full rollup chain, repeat this process until `n==latest_l1_block_number` indicating that we have reached the tip of L1. \ No newline at end of file diff --git a/components/rollup_node/block_producer.md b/components/rollup_node/block_producer.md deleted file mode 100644 index 376bbddeb11a..000000000000 --- a/components/rollup_node/block_producer.md +++ /dev/null @@ -1,2 +0,0 @@ -# Block Producer -TODO, see README for now. \ No newline at end of file diff --git a/components/rollup_node/exec_engine.md b/components/rollup_node/exec_engine.md deleted file mode 100644 index 111eccd58b09..000000000000 --- a/components/rollup_node/exec_engine.md +++ /dev/null @@ -1,29 +0,0 @@ -# L2 Execution Engine - -## Overview - -The L2 execution engine is where transaction execution actually takes place, and is where all L2 state is held. Its goal is to be as similar to L1 nodes as possible by using the Eth2 Merge Engine API. In normal Eth2, the consensus node sends execution payloads (essentially eth1 blocks, without proof of work) from the beacon chain into the engine. In Optimistic Ethereum, the Rollup Driver (and perhaps other components, depending on the type of Rollup Node) sends L2 blocks that are canonically derived from L1 into the engine. - -## Differences between L1 and L2 EE - -1. **Deposit TX Type**: There is a new typed transaction which corresponds to deposits. This is a cross-chain message type; not propagated by the mempool, only insertable by the rollup node in correspondence to an on-chain event. This transaction type is also able to mint deposited ETH as new native L2 `account.value`. -2. **Deposit Insertability**: The TX type described above must be L1-authenticated and deterministically applied, and therefore cannot come from the unauthenticated mempool. This requires adding a `Transaction[]` argument to [`engine_perparePayload`](https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.2/src/engine/interop/specification.md#engine_preparepayload). -3. **Fee payment modification**: ETH is charged in addition to the `gasPrice * gasUsed`, to compensate the sequencer for rolling up the user transaction. This should be consistent with the [existing OVM 2.0 fee scheme](https://community.optimism.io/docs/users/fees-2.0.html), but using the L1 context information directly instead of via an oracle. -4. **EIP1559 modification**: Updates to the `BASEFEE` on L2 must be handled differently, in accordance to L1 time, as L2 blocktime may not be constant. (*Note: this modification may not be necessary; L1 devs are actively discussing modification of eip-1559 to handle "gap-slots" which would solve for the same timing.*) -5. **L1 Context Information**: The L1 blockhash, L1 blocknumber, and L1 basefee are frequently requested to be accessible within L2. *(TBD: it is possible to expose this information purely in a normal L2 contract, which is updated via the deposit TX type. This may minimize the diff more.)* -6. **Confirmation Status**: The Execution Engine will repurpose (but not otherwise modify) the three beacon chain confirmation strengths (`finalized, safe, unsafe`) to corresponding to (`l1_finalized, l1_confirmed, sequencer_confirmed`). - -## Engine usage - -### `engine_forkchoiceUpdatedV1` - -TODO - -### `engine_getPayloadV1` - -TODO - -### `engine_executePayloadV1` - -TODO - diff --git a/components/rollup_node/p2p_interface.md b/components/rollup_node/p2p_interface.md deleted file mode 100644 index bc7ade7579a3..000000000000 --- a/components/rollup_node/p2p_interface.md +++ /dev/null @@ -1,208 +0,0 @@ -# P2P Interface - -This peer-to-peer (P2P) network service in the rollup node is optional, -but greatly improves the latency between the view of sequencers and the rest of the network, -as well as enabling faster historical sync to be bootstrapped, without relying on a single endpoint. - -In summary, the P2P stack looks like: -- Discovery to find peers: [Discv5][discv5] -- Connections, peering, transport security, multi-plexing, gossip: [LibP2P][libp2p] - -This document only specifies the composition and configuration of these network libraries. -These components have their own standards, implementations in Go/Rust/Java/Nim/JS/more, -and adopted several other blockchains, most notably the [L1 consensus layer (Eth2)][eth2-p2p]. - -## P2P configuration - -### Identification - -Nodes have a **separate** network- and consensus-identity. -The network identity is a `secp256k1` key, used for both discovery and active LibP2P connections. - -Common representations of network identity: -- `PeerID`: a LibP2P specific ID derived from the pubkey (through protobuf encoding, typing and hashing) -- `NodeID`: a Discv5 specific ID derived from the pubkey (through hashing, used in the DHT) -- `Multi-address`: an unsigned address, containing: IP, TCP port, PeerID -- `ENR`: a signed record used for discovery, containing: IP, TCP port, UDP port, signature (pubkey can be derived) and L2 network identification. Generally encoded in base64. - -### Discv5 - -#### Structure - -The Ethereum Node Record (ENR) for an Optimism rollup node must contain the following values, identified by unique keys: - -- An IPv4 address (`ip` field) and/or IPv6 address (`ip6` field). -- A TCP port (`tcp` field) representing the local libp2p listening port. -- A UDP port (`udp` field) representing the local discv5 listening port. -- An Optimism (`optimism` field) L2 network identifier - -The `optimism` value is encoded as the concatenation of: -- chain ID (`varint`) -- fork ID (`varint`) - -Note that DiscV5 is a shared DHT (Distributed Hash Table): the L1 consensus and execution nodes, as well as testnet nodes, -and even external IOT nodes, all communicate records in this large common DHT. -This makes it more difficult to censor the discovery of node records. - -The discovery process in Optimism is a pipeline of node records: -1. Fill the table with `FINDNODES` if necessary (Performed by Discv5 library) -2. Pull additional records with searches to random Node IDs if necessary (e.g. iterate [`RandomNodes()`][discv5-random-nodes] in Go implementation) -3. Pull records from the DiscV5 module when looking for peers -4. Check if the record contains the `optimism` entry, verify it matches the chain ID and current or future fork number -5. If not already connected, and not recently disconnected or put on deny-list, attempt to dial. - -### LibP2P - -#### Transport - -TCP transport. Additional transports are supported by LibP2P, but not required. - -#### Dialing - -Nodes should be publicly dialable, not rely on relay extensions, and able to dial both IPv4 and IPv6. - -#### NAT - -The listening endpoint must be publicly facing, but may be configured behind a NAT. -LibP2P has optional automation for this. - -#### Peergating and pruning - -TODO: max-peers, grace periods, pruning - -#### Transport security - -[Libp2p-noise][libp2p-noise], `XX` handshake, with the the `secp256k1` P2P identity, as popularized in Eth2. - -#### Protocol negotiation - -[Multistream-select 1.0][multistream-select] (`/multistream/1.0.0`) is an interactive protocol -used to negotiate sub-protocols supported in LibP2P peers. Multistream-select 2.0 may be used in the future. - -#### Identify - -LibP2P offers a minimal identification module to share client version and programming language. -This is optional and can be disabled for enhanced privacy. -It also includes the same protocol information, which can speed up initial connections. - -#### Multiplexing - -For async communication over different channels over the same connection, multiplexing is used. -[mplex][mplex] (`/mplex/6.7.0`) is required, and [yamux][yamux] (`/yamux/1.0.0`) is recommended but optional - -#### GossipSub - -[GossipSub 1.1](gossipsub) (`/meshsub/1.1.0`, i.e. with peer-scoring extension) is a pubsub protocol for mesh-networks, -deployed on L1 consensus (Eth2) and other protocols such as Filecoin, offering lots of customization options. - -##### Content-based message identification - -Messages are deduplicated, and filtered through application-layer signature verification. -Thus origin-stamping is disabled and published messages must only contain application data, -enforced through a [`StrictNoSign` Signature Policy][signature-policy] - -This provides greater privacy, and allows sequencers (consensus identity) to maintain -multiple network identities for redundancy. - -##### Message compression and limits - -The application contents are compressed with [snappy][snappy] single-block-compression -(as opposed to frame-compression), and constrained to 10 MiB. - -##### Message ID computation - -[Same as L1][l1-message-id], with recognition of compression: -* If `message.data` has a valid snappy decompression, set `message-id` to the first 20 bytes of the `SHA256` hash of - the concatenation of `MESSAGE_DOMAIN_VALID_SNAPPY` with the snappy decompressed message data, - i.e. `SHA256(MESSAGE_DOMAIN_VALID_SNAPPY + snappy_decompress(message.data))[:20]`. -* Otherwise, set `message-id` to the first 20 bytes of the `SHA256` hash of - the concatenation of `MESSAGE_DOMAIN_INVALID_SNAPPY` with the raw message data, - i.e. `SHA256(MESSAGE_DOMAIN_INVALID_SNAPPY + message.data)[:20]`. - -#### Heartbeat and parameters - -GossipSub [parameters][gossip-parameters]: - -- `D` (topic stable mesh target count): 8 -- `D_low` (topic stable mesh low watermark): 6 -- `D_high` (topic stable mesh high watermark): 12 -- `D_lazy` (gossip target): 6 -- `heartbeat_interval` (frequency of heartbeat, seconds): 1.0 -- `fanout_ttl` (ttl for fanout maps for topics we are not subscribed to but have published to, seconds): 24 -- `mcache_len` (number of windows to retain full messages in cache for `IWANT` responses): 6 -- `mcache_gossip` (number of windows to gossip about): 3 -- `seen_ttl` (number of heartbeat intervals to retain message IDs): 40 - -Notable differences from L1 consensus (Eth2): -- `seen_ttl` does not need to cover a full L1 epoch (6.4 minutes), but rather just a small window covering latest blocks -- `fanout_ttl` adjusted to lower than `seen_ttl` -- `heartbeat_interval` lowered for bandwidth saving, since there are less messages per second (no 600 attestations every second) - - -#### Topic configuration - -Topics have string identifiers and are communicated with messages and subscriptions. -`/optimism/chain_id/hardfork_version/Name` - -- `chain_id`: replace with decimal representation of chain ID -- `hardfork_version`: replace with decimal representation of hardfork -- `Name`: topic application-name - -Note that the topic encoding depends on the topic, unlike L1, since there are less topics, and all are snappy-compressed. - -## Gossip Topics - -### `blocks` - -The primary topic of the L2, to distribute blocks to other nodes faster than proxying through L1 would. - -#### Block encoding - -TODO: encode execution payload (SSZ or RLP), with sequencer identifier and signature. - -TODO: signature type and verification (options: `secp256k1` like transactions, or `BLS12-381` with pubkeys on G1, like L1) - -#### Block validation - -To ensure malicious peers get scored based on application behavior the validation signals -`ACCEPT` (valid), `IGNORE` (like inactivity) or `REJECT` (score penalties). - -In order of operation: -- `[REJECT]` if the encoding or compression is not valid -- `[REJECT]` if the block timestamp is older than 20 seconds in the past (graceful boundary for worst-case propagation and clock skew) -- `[REJECT]` if the block timestamp is more than 5 seconds into the future (graceful boundary for clock skew) -- `[REJECT]` if the signature by the sequencer is not valid -- `[REJECT]` if more than 5 blocks have been seen with the same block height -- `[IGNORE]` if a conflicting block was already seen on L1. It may not be malicious due to racing between L1 confirmation and L2 propagation, but should be filtered out. - -The block is signed by the corresponding sequencer, to filter malicious messages. -The sequencer model is singular but may change to multiple sequencers in the future. -A default sequencer pubkey is distributed with rollup nodes and should be configurable. - -##### Block processing - -A node may apply the block to their local engine ahead of L1 availability, if it ensures that: -- The application of the block is reversible, in case of a conflict with delayed L1 information -- The subsequent forkchoice-update ensures this block is recognized as "unsafe" (see [`engine_forkchoiceUpdatedV1`](./exec_engine.md#engine_forkchoiceupdatedv1)) - -##### Block topic scoring parameters - -TODO: GossipSub per-topic scoring to fine-tune incentives for ideal propagation delay and bandwidth usage. - ----- - -[consensus-layer]: ./consensus_layer.md -[libp2p]: https://libp2p.io/ -[discv5]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md -[discv5-random-nodes]: https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.10.12/p2p/discover#UDPv5.RandomNodes -[eth2-p2p]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md -[libp2p-noise]: https://github.com/libp2p/specs/tree/master/noise -[multistream-select]: https://github.com/multiformats/multistream-select/ -[mplex]: https://github.com/libp2p/specs/tree/master/mplex -[yamux]: https://github.com/hashicorp/yamux/blob/master/spec.md -[gossipsub]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md -[signature-policy]: https://github.com/libp2p/specs/blob/master/pubsub/README.md#signature-policy-options -[snappy]: https://github.com/google/snappy -[l1-message-id]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#topics-and-messages -[gossip-parameters]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.0.md#parameters - diff --git a/components/rollup_node/rollup_driver.md b/components/rollup_node/rollup_driver.md deleted file mode 100644 index 79ceff1b5563..000000000000 --- a/components/rollup_node/rollup_driver.md +++ /dev/null @@ -1,27 +0,0 @@ -# Rollup Driver - -The Rollup Driver is the core code which guarantees that the canonical L1 state is accurately reflected in the EE. It does this by connecting to an L1 node, and using the pure function which maps L1 blocks to L2 block inputs as defined by [block derivation][block-derivation]. Once it knows the block inputs, it checks the EE to make sure that the blocks there all have the correct inputs. - -This is a functionality that is shared between all configurations of the rollup node, including the sequencer. Because block derivation defines the L1 block -> L2 block input transformation as a pure function, it can be completely stateless and has no DB. - -## Basic Functionality - -We define the `latestL1ConfirmedL2Block` as the latest L2 block in the EE which is marked as L1-confirmed. This can be found by starting at the head of the L2 EE, and iterating backwards until we find the first L2 block which is marked as L1-confirmed. - -The core logic which the CL executes is as follows. - -1. Find `latestL1ConfirmedL2Block`. Then get `latestL1ConfirmedL2Block.l1BlockNumber` and `latestL1ConfirmedL2Block.l1BlockHash` from the EE. Compare these to L1 with an RPC query to the L1 node's RPC. - - if they DO match, continue to 2. - - if they DO NOT match, then there has been an L1 reorg. In that case: - - Signal the reorg. - - Iterate backwards until we find the latest L2 block whose `l1BlockNumber` and `l1BlockHash` DO match the L1 node RPC. - - Set the EE's head to this L2 block (thereby updating `latestL1ConfirmedL2Block`). -2. Iterate forward through L1 blocks, starting from `latestL1ConfirmedL2Block.l1BlockNumber + 1`. For each: - - Derive the L2 block inputs for this L1 block as defined by [block derivation][block-derivation]. For each L2 block input: - - If the L2 block DOES NOT exist in the EE already, insert it and update the EE head. - - If the L2 block DOES exist in the EE already (as sequencer confirmed), then compare the derived block input to the existing block input. - - If they DO match, mark the L2 block as L1 confirmed. - - If they DO NOT match, there has been an L2 reorg. Signal the reorg, insert the correct block, and update the EE head. -3. Wait and GOTO 1. - -[block-derivation]: ./components/rollup_node/block_derivation.md \ No newline at end of file diff --git a/components/witness_gen.md b/components/witness_gen.md deleted file mode 100644 index 64acf232a9fb..000000000000 --- a/components/witness_gen.md +++ /dev/null @@ -1 +0,0 @@ -# Fraud Proof Witness Generator diff --git a/glossary.md b/glossary.md deleted file mode 100644 index 8828b10a0f2f..000000000000 --- a/glossary.md +++ /dev/null @@ -1,89 +0,0 @@ -# Glossary of Optimistic Ethereum Terms - -### Layer 1 (L1) - -An Ethereum network with its own native security mechanism (e.g., proof of work, proof of stake or proof of authority). - -### Layer 2 (L2) - -A network that derives its security from a layer one. - -### L2 State Root Oracle - -A smart contract on L1, providing access to historical L1 block hashes. The existence of this contract makes it possible to prove the existence of a particular L2 state root within a previous L1 block. - -### Block Generation (AKA Block Derivation) - -All of the data necessary to reconstruct the history and state of L2 is contained within L1 blocks. Block Generation is the process of converting data contained in L1 blocks into L2 blocks. - -### Epoch - -A continuous sequence of 0 or more L2 blocks. There is a one to one correspondence between L2 Epochs, and L1 blocks. -A continuous sequence of L2 blocks, including a single deposit block, followed by 0 or more L2 blocks. There is a one to one correspondence between L2 Epochs, and L1 blocks.``` -**Example usage:** "Epoch 20 corresponds to L1 block 637, epoch 21 corresponds to block 638, etc". - -### Feeds - -Feeds are append only lists, each of which is contained in a smart contract on Layer 1. The state of the Rollup Chain is determined by the data written to these contracts. - -### Sequencer Feed - -The Sequencer Feed is a contract which contains the data representing sequencer submitted blocks, each element in this feed will be used to generate a "sequencer block". - -### Deposit Feed - -The Deposit Feed is a contract which contains deposit data. Each element in this feed will be used to generate a "deposit block". - -### Sequencing Window - -The number of L1 blocks during which the Sequencer _may_ insert Sequencer blocks before a Deposit block. - -If the Sequencer Window is 2 blocks, and Alice makes a Deposit in Block 420, her deposit WILL be included (by the Block Generation process) at block 422. - -### Execution Environment (EE) - -The virtual machine in which transactions are applied to the pre-state to generate the post-state. - -### Rollup Node AKA Rollup Driver - -The core client software which reads data from an L1 node, and transforms it into L2 data. Both the Sequencer, and Verifier nodes run a Rollup Node, albeit in different configurations. - -### Consensus Layer - -By analogy to the architecture of ETH2 we can also describe Layer 1 as the "Consensus Layer", as it defines the canonical history and state of the Layer 2 chain. - -### Sequencer - -The privileged entity which accepts L2 transactions from users, and determines the ordering of those transactions with respect to each other and deposit transactions. - - -### Verifier - -A verifier is any Rollup Node operator who is not the Sequencer. Verifiers compute the state of the L2 chain, and compare it to the states proposed by the Sequencer. - -### Deposit transaction (via the Deposit Feed) - -A transaction which originates on L1, by way of a message sent to the Deposit Feed contract. This message can be sent either by a contract or an externally owned account. - -### Sequencer transaction (via the Sequencer feed) - -A transaction which is sent directly to the sequencer from user. - -### L2 State Oracle (AKA L2 Block Oracle) - -The on-chain component to which the Sequencer writes the L2 state roots. -The L2 State oracle also implements the k-section game, and single step verifier. - -### Single Step Verifier - -An on-chain - -### Dispute game - -The Dispute Game is the process by which a verifier - - -### Preimage -### Pure function - - diff --git a/introduction.md b/introduction.md deleted file mode 100644 index a9f75267a63f..000000000000 --- a/introduction.md +++ /dev/null @@ -1,132 +0,0 @@ -# Optimistic Ethereum Introduction - -Optimistic Ethereum is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_ while remaining maximally compatible with existing Ethereum infrastructure. This document provides an overview of the protocol to provide context for the rest of the specification. - -## Table of Contents -1. [Foundations](#foundations) -2. [Protocol Guarantees](#protocol-guarantees) -3. [Network Participants](#network-participants) -4. [Key Interaction Diagrams](#key-interaction-diagrams) - - [Depositing and Transacting](#depositing-and-sending-transactions) - - [Withdrawing](#withdrawing) - - [Verifying the Network](#verifying-the-network) -5. [Next Steps](#next-steps) - -## Foundations - -### What is Ethereum scalability? - -Scaling Ethereum means increasing the number of useful transactions the Ethereum network can process. Ethereum's limited resources, specifically bandwidth, computation, and storage, constrain the number of transactions which can be processed on the network. Of the three resources, computation and storage are currently the most significant bottlenecks. These bottlenecks limit the supply of transactions, leading to extremely high fees. Scaling Ethereum and reducing fees can be achieved by increasing the supply of these limited resources. - -### What is Optimistic Rollup? - -[Optimistic rollup](https://vitalik.ca/general/2021/01/05/rollup.html) is a layer 2 scalability technique which increases the computation & storage capacity of Ethereum without sacrificing security or decentralization. Transaction data is submitted on-chain but executed off-chain. If there is an error in the off-chain execution, a fraud proof can be submitted on-chain to correct the error and protect user funds. In the same way you don't go to court unless there is a dispute, you don't execute transactions on on-chain unless there is an error. - -### What is EVM Equivalence? - -[EVM Equivalence](https://medium.com/ethereum-optimism/introducing-evm-equivalence-5c2021deb306) is complete compliance with the state transition function described in the Ethereum yellow paper, the formal definition of the protocol. By conforming to the Ethereum standard across EVM equivalent rollups, smart contract developers can write once and deploy anywhere. - -### 🎶 All together now 🎶 - -#### Optimistic Ethereum is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_. - -## Protocol Guarantees - -In order to scale Ethereum without sacrificing security, we must preserve 3 critical properties of Ethereum layer 1: liveness, availability, and validity. - -1. **Liveness** - Anyone must be able to extend the rollup chain by sending transactions at any time. - - There are two ways transactions can be sent to the rollup chain: 1) via the sequencer, and 2) directly on layer 1. The sequencer provides low latency & low cost transactions, while sending transactions directly to layer 1 provides censorship resistance. -2. **Availability** - Anyone must be able to download the rollup chain. - - All information required to derive the chain is embedded into layer 1 blocks. That way as long as the layer 1 chain is available, so is the rollup. -3. **Validity** - All transactions must be correctly executed and all withdrawals correctly processed. - - The rollup state and withdrawals are managed on an L1 contract called the `L2 State Oracle`. This oracle is guaranteed to _only_ finalize correct (ie. valid) rollup block hashes given a **single honest verifier** assumption. If there is ever an invalid block hash asserted on layer 1, an honest verifier will prove it is invalid and win a bond. - -**Footnote**: There are two main ways to enforce validity of a rollup: fraud proofs (optimistic rollup) and validity proofs (zkRollup). For the purposes of this spec we only focus on fraud proofs but it is worth noting that validity proofs can also be plugged in once they have been made feasible. - -## Network Participants - -There are three actors in Optimistic Ethereum: users, sequencers, and verifiers. - -![Network Overview](./assets/network-participants-overview.svg) - -### Users - -At the heart of the network are users (us!). Users can: - -1. Deposit or withdraw tokens by sending transactions to Ethereum mainnet. -2. Use EVM smart contracts on layer 2 by sending transactions to the sequencers. -3. View the status of transactions using block explorers provided by network verifiers. - -### Sequencers - -The sequencer is the primary block producer. There may be one sequencer **or** many using a consensus protocol. For 1.0.0, there is just one sequencer. In general, specifications may use "the sequencer" to be a stand-in term for the consensus protocol operated by multiple sequencers. - -The sequencer: -1. Accepts user off-chain transactions (exposes `eth_sendRawTransaction`, validates fees, ...) -2. Observes on-chain transactions (primarily, deposit events coming from L1) -3. Consolidates both kinds of transactions into L2 blocks with a specific ordering. -4. Propagates consolidated L2 blocks to L1, by submitting two things as calldata to L1: - - The pending off-chain transactions accepted in step 1. - - Sufficient information about the ordering of the on-chain transactions to successfully reconstruct the blocks from step 3., purely by watching L1. - -The sequencer also provides access to block data as early as step 3., so that users may access real-time state in advance of L1 confirmation if they so choose. - -### Verifiers - -Verifiers serve two purposes: - -1. Serving rollup data to users; and -2. Verifying rollup integrity and disputing invalid assertions. - -In order for the network to remain secure there must be **at least** one honest verifier who is able to verify the integrity of the rollup chain & serve blockchain data to users. - -## Key Interaction Diagrams - -The following diagrams demonstrate how protocol components are utilized during key user interactions in order to provide context when diving into any particular component specification. - -### Depositing and Sending Transactions - -Users will often begin their L2 journey by depositing ETH from L1. Once they have ETH to pay fees, they'll start sending transactions on L2. The following diagram demonstrates this interaction and all key Optimistic Ethereum components which are utilized: - -![Diagram of Depositing and Sending Transactions](./assets/sequencer-handling-deposits-and-transactions.svg) - -Links to components mentioned in this diagram: - -- Rollup Feeds (WIP) -- Rollup Node (WIP) -- Execution Engine (WIP) -- Sequencer Batch Submitter (WIP) -- L2 State Oracle (WIP) -- Block Hash Assertion Submitter (WIP) -- Fraud Proof VM (WIP) - -### Withdrawing - -Just as important as depositing, it is critical that users can withdraw from the rollup. Withdrawals are initiated by normal transactions on L2, but then completed using a transaction on L1 after the dispute period has elapsed. - -![Diagram of Withdrawing](./assets/user-withdrawing-to-l1.svg) - -Links to components mentioned in this diagram: - -- Rollup Feeds (WIP) -- L2 State Oracle (WIP) -- Bridge (WIP) - - -### Verifying The Network - -To ensure only valid withdrawals are processed, it is critical that verifiers check each block hash assertion that the sequencer makes and disputes it if there is an error. The following diagram demonstrates a verifier on the network that detects an invalid assertion and submits a dispute, thereby protecting user funds: - -![Diagram of a verifier disputing an assertion](./assets/verifier-executing-fraud-proof.svg) - -Links to components mentioned in this diagram: - -- Rollup Node (WIP) -- Execution Engine (WIP) -- L2 State Oracle (WIP) -- Challenger Agent (WIP) -- Fraud Proof VM (WIP) - -## Next Steps - -This is a choose your own adventure. Are you interested in how a verifier works under the hood? Maybe you want to dive deep into the bit flippin' Fraud Proof VM? All key components have been linked at least once in this doc, so you should now have the context you need to dive in deeper. [The world is yours](https://www.youtube.com/watch?v=e5PnuIRnJW8)! \ No newline at end of file diff --git a/layer-1-contracts/README.md b/layer-1-contracts/README.md deleted file mode 100644 index a112044a8614..000000000000 --- a/layer-1-contracts/README.md +++ /dev/null @@ -1,20 +0,0 @@ -layer-1-contracts/README.md# Layer 1 Contracts - -## Design Goals -We want our ORU contracts to be built in compliance with the following goals: -- A **pluggable state machine** which: - - allows separation of concerns and parallelizable work - - is fully stateless, i.e. all state transitions can be expressed in the form `bytes32 _inputHash, bytes _witness => bytes32 _outputhash` and are only dependent on the immediately preceding pre-state -- A cryptoeconomic **L2 State Oracle** which: - - Provides a cryptoeconomic mechanism to propose, assert, challenge, and finalize optimistic states of the L2 machine - - Does NOT require that the entire execution trace is provable, just the execution output - - i.e. an honest party may not necessarily ever post a hash of the full trace - - DOES require that there is a winning strategy for all correct state proposals - - DOES require that there is a winning strategy for challenging all incorrect state proposals - - Provides access to L2 block hashes, which may not be equal to the `_inputHash`es above - - Is optimized to minimize the number of rounds of interaction, so as to be most resistant to hostile L1 censorship and griefing -- A set of **data feed** contracts which: - - allow parties and contracts to provide inputs which are processed by the L2 machine - - allow verifiability of those inputs for disputes - - is highly gas-efficient -- A useful **message-passing abstraction** which can be used to easily send messages (e.g. deposits and withdrawals) between L1 and L2 with a consistent interface diff --git a/overview.md b/overview.md deleted file mode 100644 index 55b9cf7507d8..000000000000 --- a/overview.md +++ /dev/null @@ -1,114 +0,0 @@ -# Optimistic Ethereum Overview -*// Note: this section assumes you've read the [introduction](./introduction.md)!* -## Arcitecture Design Goals - -- Execution-Level EVM Equivalence - - The developer experience should be indentical to L1 except where L2 introduces a fundamental difference. - - No special compiler - - No unexpected gas costs - - Out-of-the-box TX traces - - All tooling "just works"--configure chain ID, good to go - - Fundamental L2 differences are limited to the bare minimum, still use existing L1 standards, and require only block-level modifications. These include: - - Fee logic which accounts for L1 calldata costs (still uses existing L1 tx type) - - A new transaction type for deposits (still uses L1 tx envelope schema) - - EIP1559 algorithm that accounts for L2 blocktimes -- Maximal compatibility with Eth1 nodes - - Uses the ETH2 merge's Engine API for: - - Fork-choice: change head based on L1 reorgs of data (and leverage undisputed state-roots for finalized checkpoint) - - Block-production: sequencing blocks with any Eth1 node - - Block-insertion: Eth1 node has specialized EVM and DB, valuable for L2, instead of reinventing the wheel - - Leverages sync: verify block inputs based on L1, but do state-sync via L2 p2p network - - Leverage tx propagation: can use existing mempool infrastructure -- Simple, stateless services - - Whenever possible (e.g. in batch submitter and synchronizer), services contributing to the rollup infrastructure do not persist state - - Given an L1 node, and an L2 execution engine, all other services can recover to full operation when started with a fresh DB - -## Components - -![Architecture Diagram](./assets/architecture.svg) - -### L1 Components -- **Feeds**: ("Data availability layer"): A **feed** is an append-only log of data (e.g. of deposits, or sequencer batches). Feeds can be computed as functions of L1 block data. The definition of these functions can be found in the [block derivation spec][block-derivation]. Optimistic Ethereum has three primary feeds: - - **Deposit Feed**: A feed of L2 transactions which originated as smart contract calls in the L1 state which emitted an event. Deposits are guaranteed to be reflected in the L2 state within the *sequencing window*. - - **Sequencer Feed**: A feed of L2 transactions which are submitted by the sequencer to L1 in batches. Includes L2 tx calldata, *as well as time and ordering information.* - - **L2 Block Feed**: A feed of canonical L2 block inputs (i.e. L2 blocks, but without the `stateRoot`, `receiptsRoot`, `gasUsed`, ...) which should be executed by L2 nodes and enforced in fraud proofs. - - ***The L2 Block Feed is a pure function of the Deposit Feed and Sequencer Feed.*** That is, given the Deposit Feed and Sequencer Feed, the L2 Block Feed can be reconstructed, even without full L1 blockdata. - - In general, all feeds must enforce that: - - All entries are deterministically indexable by off-chain parties. - - The fraud proof VM can find any feed entry in a bounded number of steps, such that the off-chain indexing is sufficient to generate a witness for verifing any individual step on-chain. - - Note: a "feed" may not necessarily correspond to an on-chain contract (e.g. which stores a hash of each entry). Instead, a feed refers to the actual log of data which is derivable from L1, which may or may not use a contract. For more info, check out [this discussion.](https://github.com/ethereum-optimism/optimistic-specs/issues/14) -- **L2 State Oracle**: A cryptoeconomic light client of the L2. Will finalize hashes of the L2 state on L1, once the dispute period has passed. Used to validate withdrawals. *(Note: contract separation is not yet final)* - - **Proposal Manager**: Handles conflicting state proposals to determine malicious party - - Maintains a set of ongoing optimistic proposals of the L2 state - - Ensures that state proposers are sufficiently bonded - - Distributes bond payouts - - **k-section game** - - executed to narrow in on the first disagreed-upon step between proposers - - played between two parties ("all people who agree with a proposal" may be considered a single party) - - merkle tree of execution steps between the trusted start and disputed end - - **Single Step Verifier** for executing the earliest disagreed-upon step - - Loads witness data: - - step witness parts can be represented as `generalized index -> bytes32`, - to simplify interaction with the partial structure (no tree management, every lookup is a simple math evaluation to get the right key) - - involved contract code entries can be large, TBD if put in storage or better of in call-data - - MPT nodes are just a dict (of internal MPT node hash to MPT node content) - - Runs verification step - - Registers result in bond-manager (slash sequencer, reward challenger, or vice-versa if spam attempt) -- **Cross-domain Messenger**: Message-passing abstraction contract used by applications developers (e.g. token bridge implementations) - - Sends messages into L2 (deposits) by adding to the deposit feed - - Relays messages out of L2 (withdrawals) by MPT proof to undisputed state-root - -### L2 Components - -- **Rollup Node** (previously "Data Transport Layer"): - - Sync data from the L1: call payload-insertion method of Engine API - - Track L1 data tip, and track state-roots: call forkchoice method of Engine API to finalize (undisputed state root) and reorg (follow head derived from L1) - - Create execution payloads: - - L2 Blocks as a whole from the L1 (i.e. include header data for batch of transactions) (TBD) - - Follow rollup rules to batch remaining individual transactions - - L1 may log special transactions, created by the Gateway, - which are paid for (i.e. signed by dummy key, and sent to L2 Gateway receiver contract, avoid new transaction type) - - Verifier (if loaded with a funded L1 account to bond the challenge): - - Block is executed with engine API, resulting state root is cached - - State roots are synced (maybe with a slight delay) - - If roots are different, run the Fraud-Proof Generator and start challenger agent job -- **Execution Engine** (previously "Eth1 client") - - Serves new [Engine API](https://hackmd.io/@n0ble/consensus_api_design_space) (Work in progress, introduced in The Merge hardfork) - - Maintains the L2 state (just like it would on L1) - - Syncs state to other L2 nodes for fast onboarding. Engine API can inform of finalized checkpoint, - to efficiently sync to trusted point, before processing block by block to the head of the L2 chain. -- **Witness Generator**: - - Highly experimental concept implementation (work in progress!): [Macula](https://github.com/protolambda/macula) - - Python: readability, not performance critical, just a temporary sub-process - - Requires bare minimum API methods from the Engine: - - get a MPT node (actually already present in p2p of eth1) - - get contract-code by contract-code hash - - Inputs: - - the API address to call for MPT node data and contract code - - the last 256 block-hashes - - the failing execution payload - - Output: fraud proof - - array of `bytes32`, root of each step, in sequence. (can be thousands) - - array of `AccessData`, encoding the set of generalized indices, code-hashes and MPT-node-hashes that were accessed this step. - as well as for the step-by-index (optimization, see generator spec). - - dict of `bytes32->(bytes32, bytes32)`: DB of all tree structure of the steps, without duplicating anything - - dict of `bytes->bytes`: map MPT node key (not leaf key, the actual internal node hash referenced in parent MPT nodes) to MPT node (RLP encoded path and child node data) - - dict of `bytes32->bytes`: map contract-code-hash to full contract code - - metadata of fraud (when/where/etc.) -- **Challenger Agent**: - - Take generated fraud proof (e.g. JSON file) - - Submit bond: control spam, challenges get back the bond, if they are actually valid. - - Run dispute game, retrieve disputed step index (WIP implementation [here](https://github.com/statechannels/dispute-game)) - - every step before this is agreed on by both parties - - the first differing step will be verified by reproducing the correct outcome on-chain - - Build witness data: - 1. get root of the disputed step - 2. get generalized indices - 3. load nodes as identified by the AccessData from shared dicts - 4. format witness data as L1 transaction input - - Sign tx, finish dispute (resubmit if not confirmed in time) -- **Batch Submitter**: - - Finalizes pre-confirmed sequencer transactions onto L1 - - Writes to sequencer feed - -[block-derivation]: ./components/rollup_node/block_derivation.md \ No newline at end of file diff --git a/roadmap.md b/roadmap.md deleted file mode 100644 index ea2f14e967ed..000000000000 --- a/roadmap.md +++ /dev/null @@ -1,70 +0,0 @@ -# Optimistic Roadmap -This document contains the Optimistic Ethereum protocol roadmap. That includes the project goals and a high level roadmap diagram. - -## Goals -The fundamental goal of the Optimistic Ethereum protocol is to scale Ethereum while preserving the security properties of L1. To achieve this we must create: - -### Ultra-Minimal Rollup Node -A rollup client, expressible as a minimal diff against Ethereum. Minimalism is key because it enables compatibility with existing Ethereum tooling as well as security. - -#### Completion Criteria -1. 1:1 equivalence with the Ethereum yellow paper. - - This may require changes to Ethereum in order to natively support rollups (eg. the merge API). -2. Multi-client support. -3. Minimal batch submission cost including the integration of eth2 sharding when ready. -4. Support for sequencer consensus. - -### Pluggable State Oracle -A set of pluggable contracts for proving L2 rollup state to L1. Pluggability is key because it will allow parallel development across the OE rollup stack. - -#### Completion Criteria -1. Proposal manager capable of being managed by any dispute game. - - Should eventually support validity proofs. -2. Dispute game capable of adjudicating any fraud proof VM. - -### Future Proof Fraud Proof VM -Create a VM built for executing fraud proofs against an EVM equivalent rollup. Future proof-ness is key because the fraud proof must evolve as the Ethereum protocol evolves. - -#### Completion Criteria -1. Must correctly implement the Optimistic Ethereum protocol defined in the Ultra-Minimal Rollup Node specs. -2. Easy to update as Ethereum hard forks are released. -3. Divergences between client implementations and the fraud proof are gracefully handled. - -## Roadmap Diagram -We will be working towards these goals iteratively. The following diagram is an approximation of what the ordering of work will look like and what streams of work can be parallelized: - -![Roadmap Diagram](./assets/roadmap.svg) - -The roadmap & abstractions are designed to enable independent development of each component. The 4 major components are: - -1. the optimistic mainnet deployment, -2. the fraud proof infrastructure, -3. stateless clients, -4. sharding. - -Each component will produce incremental and independent releases, each driving closer to unification and Optimistic Ethereum nirvana. - -### Summary of each component - -#### Optimism Mainnet -Optimism mainnet is the first Optimistic Ethereum network. It serves as: - -1. A live deployment of the latest stable Optimistic Ethereum spec; and -2. The source of funding of Optimistic Ethereum protocol development and other Ethereum public goods. - -This network will start out as being a rollup using eth1 as a data availability engine, and will migrate once sharding is ready. - -#### Fraud Proof -The fraud proof contracts and infrastructure are a pluggable set of EVM smart contracts, off-chain witness generators, challenge agents, and more. The near term fraud proof design is a 1:1 implementation of the Ethereum protocol written in the EVM. In the medium to long term, after statelessness is introduced to Ethereum (see the next project), the fraud proof should become entirely native so that Ethereum clients remain fully compatible with layer 2. - -#### eth1.x stateless clients -State expiry and stateless clients are key to solving the Ethereum state bloat problem **and** for native EVM fraud proofs. Once stateless clients are ready we can transition the Optimistic Ethereum fraud proof to a native component of the EVM. - -Note: Although critical to the OE roadmap, this project is tracked [external](https://github.com/ethereum/stateless-ethereum-specs/) to this repository. - -#### eth2 -The eth2 merge API and sharding will allow for native integration into execution engines as well as massive scalability ([~100k TPS](https://vitalik.ca/general/2021/01/05/rollup.html)) by greatly increasing Ethereum's data availability bandwidth. - -Note: Although critical to the OE roadmap, this project is tracked [external](https://github.com/ethereum/consensus-specs) to this repository. - -***Combining the eth2 merge API, native fraud proofs, and sharding - we'll reach Optimistic Ethereum nirvana.*** From cd6a7cc09dbc7b696b92bbca9528b3d0e4645294 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Wed, 24 Nov 2021 14:17:50 +0100 Subject: [PATCH 054/585] explain exactly what we're specifying --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b25194ca1e90..dbb20e177e37 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ # The Optimistic Ethereum Spec -This repository holds the work-in-progress specification for a "Simple Optimistic Rollup"; a minimum viable -version of the Optimistic Ethereum protocol. +This repository holds the work-in-progress specification for the next version of +Optimistic Ethereum. -A more detailed, though potentially out of date specification can be found on the `alpha` branch. +This spec is developped iteratively, specifying a rollup of increasing +complexity. The current stage specifies a "rollup" whose only transactions are +deposits (L2 transactions submitted on L1). + +A more detailed, though potentially out of date specification can be found on +the `alpha` branch. ## Work in Progress From 7564324bc7523acffdec8eb92cc8888beb603bae Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Wed, 24 Nov 2021 14:21:52 +0100 Subject: [PATCH 055/585] reformat, remove typo, add norswap to contacts --- README.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index dbb20e177e37..78cc7ec6b321 100644 --- a/README.md +++ b/README.md @@ -15,16 +15,33 @@ the `alpha` branch. Please note that this specification is currently under heavy construction. ## Contributing + ### Basic Contributions + Contributing to the Optimistic Ethereum specification is easy. -You'll find a list of open questions and active research topics over on the [discussions](https://github.com/ethereum-optimism/optimistic-specs/discussions) page for this rep. -Specific tasks and TODOs can be found on the [Issues](https://github.com/ethereum-optimism/optimistic-specs/issues) page. -You can edit content or add new pages by creating a [Pull Request](https://github.com/ethereum-optimism/optimistic-specs/pulls). + +You'll find a list of open questions and active research topics over on the +[Discussions] page for this repo. Specific tasks and TODOs can be found on the +[Issues] page. You can edit content or add new pages by creating a [pull +request]. + +[Discussions]: https://github.com/ethereum-optimism/optimistic-specs/discussions +[Issues]: https://github.com/ethereum-optimism/optimistic-specs/issues +[pull request]: https://github.com/ethereum-optimism/optimistic-specs/pulls ### R&D Calls -We hold bi-weekly R&D calls that are open to anyone interested in contributing to the Optimistic Ethereum spec. -Contact [@karlfloersch](https://twitter.com/karl_dot_tech/), [@protolambda](https://github.com/protolambda/), or [@kelvinfichter](https://twitter.com/kelvinfichter) if you'd like to join these calls. -Please note that these calls may be recorded and shared publicly (we will ask for consent before recording). + +We hold bi-weekly R&D calls that are open to anyone interested in contributing +to the Optimistic Ethereum spec. + +Contact [@karlfloersch], [@protolambda], [@kelvinfichter] or [@norswap] if you'd +like to join these calls. Please note that these calls may be recorded and +shared publicly (we will ask for consent before recording). + +[@karlfloersch]: https://twitter.com/karl_dot_tech/ +[@protolambda]: https://github.com/protolambda/ +[@kelvinfichter]: https://twitter.com/kelvinfichter +[@norswap]: https://twitter.com/norswap ## License From 422624422a0bde8ea7280559aac37234572f6c1c Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 17 Nov 2021 10:08:58 -0600 Subject: [PATCH 056/585] Add linting and formatting with markdownlint --- .markdownlintrc | 5 + package.json | 17 + yarn.lock | 821 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 843 insertions(+) create mode 100644 .markdownlintrc create mode 100644 package.json create mode 100644 yarn.lock diff --git a/.markdownlintrc b/.markdownlintrc new file mode 100644 index 000000000000..cafabca300de --- /dev/null +++ b/.markdownlintrc @@ -0,0 +1,5 @@ +{ + // Enable all markdownlint rules + // https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md + "default": true +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 000000000000..3d1da8f3b882 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "@eth-optimism/specs-2", + "version": "0.4.0", + "license": "MIT", + "private": true, + "devDependencies": { + "lint-staged": "11.0.0", + "markdownlint": "^0.24.0", + "markdownlint-cli2": "^0.3.2" + }, + "scripts": { + "lint": "yarn lint:fix && yarn lint:check", + "lint:fix": "markdownlint-cli2-fix '**/*.md' '#node_modules'", + "lint:check": "markdownlint-cli2 '**/*.md' '#node_modules'" + } +} + diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000000..26571ba6f50a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,821 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" + integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== + dependencies: + "@babel/highlight" "^7.16.0" + +"@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== + +"@babel/highlight@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" + integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== + dependencies: + "@babel/helper-validator-identifier" "^7.15.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0, chalk@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + +clone@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.16: + version "2.0.16" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + +commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +cosmiconfig@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.3.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + dependencies: + ms "2.1.2" + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enquirer@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +fast-glob@^3.1.1: + version "3.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +globby@~11.0.4: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +ignore@^5.1.4: + version "5.1.9" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" + integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + +lint-staged@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-11.0.0.tgz#24d0a95aa316ba28e257f5c4613369a75a10c712" + integrity sha512-3rsRIoyaE8IphSUtO1RVTFl1e0SLBtxxUOPBtHxQgBHS5/i6nqvjcUfNioMa4BU9yGnPzbO+xkfLtXtxBpCzjw== + dependencies: + chalk "^4.1.1" + cli-truncate "^2.1.0" + commander "^7.2.0" + cosmiconfig "^7.0.0" + debug "^4.3.1" + dedent "^0.7.0" + enquirer "^2.3.6" + execa "^5.0.0" + listr2 "^3.8.2" + log-symbols "^4.1.0" + micromatch "^4.0.4" + normalize-path "^3.0.0" + please-upgrade-node "^3.2.0" + string-argv "0.3.1" + stringify-object "^3.3.0" + +listr2@^3.8.2: + version "3.13.4" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.13.4.tgz#34101fc0184545597e00d1e7915ccfbfb17332e6" + integrity sha512-lZ1Rut1DSIRwbxQbI8qaUBfOWJ1jEYRgltIM97j6kKOCI2pHVWMyxZvkU/JKmRBWcIYgDS2PK+yDgVqm7u3crw== + dependencies: + cli-truncate "^2.1.0" + clone "^2.1.2" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rxjs "^7.4.0" + through "^2.3.8" + wrap-ansi "^7.0.0" + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + +markdown-it@12.2.0: + version "12.2.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.2.0.tgz#091f720fd5db206f80de7a8d1f1a7035fd0d38db" + integrity sha512-Wjws+uCrVQRqOoJvze4HCqkKl1AsSh95iFAeQDwnyfxM09divCBSXlDR1uTvyUP3Grzpn4Ru8GeCxYPM8vkCQg== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +markdownlint-cli2-formatter-default@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.2.tgz#76f1a064d70966178dfe3bb489af9423d830ca79" + integrity sha512-jIz1X3SIC8sX4NDFqQFUXL+JEtfnDoN4i+xocEu+etcxGX455pHb6sx86f/yVk4mKJ2o7aNe2ydSx9an22BfBg== + +markdownlint-cli2@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/markdownlint-cli2/-/markdownlint-cli2-0.3.2.tgz#328774b5ab981997fdd6fa8f72ea7feaed84722b" + integrity sha512-Wj4iQy2J49m9CVkWkLTdFxMTPDqD3AyL3NbLQgz/nUnTu8LnDguFCbQtFhdzQPvncHVjrKT2vYqg7DifzVP4tA== + dependencies: + globby "~11.0.4" + markdownlint "~0.24.0" + markdownlint-cli2-formatter-default "^0.0.2" + markdownlint-rule-helpers "~0.15.0" + micromatch "~4.0.4" + strip-json-comments "~3.1.1" + yaml "~1.10.2" + +markdownlint-rule-helpers@~0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.15.0.tgz#11434c573649b9235ae70b967314f5711f7d8fa8" + integrity sha512-A+9mswc3m/kkqpJCqntmte/1VKhDJ+tjZsERLz5L4h/Qr7ht2/BkGkgY5E7/wsxIhcpl+ctIfz+oS3PQrMOB2w== + +markdownlint@^0.24.0, markdownlint@~0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.24.0.tgz#224b53f671367a237d40c8be1745c7be9a322671" + integrity sha512-OJIGsGFV/rC9irI5E1FMy6v9hdACSwaa+EN3224Y5KG8zj2EYzdHOw0pOJovIYmjNfEZ9BtxUY4P7uYHTSNnbQ== + dependencies: + markdown-it "12.2.0" + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@~4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + +please-upgrade-node@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== + dependencies: + semver-compare "^1.0.0" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rxjs@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" + integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== + dependencies: + tslib "~2.1.0" + +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.5" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" + integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +string-argv@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" + integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +yaml@^1.10.0, yaml@~1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== From ad4fe7bd20a6f5f18aee8cc9aa35116085abfb4b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 1 Dec 2021 15:45:29 -0500 Subject: [PATCH 057/585] Add linting workflow for github actions --- .github/workflows/lint.yml | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000000..760c97d26246 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,40 @@ +name: lint/format markdown + +on: + push: + branches: + - 'main' + pull_request: + workflow_dispatch: + +jobs: + lint: + name: Linting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Fetch history + run: git fetch + - uses: actions/setup-node@v1 + with: + node-version: 14 + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v2 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install Dependencies + # only install dependencies if there was a change in the deps + # if: steps.yarn-cache.outputs.cache-hit != 'true' + run: yarn install + + - name: Lint + run: yarn lint:check From 47a8667d19fbdf23949e1714118ec5be00377bca Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 2 Dec 2021 22:01:37 +0100 Subject: [PATCH 058/585] Update to markdownlint json config --- .markdownlint.json | 8 ++++++++ .markdownlintrc | 5 ----- 2 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 .markdownlint.json delete mode 100644 .markdownlintrc diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 000000000000..b59ac7d5727c --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,8 @@ +{ + "line_length": { + "line_length": 120, + "strict": true, + "code_blocks": false, + "tables": false, + } +} \ No newline at end of file diff --git a/.markdownlintrc b/.markdownlintrc deleted file mode 100644 index cafabca300de..000000000000 --- a/.markdownlintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - // Enable all markdownlint rules - // https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md - "default": true -} \ No newline at end of file From caa12b5a3707eb73f6026f0024685a4e0a1bf607 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 3 Dec 2021 00:43:15 +0100 Subject: [PATCH 059/585] Spec Execution Engine behavior --- exec-engine.md | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 exec-engine.md diff --git a/exec-engine.md b/exec-engine.md new file mode 100644 index 000000000000..fe748dd8d00f --- /dev/null +++ b/exec-engine.md @@ -0,0 +1,146 @@ +# L2 Execution Engine + +The rollup mirrors the layer abstraction that the Merge introduces to Ethereum L1: +- Consensus: *Determine* canonical chain, propagate *blocks*, maintain *system-state* +- Execution: *Process* canonical chain, propagate *transactions*, maintain *user-state* + +The consensus task is implemented by the rollup-node, deriving most functionality from L1. +The execution task is implemented by the engine, providing an equivalent user environment as L1, with deposits. + +This document outlines the modifications, configuration and usage of a L1 execution engine for L2. + + +## Deposit processing + +The Engine interfaces abstract away transaction types with [EIP-2718][eip-2718]. + +To support rollup-functionality, processing of a new Deposit `TransactionType` is implemented by the engine, +see [Deposit specification][deposit-spec]. + +This type of transaction can mint L2 ETH, run EVM, +and introduce L1 information to enshrined contracts in the execution state. + +> **TODO**: implement deposit spec doc + +[deposit-spec]: ./deposits#transaction-type + +### Deposit boundaries + +Deposits are authenticated by the rollup-node, outside of the engine. + +To process deposits safely, the deposits MUST be authenticated first: +- Ingest directly through trusted Engine API +- Part of sync towards a trusted block-hash (trusted through previous Engine API instruction) + +Deposits MUST never be consumed from the transaction pool. +*The transaction pool can be disabled in a deposits-only rollup* + + +## Engine API + +*Note: the [Engine API][l1-api-spec] is in alpha, `v1.0.0-alpha.5`. +There may be subtle tweaks, beta starts in a few weeks* + +### `engine_forkchoiceUpdatedV1` + +This updates which L2 blocks the engine considers to be canonical (`forkchoiceState` argument), +and optionally initiates block production (`payloadAttributes` argument). + +Within the rollup, the types of forkchoice updates translate as: +- `headBlockHash`: block-hash of the head of the canonical chain. Labeled `"unsafe"` in user JSON-RPC. + Nodes may apply L2 blocks out of band ahead of time, and then reorg when L1 data conflicts. +- `safeBlockHash`: block-hash of the canonical chain, derived from L1 data, unlikely to reorg. +- `finalizedBlockHash`: irreversible block-hash, matches lower boundary of the dispute-period. + +To support rollup-functionality, one backwards-compatible change is introduced +to [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1]: + +[`PayloadAttributesV1`][PayloadAttributesV1] is extended with a `transactions` field, +equivalent to the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: +> `Array of DATA` - Array of transaction objects, each object is a byte list (`DATA`) representing +> `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718][eip-2718]. + +This `transactions` field is an optional JSON field: +- If empty or missing: no changes to engine behavior. + Utilized by sequencers (if enabled) to consume the transaction-pool. +- If present and non-empty: the payload MUST only be produced with this exact list of transactions. + Utilized by block-derivation to compute full block payloads based on deterministic inputs. + + +### `engine_executePayloadV1` + +No modifications to [`engine_executePayloadV1`][engine_executePayloadV1]. +Applies a L2 block to the engine state. + +### `engine_getPayloadV1` + +No modifications to [`engine_getPayloadV1`][engine_getPayloadV1]. +Retrieves a payload by ID, prepared by `engine_forkchoiceUpdatedV1` when called with `payloadAttributes`. + +## Networking + +The execution-engine can acquire all data through the rollup-node, as derived from L1: +*P2P networking is strictly optional.* + +However, to provide L1-equivalent experience, the P2P network functionality SHOULD be enabled, serving: +- Peer discovery ([Disc v5][discv5]) +- [`eth/66`][eth66]: + - Transaction pool (consumed by sequencer nodes) + - State-sync (happy-path for fast trustless db replication) + - Historical block header and body retrieval + - *New blocks are acquired through the consensus-layer instead (rollup-node)* + +No modifications to L1 network functionality are required, except configuration: +- `networkID`: Distinguishes the L2 network from L1 and testnets. + Equal to the `chainID` of the rollup network. +- Activate Merge fork: Enables Engine API and disables propagation of blocks, + as block-headers cannot be authenticated without consensus-layer. +- Bootnode list: although DiscV5 is a shared network, bootstrap is faster through L2 nodes. + +[discv5]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md +[eth66]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md + + +## Sync + +The execution-engine can operate sync in different ways: +- Happy-path: no special work for rollup-node, inform engine of the desired chain head, completes through engine P2P. +- Worst-case: rollup-node detects stalled engine, completes sync purely from L1 data, no peers required. + + +### Happy-path sync + +1. Engine API informs engine of chain head, unconditionally (part of regular node operation): + - [`engine_executePayloadV1`][engine_executePayloadV1] is called with latest L2 block derived from L1. + - [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1] is called with the current `unsafe`/`safe`/`finalized` L2 block hashes. +2. Engine requests headers from peers, in reverse till the parent-hash matches the local chain +3. Engine catches up: + a) A form of state-sync is activated towards the finalized or head block-hash + b) A form of block-sync pulls block bodies and processes towards head block-hash + +The exact P2P based sync is out of scope for the L2 specification: +the operation within the engine is the exact same as with L1 (although with an EVM that supports deposits). + +### Worst-case sync + +1. Engine is out of sync, not peered and/or stalled due other reasons. +2. Rollup-node periodically fetches latest head from engine (`eth_getBlockByNumber`) +3. Rollup-node activates sync if the engine is out of sync but not syncing through P2P (`eth_syncing`) +4. Rollup-node inserts blocks, derived from L1, one by one, + starting from the engine head (or genesis block if unrecognized) up to the latest chain head. + (`engine_forkchoiceUpdatedV1`, `engine_executePayloadV1`) + +See [rollup-node sync spec][rollup-node-sync] for L1-based block syncing specification. + +> **TODO**: rollup-node block-by-block sync (covered in rollup-node PR #43) +> +[rollup-node-sync]: ./rollup-node.md#sync + +[eip-2718]: https://eips.ethereum.org/EIPS/eip-2718 + +[l1-api-spec]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md +[PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#PayloadAttributesV1 +[ExecutionPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#ExecutionPayloadV1 +[engine_forkchoiceUpdatedV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_forkchoiceupdatedv1 +[engine_executePayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_executePayloadV1 +[engine_getPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_getPayloadV1 \ No newline at end of file From adeb4f83f598120f4f217783da77c16abcaab687 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 6 Dec 2021 14:55:40 +0100 Subject: [PATCH 060/585] Exec engine: address review and suggestions from @norswap --- exec-engine.md | 86 +++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/exec-engine.md b/exec-engine.md index fe748dd8d00f..1eaa307819b5 100644 --- a/exec-engine.md +++ b/exec-engine.md @@ -1,12 +1,5 @@ # L2 Execution Engine -The rollup mirrors the layer abstraction that the Merge introduces to Ethereum L1: -- Consensus: *Determine* canonical chain, propagate *blocks*, maintain *system-state* -- Execution: *Process* canonical chain, propagate *transactions*, maintain *user-state* - -The consensus task is implemented by the rollup-node, deriving most functionality from L1. -The execution task is implemented by the engine, providing an equivalent user environment as L1, with deposits. - This document outlines the modifications, configuration and usage of a L1 execution engine for L2. @@ -14,8 +7,8 @@ This document outlines the modifications, configuration and usage of a L1 execut The Engine interfaces abstract away transaction types with [EIP-2718][eip-2718]. -To support rollup-functionality, processing of a new Deposit `TransactionType` is implemented by the engine, -see [Deposit specification][deposit-spec]. +To support rollup functionality, processing of a new Deposit [`TransactionType`][eip-2718-transactions] +is implemented by the engine, see the [deposit specification][deposit-spec]. This type of transaction can mint L2 ETH, run EVM, and introduce L1 information to enshrined contracts in the execution state. @@ -26,11 +19,13 @@ and introduce L1 information to enshrined contracts in the execution state. ### Deposit boundaries -Deposits are authenticated by the rollup-node, outside of the engine. +Transactions cannot be blindly trusted, trust is established through authentication. +Unlike other transaction types deposits are not authenticated by a signature: +the rollup node authenticates them, outside of the engine. To process deposits safely, the deposits MUST be authenticated first: - Ingest directly through trusted Engine API -- Part of sync towards a trusted block-hash (trusted through previous Engine API instruction) +- Part of sync towards a trusted block hash (trusted through previous Engine API instruction) Deposits MUST never be consumed from the transaction pool. *The transaction pool can be disabled in a deposits-only rollup* @@ -47,25 +42,28 @@ This updates which L2 blocks the engine considers to be canonical (`forkchoiceSt and optionally initiates block production (`payloadAttributes` argument). Within the rollup, the types of forkchoice updates translate as: -- `headBlockHash`: block-hash of the head of the canonical chain. Labeled `"unsafe"` in user JSON-RPC. +- `headBlockHash`: block hash of the head of the canonical chain. Labeled `"unsafe"` in user JSON-RPC. Nodes may apply L2 blocks out of band ahead of time, and then reorg when L1 data conflicts. -- `safeBlockHash`: block-hash of the canonical chain, derived from L1 data, unlikely to reorg. -- `finalizedBlockHash`: irreversible block-hash, matches lower boundary of the dispute-period. +- `safeBlockHash`: block hash of the canonical chain, derived from L1 data, unlikely to reorg. +- `finalizedBlockHash`: irreversible block hash, matches lower boundary of the dispute period. -To support rollup-functionality, one backwards-compatible change is introduced +To support rollup functionality, one backwards-compatible change is introduced to [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1]: [`PayloadAttributesV1`][PayloadAttributesV1] is extended with a `transactions` field, equivalent to the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: -> `Array of DATA` - Array of transaction objects, each object is a byte list (`DATA`) representing +> `Array of DATA` - Array of transaction objects, each object is a byte list ([`DATA`][exec-api-data]) representing > `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718][eip-2718]. This `transactions` field is an optional JSON field: - If empty or missing: no changes to engine behavior. - Utilized by sequencers (if enabled) to consume the transaction-pool. + Utilized by sequencers (if enabled) to consume the transaction pool. - If present and non-empty: the payload MUST only be produced with this exact list of transactions. - Utilized by block-derivation to compute full block payloads based on deterministic inputs. + Utilized by [rollup driver][rollup-driver] to compute full block payloads based on deterministic inputs. + +> **TODO**: derivation function spec in rollup node doc or separate driver doc +[rollup-driver]: ./rollup-driver.md ### `engine_executePayloadV1` @@ -79,44 +77,51 @@ Retrieves a payload by ID, prepared by `engine_forkchoiceUpdatedV1` when called ## Networking -The execution-engine can acquire all data through the rollup-node, as derived from L1: +The execution engine can acquire all data through the rollup node, as derived from L1: *P2P networking is strictly optional.* -However, to provide L1-equivalent experience, the P2P network functionality SHOULD be enabled, serving: +However, to not bottleneck on L1 data retrieval speed, the P2P network functionality SHOULD be enabled, serving: - Peer discovery ([Disc v5][discv5]) - [`eth/66`][eth66]: - Transaction pool (consumed by sequencer nodes) - - State-sync (happy-path for fast trustless db replication) + - State sync (happy-path for fast trustless db replication) - Historical block header and body retrieval - - *New blocks are acquired through the consensus-layer instead (rollup-node)* + - *New blocks are acquired through the consensus layer instead (rollup node)* No modifications to L1 network functionality are required, except configuration: -- `networkID`: Distinguishes the L2 network from L1 and testnets. - Equal to the `chainID` of the rollup network. +- [`networkID`][network-id]: Distinguishes the L2 network from L1 and testnets. + Equal to the [`chainID`][chain-id] of the rollup network. - Activate Merge fork: Enables Engine API and disables propagation of blocks, - as block-headers cannot be authenticated without consensus-layer. -- Bootnode list: although DiscV5 is a shared network, bootstrap is faster through L2 nodes. + as block headers cannot be authenticated without consensus layer. +- Bootnode list: DiscV5 is a shared network, + [bootstrap][discv5-rationale] is faster through connecting with L2 nodes first. [discv5]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md [eth66]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md - +[network-id]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md#status-0x00 +[chain-id]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md +[discv5-rationale]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5-rationale.md ## Sync -The execution-engine can operate sync in different ways: -- Happy-path: no special work for rollup-node, inform engine of the desired chain head, completes through engine P2P. -- Worst-case: rollup-node detects stalled engine, completes sync purely from L1 data, no peers required. +The execution engine can operate sync in different ways: +- Happy-path: rollup node informs engine of the desired chain head as determined by L1, completes through engine P2P. +- Worst-case: rollup node detects stalled engine, completes sync purely from L1 data, no peers required. +The happy-path is more suitable to bring new nodes online quickly, +as the engine implementation can sync state faster through methods like [snap-sync][snap-sync]. + +[snap-sync]: https://github.com/ethereum/devp2p/blob/master/caps/snap.md ### Happy-path sync 1. Engine API informs engine of chain head, unconditionally (part of regular node operation): - [`engine_executePayloadV1`][engine_executePayloadV1] is called with latest L2 block derived from L1. - [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1] is called with the current `unsafe`/`safe`/`finalized` L2 block hashes. -2. Engine requests headers from peers, in reverse till the parent-hash matches the local chain +2. Engine requests headers from peers, in reverse till the parent hash matches the local chain 3. Engine catches up: - a) A form of state-sync is activated towards the finalized or head block-hash - b) A form of block-sync pulls block bodies and processes towards head block-hash + a) A form of state sync is activated towards the finalized or head block hash + b) A form of block sync pulls block bodies and processes towards head block hash The exact P2P based sync is out of scope for the L2 specification: the operation within the engine is the exact same as with L1 (although with an EVM that supports deposits). @@ -124,20 +129,21 @@ the operation within the engine is the exact same as with L1 (although with an E ### Worst-case sync 1. Engine is out of sync, not peered and/or stalled due other reasons. -2. Rollup-node periodically fetches latest head from engine (`eth_getBlockByNumber`) -3. Rollup-node activates sync if the engine is out of sync but not syncing through P2P (`eth_syncing`) -4. Rollup-node inserts blocks, derived from L1, one by one, +2. rollup node periodically fetches latest head from engine (`eth_getBlockByNumber`) +3. rollup node activates sync if the engine is out of sync but not syncing through P2P (`eth_syncing`) +4. rollup node inserts blocks, derived from L1, one by one, starting from the engine head (or genesis block if unrecognized) up to the latest chain head. (`engine_forkchoiceUpdatedV1`, `engine_executePayloadV1`) -See [rollup-node sync spec][rollup-node-sync] for L1-based block syncing specification. +See [rollup node sync spec][rollup-node-sync] for L1-based block syncing specification. + +> **TODO**: rollup node block-by-block sync (covered in rollup node PR #43) -> **TODO**: rollup-node block-by-block sync (covered in rollup-node PR #43) -> [rollup-node-sync]: ./rollup-node.md#sync [eip-2718]: https://eips.ethereum.org/EIPS/eip-2718 - +[eip-2718-transactions]: https://eips.ethereum.org/EIPS/eip-2718#transactions +[exec-api-data]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#structures [l1-api-spec]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md [PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#PayloadAttributesV1 [ExecutionPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#ExecutionPayloadV1 From a0b614722e08320dcbd1ae6eb73c3e0bfaef8140 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 7 Dec 2021 15:53:43 +0100 Subject: [PATCH 061/585] .gitignore and lint line-length fix --- .gitignore | 1 + .markdownlint.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..3c3629e647f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/.markdownlint.json b/.markdownlint.json index b59ac7d5727c..91b5460c00a0 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,7 +1,8 @@ { "line_length": { "line_length": 120, - "strict": true, + "strict": false, + "stern": true, "code_blocks": false, "tables": false, } From 737991de5212d4b9101b4642502fee1ae8cba57e Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 7 Dec 2021 15:59:55 +0100 Subject: [PATCH 062/585] exec engine: doc formatting --- exec-engine.md | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/exec-engine.md b/exec-engine.md index 1eaa307819b5..3e11ba302cee 100644 --- a/exec-engine.md +++ b/exec-engine.md @@ -2,15 +2,14 @@ This document outlines the modifications, configuration and usage of a L1 execution engine for L2. - ## Deposit processing The Engine interfaces abstract away transaction types with [EIP-2718][eip-2718]. -To support rollup functionality, processing of a new Deposit [`TransactionType`][eip-2718-transactions] +To support rollup functionality, processing of a new Deposit [`TransactionType`][eip-2718-transactions] is implemented by the engine, see the [deposit specification][deposit-spec]. -This type of transaction can mint L2 ETH, run EVM, +This type of transaction can mint L2 ETH, run EVM, and introduce L1 information to enshrined contracts in the execution state. > **TODO**: implement deposit spec doc @@ -24,13 +23,13 @@ Unlike other transaction types deposits are not authenticated by a signature: the rollup node authenticates them, outside of the engine. To process deposits safely, the deposits MUST be authenticated first: + - Ingest directly through trusted Engine API - Part of sync towards a trusted block hash (trusted through previous Engine API instruction) Deposits MUST never be consumed from the transaction pool. *The transaction pool can be disabled in a deposits-only rollup* - ## Engine API *Note: the [Engine API][l1-api-spec] is in alpha, `v1.0.0-alpha.5`. @@ -42,6 +41,7 @@ This updates which L2 blocks the engine considers to be canonical (`forkchoiceSt and optionally initiates block production (`payloadAttributes` argument). Within the rollup, the types of forkchoice updates translate as: + - `headBlockHash`: block hash of the head of the canonical chain. Labeled `"unsafe"` in user JSON-RPC. Nodes may apply L2 blocks out of band ahead of time, and then reorg when L1 data conflicts. - `safeBlockHash`: block hash of the canonical chain, derived from L1 data, unlikely to reorg. @@ -56,6 +56,7 @@ equivalent to the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloa > `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718][eip-2718]. This `transactions` field is an optional JSON field: + - If empty or missing: no changes to engine behavior. Utilized by sequencers (if enabled) to consume the transaction pool. - If present and non-empty: the payload MUST only be produced with this exact list of transactions. @@ -81,6 +82,7 @@ The execution engine can acquire all data through the rollup node, as derived fr *P2P networking is strictly optional.* However, to not bottleneck on L1 data retrieval speed, the P2P network functionality SHOULD be enabled, serving: + - Peer discovery ([Disc v5][discv5]) - [`eth/66`][eth66]: - Transaction pool (consumed by sequencer nodes) @@ -89,12 +91,13 @@ However, to not bottleneck on L1 data retrieval speed, the P2P network functiona - *New blocks are acquired through the consensus layer instead (rollup node)* No modifications to L1 network functionality are required, except configuration: -- [`networkID`][network-id]: Distinguishes the L2 network from L1 and testnets. + +- [`networkID`][network-id]: Distinguishes the L2 network from L1 and testnets. Equal to the [`chainID`][chain-id] of the rollup network. -- Activate Merge fork: Enables Engine API and disables propagation of blocks, +- Activate Merge fork: Enables Engine API and disables propagation of blocks, as block headers cannot be authenticated without consensus layer. -- Bootnode list: DiscV5 is a shared network, - [bootstrap][discv5-rationale] is faster through connecting with L2 nodes first. +- Bootnode list: DiscV5 is a shared network, + [bootstrap][discv5-rationale] is faster through connecting with L2 nodes first. [discv5]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md [eth66]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md @@ -105,6 +108,7 @@ No modifications to L1 network functionality are required, except configuration: ## Sync The execution engine can operate sync in different ways: + - Happy-path: rollup node informs engine of the desired chain head as determined by L1, completes through engine P2P. - Worst-case: rollup node detects stalled engine, completes sync purely from L1 data, no peers required. @@ -115,9 +119,10 @@ as the engine implementation can sync state faster through methods like [snap-sy ### Happy-path sync -1. Engine API informs engine of chain head, unconditionally (part of regular node operation): +1. Engine API informs engine of chain head, unconditionally (part of regular node operation): - [`engine_executePayloadV1`][engine_executePayloadV1] is called with latest L2 block derived from L1. - - [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1] is called with the current `unsafe`/`safe`/`finalized` L2 block hashes. + - [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1] is called with the current + `unsafe`/`safe`/`finalized` L2 block hashes. 2. Engine requests headers from peers, in reverse till the parent hash matches the local chain 3. Engine catches up: a) A form of state sync is activated towards the finalized or head block hash @@ -132,7 +137,7 @@ the operation within the engine is the exact same as with L1 (although with an E 2. rollup node periodically fetches latest head from engine (`eth_getBlockByNumber`) 3. rollup node activates sync if the engine is out of sync but not syncing through P2P (`eth_syncing`) 4. rollup node inserts blocks, derived from L1, one by one, - starting from the engine head (or genesis block if unrecognized) up to the latest chain head. + starting from the engine head (or genesis block if unrecognized) up to the latest chain head. (`engine_forkchoiceUpdatedV1`, `engine_executePayloadV1`) See [rollup node sync spec][rollup-node-sync] for L1-based block syncing specification. @@ -149,4 +154,4 @@ See [rollup node sync spec][rollup-node-sync] for L1-based block syncing specifi [ExecutionPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#ExecutionPayloadV1 [engine_forkchoiceUpdatedV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_forkchoiceupdatedv1 [engine_executePayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_executePayloadV1 -[engine_getPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_getPayloadV1 \ No newline at end of file +[engine_getPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_getPayloadV1 From ceb049989e49bc34653b4d5d16100e4722c71945 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 30 Nov 2021 21:06:47 +0100 Subject: [PATCH 063/585] rollup node spec draft --- glossary.md | 241 +++++++++++++++++++++++++++++++++++++++++ rollup-node.md | 284 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 525 insertions(+) create mode 100644 glossary.md create mode 100644 rollup-node.md diff --git a/glossary.md b/glossary.md new file mode 100644 index 000000000000..281a21f60c92 --- /dev/null +++ b/glossary.md @@ -0,0 +1,241 @@ +# Glossary + +-------------------------------------------------------------------------------- + +# General Terms + +## Layer 1 (L1) +[L1]: /glossary.md#layer-1-L1 + +Refers the Ethereum blockchain, used used in contrast to [layer 2][L2], which +refers to Optimistic Ethereum. + +## Layer 2 (L2) +[L2]: /glossary.md#layer-2-L2 + +Refers to the Optimistic Ethereum blockchain (specified in this repository), +used in contrast to [layer 1][L1], which refers to the Ethereum blockchain. + +## Block +[block]: /glossary.md#layer-1-L1 + +Can refer to an [L1] block, or to an [L2] block, which are structured similarly. + +A block is a sequential list of transactions, along with a couple of properties +stored in the *header* of the block. A description of these properties can be +found in code comments [here][nano-header], or in the [Ethereum yellow paper +(pdf)][yellow], section 4.3. + +It is useful to distinguish between input block properties, which are known +before executing the transactions in the block, and output bblock properties, +which are derived after executing the block's transactions. These include +various [Merkle roots][Merkle root] for the L2 state and for log events emitted +during the execution. + +## EOA +[EOA]: /glossary.md#EOA + +"Externally Owned Account", an Ethereum term to designate addresses operated by +users, as opposed to contract addresses. + +## Merkle Root +[Merkle root]: /glossary.md#merkle-roots + +The Merkle root is the root hash of a [Merkle Patricia tree] (MPT). A MPT is a +[trie], which is a tree tree structure that maps keys to values. The root hash +of a MPT is a commitment to the contents of the tree, which allows a proof to be +constructed for any key-value mapping encoded in the tree. Such a proof is +called a Merkle proof, and can be verified against the Merkle root. + +## Chain Re-Organization +[reorg]: /glossary.md#chain-re-organization + +A re-organization, or re-org for short, is whenever the head of a blockchain +(its last block) changes (as dictated by the [fork choice rule]) to a block that +is not a child of the previous head. + +L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a +consequence of L1 re-orgs, mediated via [L2 chain derivation][derivation]. + +## Precompiled Contract ("Precompile") +[precompile]: /glossary.md#precompiled-contract-precompile + +A contract that exists on chain but consumes no storage, and whose invocation +does not need to result in the execution of EVM bytecode. Instead, its behaviour +is defined by specification. + +Ethereum L1 precompiles are specified in Appendix E of the [yellow +paper][yellow]. + +Optimistic Ethereum exposes all of Ethereum's precompiles, and adds the +following precompiles: + +- [L1 Attributes Precompiled Contract][l1-attr-precompile] + +-------------------------------------------------------------------------------- + +# L2 Chain Concepts + +## L2 Chain Inception +[L2 chain inception]: /glossary.md#L2-chain-inception + +The L1 block number for which the first block of the L2 chain was generated. + +## Rollup Node +[rollup node]: /glossary.md#rollup-node + +The rollup node is responsible for [deriving the L2 chain][derivation] from the +[L2 derivation inputs][deriv-inputs] available on L1. This is done by its +[rollup driver] component. + +The rollup node is also responsible for [block gossip], the process of +transmitting the L2 blocks it derives over a peer-to-peer network. + +- cf. [Rollup Node Specification](/rollup-node.md) +- cf. [Block Gossip Specification](TODO) + +> **TODO LINK** block gossip spec + +## Rollup Driver +[rollup driver]: /glossary.md#rollup-driver + +The rollup driver is the [rollup node] component responsible for [deriving the +L2 chain][derivation] from the [L2 derivation inputs][deriv-inputs] available on +L1. + +## L2 Chain Derivation +[derivation]: /glossary.md#L2-chain-derivation + +A process that reads [L2 derivation inputs][deriv-inputs] from L1 in order to +derive the L2 chain. + +cf. [L2 Chain Derivation (in Rollup Node +Specification)](/rollup-node.md#l2-chain-derivation) + +## L2 Derivation Inputs +[deriv-inputs]: /glossary.md#l2-chain-derivation-inputs + +This term refers to data that is found in L1 blocks and is read by the [rollup +node] to construct [payload attributes]. + +Chain derivation attributes include: +- L1 block attributes + - block number + - timestamp + - basefee +- [deposits] + +## Payload Attributes +[payload attributes]: /glossary.md#payload-attributes + +This term refers to data that can be derived from [L2 chain derivation +inputs][deriv-inputs] found on L1, which are then passed to the [execution +engine] to construct L2 blocks. + +"Payload attributes" is a term that originates and is specified in the [Ethereum +Engine API specification][engine-api]. + +In addition to the [specified][engine-api] `timestamp`, `random`and +`suggestedFeeRecipient` fields, we add a field to specify the transactions that +the execution engine must include in the block and execute. + +> **TODO** The transaction field must be specified. + +Payload attributes were historically called "L2 block inputs" and you might +still hear some people using this term. + +## L1 Attributes Transaction +[l1-attributes-tx]: /glossary.md#l1-attributes-transaction + +A transaction with an Optimistic-Ethereum-specific transaction type, that is +used to register the L1 block attributes (number, timestamp, ...) on L2. + +The L1 attributes for a given L1 block can be read on L2 from the [L1 Attributes +Precompiled Contract][l1-attr-precompile]. + +cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-format) +(in the section on [payload attributes]) + +> **TODO** We might want to move this the format spec to the execution engine. + +## L1 Attributes Precompiled Contract +[l1-attr-precompile]: /glossary.md#l1-attributes-precompiled-contract + +A [precompiled contract][precompile] on L2 that can be used to retrieve the L1 +block attributes of L1 blocks with a given block number or a given block hash. + +cf. [L1 Attributes Precompiled Contract Specification](TODO) + +> **TODO LINK** L1 attributes precompiled contract spec + +## Deposits +[deposits]: /glossary.md#deposits + +A deposit is an L2 transaction that has been submitted on L1, via a transaction +sent to the [L2 deposit feed contract][deposit-feed]. + +While deposits are notably (but not only) used to "deposit" (bridge) ETH and +tokens to L2, the word *deposit* should be understood as "a transaction +*deposited* to L2". + +Deposits are one kind of [L2 derivation input][deriv-input]. + +## L2 Deposit Feed Contract +[deposit-feed]: /glossary.md#L2-deposit-feed-contract + +A contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits +are emitted as log records (in Solidity, these are called *events*) for +consumption by [rollup nodes][rollup node]. + +Advanced note: the deposits are not stored in calldata because they can be send +by contracts, in which case the calldata is part of the execution, but its value +is not captured in one of the [Merkle roots][Merkle root] included in the L1 +block. + +cf. [L2 Deposit Feed Contract Specification](TODO) + +> **TODO LINK** deposit feed contract specification + +## Block Gossip +[block gossip]: /glossary.md#block-gossip + +Block gossip is a [rollup node] component responsible for transmitting the L2 +blocks derived by the rollup node over a peer-to-peer network. + +> Note that block gossip is not useful in the current deposit-only model, but +> will become useful in later stages of the specification process. + +-------------------------------------------------------------------------------- + +# Execution Engine Concepts + +## Execution Engine +[execution engine]: /glossary.md#execution-engine + +The execution engine is responsible for executing transactions in blocks and +computing the resulting state roots, log roots and block hash. + +Both L1 (post-[merge]) and L2 have an execution engine. + +On L1, the executed blocks can come from L1 block synchronization; or from a block +freshly minted by the execution engine (using transactions from the L1 +[mempool]), at the request of the L1 consensus layer. + +On L2, the executed blocks are freshly minted by the execution engine at the +request of the [rollup node], using transactions [derived from L1 +blocks][derivations]. + +In these specifications, "execution engine" always refer to the L2 execution +engine, unless otherwise specified. + + + + +[Merkle Patricia tree]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md +[trie]: https://en.wikipedia.org/wiki/Trie +[nano-header]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/blocks/BlockHeader.java#L22-L156 +[yellow]: https://ethereum.github.io/yellowpaper/paper.pdf +[engine-api]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#PayloadAttributesV1 +[merge]: https://ethereum.org/en/eth2/merge/ +[mempool]: https://www.quicknode.com/guides/defi/how-to-access-ethereum-mempool +[L1 consensus layer]: https://github.com/ethereum/consensus-specs/#readme diff --git a/rollup-node.md b/rollup-node.md new file mode 100644 index 000000000000..afb160435bdb --- /dev/null +++ b/rollup-node.md @@ -0,0 +1,284 @@ +# Rollup Node Specification + + +[rollup node]: /glossary.md#rollup-node +[derivation]: /glossary.md#L2-chain-derivation +[L2 derivation inputs]: /glossary.md#L2-derivation-inputs +[payload attributes]: /glossary.md#payload-attributes +[block]: /glossary.md#block +[execution engine]: /glossary.md#execution-engine +[reorg]: /glossary.md#re-organization +[block gossip]: /glossary.md#block-gossip +[rollup driver]: /glossary.md#rollup-driver +[deposits]: /glossary.md#deposits +[deposit-feed]: /glossary.md#L2-deposit-feed-contract +[L2 chain inception]: /glossary.md#L2-chain-inception + +The [rollup node] is the component responsible for [deriving the L2 +chain][derivation] from L1 blocks. This process happens in two steps: + +1. Read [L2 derivation inputs] from L1 and generate [payload attributes] (essentially + [a block without output properties][block]). +2. Pass the payload attributes to the [execution engine], so that [output block + properties][block] may be computed. + +While this process is conceptually a pure function from the L1 chain to the L2 +chain, it is in practice incremental. The L2 chain changes whenever new L1 +blocks (and hence new L2 derivation inputs) are added to the L1 chain, or +whenever the L1 chain [re-organizes][reorg]. + +Additionally, the rollup node is responsible for [block gossip], i.e. +transmitting the L2 blocks it derives over a peer-to-peer network. + +The part of the rollup node that derives the L2 chain is called the [rollup +driver]. This document is mostly concerned with the specification of the rollup +driver, while block gossip is [specified in a separate document][gossip-spec]. + +[gossip-spec]: TODO + +> **TODO LINK** block gossip spec + +## L2 Chain Derivation +[l2-chain-derivation]: #l2-chain-derivation + +This section specifies how the [rollup driver] derives one L2 block from every +L1 block. The L2 block will carry the L1 block attributes (as a *[L1 attributes +transaction]*) well as all L2 transactions deposited by users in the L1 block +(*[deposits]*). + +[L1 attributes transaction]: /glossary.md#l1-attributes-transaction + +### From L2 derivation inputs to payload attributes + +[payload-attr]: #From-L2-derivation-inputs-to-payload-attributes +[`PayloadAttributesOPV1`]: #From-L2-derivation-inputs-to-payload-attributes + +The rollup reads the following [L2 derivation inputs] for each L1 block: + +- L1 block attributes + - block number + - timestamp + - basefee +- [deposits] + +A deposit is an L2 transaction that has been submitted on L1, via a transaction +sent to the [L2 deposit feed contract][deposit-feed]. + +While deposits are notably (but not only) used to "deposit" (bridge) ETH and +tokens to L2, the word *deposit* should be understood as "a transaction +*deposited* to L2". + +The L1 attributes are read from the L1 block header, while deposits are read +from the block's log entries. Refer to the [**L2 deposit feed contract +specification**][deposit-feed] for details on how deposits are encoded as +log entries. + +[deposit-feed-spec]: TODO + +> **TODO LINK** deposit feed contract specification + +From these L2 derivation inputs, the rollup node constructs an expanded version +of the [Engine API PayloadAttributesV1 object][PayloadAttributesV1]: + +[PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 + +``` +PayloadAttributesOPV1: { + timestamp: QUANTITY + random: DATA (32 bytes) + suggestedFeeRecipient: DATA (20 bytes) + transactions: array of DATA +} +``` + +The type notation used here refers to the [HEX value encoding] used by the +[Ethereum JSON-RPC API specification][JSON-RPC-API], as this structure will need to +be sent over JSON-RPC. `array` refers to a JSON array. + +[HEX value encoding]: https://eth.wiki/json-rpc/API#hex-value-encoding +[JSON-RPC-API]: https://eth.wiki/json-rpc/API + +The object properties must be set as follows: + +- `timestamp` is set to the current [unix time] (number of elapsed seconds since + 00:00:00 UTC on 1 January 1970), rounded to the closest multiple of 2 seconds. +- `random` is currently set to all zero bytes. After [the merge][merge], the randomness + value exposed for the L1 block will be copied in this property. +- `suggestedFeeRecipient` is set to an address where the sequencer would like to + direct the fees +- `transactions` is an array of transactions, RLP-encoded in the [EIP-2718] + format (i.e. as a sequence of a single byte and a byte array), of the allowed + types. We specify how to select the transactions below. + +[unix type]: https://en.wikipedia.org/wiki/Unix_time +[merge]: https://ethereum.org/en/eth2/merge/ +[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 + +> For details on RLP encoding, refer to the yellow paper, or look at [this +> hyperlinked implementation][encode-tx]. + +[encode-tx]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/transactions/Transaction.java#L84-L130 + +In particular, we allow the following two transaction types: +- [EIP-1559]: the current "regular" Ethereum L1 transaction type, which + separates gas fees between a base fee and a tip +- the *[L1 attributes transaction]*, see below + +[EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 + +Historical Optimistic Ethereum transactions also include [EIP-155] transactions, +which are not accepted by the network anymore. This is not an [EIP-2718] typed +transaction, but can be distinguished from those by the fact that their +RLP-encoding's first byte will always be `>= 0xC0`. + +[EIP-155]: https://eips.ethereum.org/EIPS/eip-155 + +#### Payload Transaction Format + +The `transactions` array is filled with the deposits, prefixed by the (single) +[L1 attributes transaction]. The deposits (which must be similarly RLP-encoded) +are simply copied byte-for-byte — it is the role of the [execution engine] to +reject invalidly-formatted transactions. + +> **TODO** must offer some precisions on the format of deposits: sender, +> receivers both in-tx-as-encoded, and on-L2-tx. What about the fees? + +The Optimistic Ethereum specific *[L1 attributes transaction]* has the following +[EIP-2718]-compatible format: `0x7E || [block_number, timestamp, basefee]` +where: + +- `0x7E` is the transaction type identifier. It is selected because transaction + type identifiers are currently allowed to go up to `0x7F`. Picking a high + identifier minimizes the risk that the identifier will be used by Ethereum in + the future. We don't pick `0x7F` itself in case it becomes used for a + variable-length encoding scheme. +- `block_number` is the L1 block number as a 64-bit integer (4 bytes) +- `timestamp` is the L1 block timestamp as a 64-bit integer (4 bytes) +- `basefee` is the L1 block basefee as a 64-bit integer (4 bytes) + +When included in the `transactions` array, this transaction should be +RLP-encoded in the same way as other transactions. + +Here is an example valid `PayloadAttributesOPV1` object, which contains an L1 +attributes transaction as well as a single deposit: + +```js +{ + timestamp: "0x61a6336f", + random: "0xde5dff2b0982ecbbd38081eb8f4aed0525140dc1c1d56f995b4fa801a3f2649e", + suggestedFeeRecipient: "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B", + transactions: [ + "TODO specify L1 attribute transaction", + "0x02f87101058459682f0085199c82cc0082520894ab5801a7d398351b8be11c439e05c5b3259aec9b8609184e72a00080c080a0a6d217a91ea344fc09f740f104f764d71bb1ca9a8e159117d2d27091ea5fce91a04cf5add5f5b7d791a2c4663ab488cb581df800fe0910aa755099ba466b49fd69" + ] +} +``` + +### Building the L2 block with the execution engine +[calling-exec-engine]: #building-the-L2-block-with-the-execution-engine + +The Optimistic Ethereum [execution engine] is [specified in its own +document][execution-engine-spec]. + +This section defines how the rollup driver must interact with the execution +engine's in order to convert [payload attributes] into L2 blocks. + +> **TODO** This section probably includes too much redundant details that will +> need to be removed once the execution engine spec is up. + +Optimistic Ethereum's execution engine API is built upon [Ethereum's Engine API +specification][eth-engine-api], with a couple of modifications. That +specification builds upon [Ethereum's JSON-RPC API specification][JSON-RPC-API], +which itself builds upon the [JSON-RPC specification][JSON-RPC]. + +[eth-engine-api]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md +[JSON-RPC]: https://www.jsonrpc.org/specification + +In particular, the [Ethereum's Engine API specification][eth-engine-api] +specifies a [JSON-RPC] endpoint with a number of JSON-RPC (REST) routes, which +are the means through which the rollup driver interacts with the execution +engine. + +Instead of calling [`engine_forkchoiceUpdatedV1`], the rollup driver must call +the new [`engine_forkchoiceUpdatedOPV1`] route. This has the same signature, +except that: + +[`engine_forkchoiceUpdatedV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_forkchoiceupdatedv1 +[`engine_forkchoiceUpdatedOPV1`]: TODO + +> **TODO LINK** forkchoiceUpdatedOPV1 from spec + +- it takes a [`PayloadAttributesOPV1`] object as input instead of + [`PayloadAttributesV1`]. The execution engine must include the valid + transactions supplied in this object in the block, in the same order as they + were supplied, and only those. See the [previous section][payload-attr] for + the specification of how the properties must be set. + +- we repurpose the [`ForkchoiceStateV1`] structure with the following property + semantics: + - `headBlockHash`: block hash of the last block of the L2 chain, according to + the rollup driver. + - `safeBlockHash`: same as `headBlockHash`. + - `finalizedBlockHash`: the hash of the block whose number is + `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if the number of that + block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where + `FINALIZATION_DELAY_BLOCKS == 43200` (approximately 7 days worth of L1 + blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of + the first L1 block for which an L2 block was produced). + +[`ForkchoiceStateV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#ForkchoiceStateV1 + +> **Note:** the properties of this `ForkchoiceStateV1` can be used to anchor queries +> to the regular (non-engine-API) JSON-RPC endpoint of the execution engine. +> [See here for more information.][L2-JSON-RPC-API] + +[L2-JSON-RPC-API]: TODO + +> **TODO LINK** L2 JSON RPC API (might be the same as [L1's][JSON-RPC-API]) + +The `payloadID` returned by [`engine_forkchoiceUpdatedOPV1`] can then be passed +to [`engine_getPayloadV1`] in order to obtain an [`ExecutionPayloadV1`], which +fully defines a new L2 block. + +[`engine_getPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_getpayloadv1 +[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 + +## Handling L1 Re-Orgs + +The [previous section on L2 chain derivation][l2-chain-derivation] assumes +linear progression of the L1 chain. It is also applicable for batch processing, +meaning that any given point in time, the canonical L2 chain is given by +processing the whole L1 chain since the [L2 chain inception]. + +The L1 chain may occasionally re-organize, meaning the head of the L1 chain +changes to a block that is not the child of the previous head but rather one of +its "cousins" (i.e. the descendant of an ancestor of the previous head). In +those case, the rollup driver must: + +1. Locate the *common ancestor*, a block that is an ancestor of both the + previous and new head. +2. Isolate the range of L1 blocks \]common ancestor, ..., new head\]. +3. For each such block, call [`engine_forkchoiceUpdatedOPV1`] and + [`engine_getPayloadV1`]. + - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. + - Fill the [``ForkchoiceStateV1`] object according to the [the section on the + execution engine][calling-exec-engine], but set `headBlockHash` to the hash + of the last processed L2 block (use the hash of the common ancestor + initially) instead of the last L2 chain head. `safeBlockHash` and + `finalizedBlockHash` must be updated accordingly. + +> Note that post-[merge], the L1 chain will offer finalization guarantees +> meaning that it won't be able to re-org more than `FINALIZATION_DELAY_BLOCKS` +> in the past, hence preserving our finalization guarantees. + +> **TODO** Enunciate our finalization guarantees. + +> **TODO** Must enunciate error cases more precisely, as well as state what +> should be impossible and should cause the node to stop deriving the L2 chain. + +## Block Gossip + +Another responsability of the rollup node is to transmit the L2 blocks it +derives from the L1 chain to other L2 nodes via a process called *block gossip*. + +This is specified in [a separate document][gossip-spec]. From bdfa85d7b789a65e069556bfb003462f0b2b56c2 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 30 Nov 2021 21:33:37 +0100 Subject: [PATCH 064/585] fix formatting snafu, add glossary link, eth 2 block time is 12s not 14s --- rollup-node.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rollup-node.md b/rollup-node.md index afb160435bdb..47b5b693f892 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -222,7 +222,7 @@ except that: - `finalizedBlockHash`: the hash of the block whose number is `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where - `FINALIZATION_DELAY_BLOCKS == 43200` (approximately 7 days worth of L1 + `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the first L1 block for which an L2 block was produced). @@ -261,7 +261,7 @@ those case, the rollup driver must: 3. For each such block, call [`engine_forkchoiceUpdatedOPV1`] and [`engine_getPayloadV1`]. - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. - - Fill the [``ForkchoiceStateV1`] object according to the [the section on the + - Fill the [`ForkchoiceStateV1`] object according to the [the section on the execution engine][calling-exec-engine], but set `headBlockHash` to the hash of the last processed L2 block (use the hash of the common ancestor initially) instead of the last L2 chain head. `safeBlockHash` and @@ -279,6 +279,7 @@ those case, the rollup driver must: ## Block Gossip Another responsability of the rollup node is to transmit the L2 blocks it -derives from the L1 chain to other L2 nodes via a process called *block gossip*. +derives from the L1 chain to other L2 nodes via a process called *[block +gossip]*. This is specified in [a separate document][gossip-spec]. From 8311961eca9664a03a9b78ee649a0e0ff3e9b3eb Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 17:26:44 +0100 Subject: [PATCH 065/585] don't try to legislate on which transaction types are allowed, follow L1 --- rollup-node.md | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/rollup-node.md b/rollup-node.md index 47b5b693f892..ea20f170b9ec 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -107,31 +107,19 @@ The object properties must be set as follows: - `suggestedFeeRecipient` is set to an address where the sequencer would like to direct the fees - `transactions` is an array of transactions, RLP-encoded in the [EIP-2718] - format (i.e. as a sequence of a single byte and a byte array), of the allowed - types. We specify how to select the transactions below. + format (i.e. as a sequence of a single byte and a byte array). [unix type]: https://en.wikipedia.org/wiki/Unix_time [merge]: https://ethereum.org/en/eth2/merge/ [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 > For details on RLP encoding, refer to the yellow paper, or look at [this -> hyperlinked implementation][encode-tx]. +> hyperlinked implementation][encode-tx] (which covers up to the London L1 hard fork). [encode-tx]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/transactions/Transaction.java#L84-L130 -In particular, we allow the following two transaction types: -- [EIP-1559]: the current "regular" Ethereum L1 transaction type, which - separates gas fees between a base fee and a tip -- the *[L1 attributes transaction]*, see below - -[EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 - -Historical Optimistic Ethereum transactions also include [EIP-155] transactions, -which are not accepted by the network anymore. This is not an [EIP-2718] typed -transaction, but can be distinguished from those by the fact that their -RLP-encoding's first byte will always be `>= 0xC0`. - -[EIP-155]: https://eips.ethereum.org/EIPS/eip-155 +The [EIP-2718] transactions must have a transaction type that is valid or L1, or +be an *[L1 attributes transaction]* (see below). #### Payload Transaction Format From 4ea28551c16b54eaed0dac2368b7e01075b2a371 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 17:34:16 +0100 Subject: [PATCH 066/585] specify random --- rollup-node.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rollup-node.md b/rollup-node.md index ea20f170b9ec..7db696d78f70 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -59,8 +59,11 @@ The rollup reads the following [L2 derivation inputs] for each L1 block: - block number - timestamp - basefee + - *random* (the output of the [`RANDOM` opcode][random]) - [deposits] +[random]: https://eips.ethereum.org/EIPS/eip-4399 + A deposit is an L2 transaction that has been submitted on L1, via a transaction sent to the [L2 deposit feed contract][deposit-feed]. @@ -102,8 +105,7 @@ The object properties must be set as follows: - `timestamp` is set to the current [unix time] (number of elapsed seconds since 00:00:00 UTC on 1 January 1970), rounded to the closest multiple of 2 seconds. -- `random` is currently set to all zero bytes. After [the merge][merge], the randomness - value exposed for the L1 block will be copied in this property. +- `random` is set to the *random* L1 block attribute - `suggestedFeeRecipient` is set to an address where the sequencer would like to direct the fees - `transactions` is an array of transactions, RLP-encoded in the [EIP-2718] @@ -118,7 +120,7 @@ The object properties must be set as follows: [encode-tx]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/transactions/Transaction.java#L84-L130 -The [EIP-2718] transactions must have a transaction type that is valid or L1, or +The [EIP-2718] transactions must have a transaction type that is valid on L1, or be an *[L1 attributes transaction]* (see below). #### Payload Transaction Format From 9f7ba14f4ad19480f0b42b7e7b94aca8aaf216d8 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 19:04:14 +0100 Subject: [PATCH 067/585] small changes from review feedback --- glossary.md | 24 ++++++++++++------------ rollup-node.md | 36 +++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/glossary.md b/glossary.md index 281a21f60c92..8da55d051392 100644 --- a/glossary.md +++ b/glossary.md @@ -7,7 +7,7 @@ ## Layer 1 (L1) [L1]: /glossary.md#layer-1-L1 -Refers the Ethereum blockchain, used used in contrast to [layer 2][L2], which +Refers the Ethereum blockchain, used in contrast to [layer 2][L2], which refers to Optimistic Ethereum. ## Layer 2 (L2) @@ -17,7 +17,7 @@ Refers to the Optimistic Ethereum blockchain (specified in this repository), used in contrast to [layer 1][L1], which refers to the Ethereum blockchain. ## Block -[block]: /glossary.md#layer-1-L1 +[block]: /glossary.md#block Can refer to an [L1] block, or to an [L2] block, which are structured similarly. @@ -42,9 +42,9 @@ users, as opposed to contract addresses. [Merkle root]: /glossary.md#merkle-roots The Merkle root is the root hash of a [Merkle Patricia tree] (MPT). A MPT is a -[trie], which is a tree tree structure that maps keys to values. The root hash -of a MPT is a commitment to the contents of the tree, which allows a proof to be -constructed for any key-value mapping encoded in the tree. Such a proof is +sparse [trie], which is a tree-like structure that maps keys to values. The root +hash of a MPT is a commitment to the contents of the tree, which allows a proof +to be constructed for any key-value mapping encoded in the tree. Such a proof is called a Merkle proof, and can be verified against the Merkle root. ## Chain Re-Organization @@ -133,16 +133,14 @@ inputs][deriv-inputs] found on L1, which are then passed to the [execution engine] to construct L2 blocks. "Payload attributes" is a term that originates and is specified in the [Ethereum -Engine API specification][engine-api]. +Engine API specification][engine-api], which we extend in this specification. -In addition to the [specified][engine-api] `timestamp`, `random`and -`suggestedFeeRecipient` fields, we add a field to specify the transactions that -the execution engine must include in the block and execute. +cf. [Execution Engine Specification](TODO) -> **TODO** The transaction field must be specified. +> **TODO LINK** execution engine specification -Payload attributes were historically called "L2 block inputs" and you might -still hear some people using this term. +Payload attributes were historically called "L2 block inputs" in the L2 spec and +you might still hear some people using this term. ## L1 Attributes Transaction [l1-attributes-tx]: /glossary.md#l1-attributes-transaction @@ -157,6 +155,8 @@ cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-forma (in the section on [payload attributes]) > **TODO** We might want to move this the format spec to the execution engine. +> **TODO** We might wish to make this a "normal transaction" if deposits end up +> not carrying a signature. ## L1 Attributes Precompiled Contract [l1-attr-precompile]: /glossary.md#l1-attributes-precompiled-contract diff --git a/rollup-node.md b/rollup-node.md index 7db696d78f70..b96753601ff7 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -23,9 +23,10 @@ chain][derivation] from L1 blocks. This process happens in two steps: properties][block] may be computed. While this process is conceptually a pure function from the L1 chain to the L2 -chain, it is in practice incremental. The L2 chain changes whenever new L1 -blocks (and hence new L2 derivation inputs) are added to the L1 chain, or -whenever the L1 chain [re-organizes][reorg]. +chain, it is in practice incremental. The L2 chain is extended whenever new L1 +blocks (and hence new L2 derivation inputs) are added to the L1 chain. +Similarly, the L2 chain re-organizes whenever the L1 chain +[re-organizes][reorg]. Additionally, the rollup node is responsible for [block gossip], i.e. transmitting the L2 blocks it derives over a peer-to-peer network. @@ -108,16 +109,16 @@ The object properties must be set as follows: - `random` is set to the *random* L1 block attribute - `suggestedFeeRecipient` is set to an address where the sequencer would like to direct the fees -- `transactions` is an array of transactions, RLP-encoded in the [EIP-2718] - format (i.e. as a sequence of a single byte and a byte array). +- `transactions` is an array of transactions, encoded in the [EIP-2718] format + (i.e. as a single byte defining the transaction type, concatenated with an + opaque byte array whose meaning depends on the type). + +> **TODO** we need to handle non-EIP-2718 transactions too [unix type]: https://en.wikipedia.org/wiki/Unix_time [merge]: https://ethereum.org/en/eth2/merge/ [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -> For details on RLP encoding, refer to the yellow paper, or look at [this -> hyperlinked implementation][encode-tx] (which covers up to the London L1 hard fork). - [encode-tx]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/transactions/Transaction.java#L84-L130 The [EIP-2718] transactions must have a transaction type that is valid on L1, or @@ -126,9 +127,9 @@ be an *[L1 attributes transaction]* (see below). #### Payload Transaction Format The `transactions` array is filled with the deposits, prefixed by the (single) -[L1 attributes transaction]. The deposits (which must be similarly RLP-encoded) -are simply copied byte-for-byte — it is the role of the [execution engine] to -reject invalidly-formatted transactions. +[L1 attributes transaction]. The deposits are simply copied byte-for-byte — it +is the role of the [execution engine] to reject invalidly-formatted +transactions. > **TODO** must offer some precisions on the format of deposits: sender, > receivers both in-tx-as-encoded, and on-L2-tx. What about the fees? @@ -149,6 +150,8 @@ where: When included in the `transactions` array, this transaction should be RLP-encoded in the same way as other transactions. +> **TODO** move this section into a doc specific to the execution-engine + Here is an example valid `PayloadAttributesOPV1` object, which contains an L1 attributes transaction as well as a single deposit: @@ -185,9 +188,8 @@ which itself builds upon the [JSON-RPC specification][JSON-RPC]. [JSON-RPC]: https://www.jsonrpc.org/specification In particular, the [Ethereum's Engine API specification][eth-engine-api] -specifies a [JSON-RPC] endpoint with a number of JSON-RPC (REST) routes, which -are the means through which the rollup driver interacts with the execution -engine. +specifies a [JSON-RPC] endpoint with a number of JSON-RPC routes, which are the +means through which the rollup driver interacts with the execution engine. Instead of calling [`engine_forkchoiceUpdatedV1`], the rollup driver must call the new [`engine_forkchoiceUpdatedOPV1`] route. This has the same signature, @@ -247,11 +249,11 @@ those case, the rollup driver must: 1. Locate the *common ancestor*, a block that is an ancestor of both the previous and new head. -2. Isolate the range of L1 blocks \]common ancestor, ..., new head\]. +2. Isolate the range of L1 blocks `]common ancestor, ..., new head]`. 3. For each such block, call [`engine_forkchoiceUpdatedOPV1`] and [`engine_getPayloadV1`]. - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. - - Fill the [`ForkchoiceStateV1`] object according to the [the section on the + - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but set `headBlockHash` to the hash of the last processed L2 block (use the hash of the common ancestor initially) instead of the last L2 chain head. `safeBlockHash` and @@ -272,4 +274,4 @@ Another responsability of the rollup node is to transmit the L2 blocks it derives from the L1 chain to other L2 nodes via a process called *[block gossip]*. -This is specified in [a separate document][gossip-spec]. +This is specified in the [Block Gossip Specification][gossip-spec]. From 95f3c6d8deb529fb76f13a3ba6e960b454177a0c Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 19:08:20 +0100 Subject: [PATCH 068/585] make the l1 attributes a predeploy instead of a precompile --- glossary.md | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/glossary.md b/glossary.md index 8da55d051392..902b2ceead2e 100644 --- a/glossary.md +++ b/glossary.md @@ -57,20 +57,14 @@ is not a child of the previous head. L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a consequence of L1 re-orgs, mediated via [L2 chain derivation][derivation]. -## Precompiled Contract ("Precompile") -[precompile]: /glossary.md#precompiled-contract-precompile +## Predeployed Contract ("Predeploy") +[predeploy]: /glossary.md#predeployed-contract-predeploy -A contract that exists on chain but consumes no storage, and whose invocation -does not need to result in the execution of EVM bytecode. Instead, its behaviour -is defined by specification. +A contract that was deployed on-chain at genesis (i.e. at the start of the chain). -Ethereum L1 precompiles are specified in Appendix E of the [yellow -paper][yellow]. +Optimistic Ethereum has the following pre-compiles: -Optimistic Ethereum exposes all of Ethereum's precompiles, and adds the -following precompiles: - -- [L1 Attributes Precompiled Contract][l1-attr-precompile] +- [L1 Attributes Predeployed Contract][l1-attr-predeploy] -------------------------------------------------------------------------------- @@ -149,7 +143,7 @@ A transaction with an Optimistic-Ethereum-specific transaction type, that is used to register the L1 block attributes (number, timestamp, ...) on L2. The L1 attributes for a given L1 block can be read on L2 from the [L1 Attributes -Precompiled Contract][l1-attr-precompile]. +Predeployed Contract][l1-attr-predeploy]. cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-format) (in the section on [payload attributes]) @@ -158,15 +152,15 @@ cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-forma > **TODO** We might wish to make this a "normal transaction" if deposits end up > not carrying a signature. -## L1 Attributes Precompiled Contract -[l1-attr-precompile]: /glossary.md#l1-attributes-precompiled-contract +## L1 Attributes Predeployed Contract +[l1-attr-predeploy]: /glossary.md#l1-attributes-predeployed-contract -A [precompiled contract][precompile] on L2 that can be used to retrieve the L1 +A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given block number or a given block hash. -cf. [L1 Attributes Precompiled Contract Specification](TODO) +cf. [L1 Attributes Predeployed Contract Specification](TODO) -> **TODO LINK** L1 attributes precompiled contract spec +> **TODO LINK** L1 attributes predeployed contract spec ## Deposits [deposits]: /glossary.md#deposits From 1d3596857303cc68bb5f2b29fced81f7aeca42de Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 19:13:12 +0100 Subject: [PATCH 069/585] remove block gossip, which doesn't make sense at the deposits-only stage --- glossary.md | 15 --------------- rollup-node.md | 19 ++----------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/glossary.md b/glossary.md index 902b2ceead2e..6b9a055bd372 100644 --- a/glossary.md +++ b/glossary.md @@ -82,13 +82,7 @@ The rollup node is responsible for [deriving the L2 chain][derivation] from the [L2 derivation inputs][deriv-inputs] available on L1. This is done by its [rollup driver] component. -The rollup node is also responsible for [block gossip], the process of -transmitting the L2 blocks it derives over a peer-to-peer network. - - cf. [Rollup Node Specification](/rollup-node.md) -- cf. [Block Gossip Specification](TODO) - -> **TODO LINK** block gossip spec ## Rollup Driver [rollup driver]: /glossary.md#rollup-driver @@ -190,15 +184,6 @@ cf. [L2 Deposit Feed Contract Specification](TODO) > **TODO LINK** deposit feed contract specification -## Block Gossip -[block gossip]: /glossary.md#block-gossip - -Block gossip is a [rollup node] component responsible for transmitting the L2 -blocks derived by the rollup node over a peer-to-peer network. - -> Note that block gossip is not useful in the current deposit-only model, but -> will become useful in later stages of the specification process. - -------------------------------------------------------------------------------- # Execution Engine Concepts diff --git a/rollup-node.md b/rollup-node.md index b96753601ff7..368e578462bd 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -28,16 +28,9 @@ blocks (and hence new L2 derivation inputs) are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the L1 chain [re-organizes][reorg]. -Additionally, the rollup node is responsible for [block gossip], i.e. -transmitting the L2 blocks it derives over a peer-to-peer network. - The part of the rollup node that derives the L2 chain is called the [rollup -driver]. This document is mostly concerned with the specification of the rollup -driver, while block gossip is [specified in a separate document][gossip-spec]. - -[gossip-spec]: TODO - -> **TODO LINK** block gossip spec +driver]. This document is currently only concerned with the specification of the +rollup driver. ## L2 Chain Derivation [l2-chain-derivation]: #l2-chain-derivation @@ -267,11 +260,3 @@ those case, the rollup driver must: > **TODO** Must enunciate error cases more precisely, as well as state what > should be impossible and should cause the node to stop deriving the L2 chain. - -## Block Gossip - -Another responsability of the rollup node is to transmit the L2 blocks it -derives from the L1 chain to other L2 nodes via a process called *[block -gossip]*. - -This is specified in the [Block Gossip Specification][gossip-spec]. From ab83f978ae39ba9d31c2e66ae338ab7e97d751f2 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 19:47:29 +0100 Subject: [PATCH 070/585] it's a receipt root --- glossary.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glossary.md b/glossary.md index 6b9a055bd372..64df49b884c5 100644 --- a/glossary.md +++ b/glossary.md @@ -29,8 +29,8 @@ found in code comments [here][nano-header], or in the [Ethereum yellow paper It is useful to distinguish between input block properties, which are known before executing the transactions in the block, and output bblock properties, which are derived after executing the block's transactions. These include -various [Merkle roots][Merkle root] for the L2 state and for log events emitted -during the execution. +various [Merkle roots][Merkle root] that notably commit to the L2 state and to +the log events emitted during the execution. ## EOA [EOA]: /glossary.md#EOA @@ -192,7 +192,7 @@ cf. [L2 Deposit Feed Contract Specification](TODO) [execution engine]: /glossary.md#execution-engine The execution engine is responsible for executing transactions in blocks and -computing the resulting state roots, log roots and block hash. +computing the resulting state roots, receipts roots and block hash. Both L1 (post-[merge]) and L2 have an execution engine. From 370e89b4d11d536c678c37fdd5dce25ee888b6b2 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 19:47:39 +0100 Subject: [PATCH 071/585] mention finalization guarantees --- rollup-node.md | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/rollup-node.md b/rollup-node.md index 368e578462bd..c1d9ec5f044c 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -32,6 +32,15 @@ The part of the rollup node that derives the L2 chain is called the [rollup driver]. This document is currently only concerned with the specification of the rollup driver. +## Table of Contents + +- [L2 Chain Derivation][l2-chain-derivation] + - [From L2 derivation inputs to payload attributes][payload-attr] + - [Payload Transaction Format][payload-format] + - [Building the L2 block with the execution engine][calling-exec-engine] +- [Handling L1 Re-Orgs][l1-reorgs] +- [Finalization Guarantees][finalization] + ## L2 Chain Derivation [l2-chain-derivation]: #l2-chain-derivation @@ -43,8 +52,8 @@ transaction]*) well as all L2 transactions deposited by users in the L1 block [L1 attributes transaction]: /glossary.md#l1-attributes-transaction ### From L2 derivation inputs to payload attributes - [payload-attr]: #From-L2-derivation-inputs-to-payload-attributes + [`PayloadAttributesOPV1`]: #From-L2-derivation-inputs-to-payload-attributes The rollup reads the following [L2 derivation inputs] for each L1 block: @@ -118,6 +127,7 @@ The [EIP-2718] transactions must have a transaction type that is valid on L1, or be an *[L1 attributes transaction]* (see below). #### Payload Transaction Format +[payload-format]: #payload-transaction-format The `transactions` array is filled with the deposits, prefixed by the (single) [L1 attributes transaction]. The deposits are simply copied byte-for-byte — it @@ -229,6 +239,7 @@ fully defines a new L2 block. [`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 ## Handling L1 Re-Orgs +[l1-reorgs]: #handling-L1-re-orgs The [previous section on L2 chain derivation][l2-chain-derivation] assumes linear progression of the L1 chain. It is also applicable for batch processing, @@ -256,7 +267,19 @@ those case, the rollup driver must: > meaning that it won't be able to re-org more than `FINALIZATION_DELAY_BLOCKS` > in the past, hence preserving our finalization guarantees. -> **TODO** Enunciate our finalization guarantees. - > **TODO** Must enunciate error cases more precisely, as well as state what > should be impossible and should cause the node to stop deriving the L2 chain. + +## Finalization Guarantees +[finalization]: #finalization-guarantees + +As already alluded to in the section on [interacting with the execution +engine][calling-exec-engine], an L2 block is considered *finalized* after a +delay of `FINALIZATION_DELAY_BLOCKS == 50400` blocks after the L1 block that +generated it. This is a duration of approximately 7 days worth of L1 blocks. + +L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality], so +these L2 blocks can safely be considered to be final: they will never disappear +from the chain's history because of a re-org. + +[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge/ From 83a32d93f41b291722e33357117b21aedc9b4af1 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 20:01:58 +0100 Subject: [PATCH 072/585] fix links --- rollup-node.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/rollup-node.md b/rollup-node.md index c1d9ec5f044c..54662e6d51eb 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -173,8 +173,12 @@ attributes transaction as well as a single deposit: ### Building the L2 block with the execution engine [calling-exec-engine]: #building-the-L2-block-with-the-execution-engine -The Optimistic Ethereum [execution engine] is [specified in its own -document][execution-engine-spec]. +The Optimistic Ethereum [execution engine] is specified in the [Execution Engine +Specification]. + +> **TODO LINK** execution engine spec + +[Execution Engine Specification]: TODO This section defines how the rollup driver must interact with the execution engine's in order to convert [payload attributes] into L2 blocks. @@ -204,10 +208,11 @@ except that: > **TODO LINK** forkchoiceUpdatedOPV1 from spec - it takes a [`PayloadAttributesOPV1`] object as input instead of - [`PayloadAttributesV1`]. The execution engine must include the valid - transactions supplied in this object in the block, in the same order as they - were supplied, and only those. See the [previous section][payload-attr] for - the specification of how the properties must be set. + [`PayloadAttributesV1`][PayloadAttributesV1]. The execution engine must + include the valid transactions supplied in this object in the block, in the + same order as they were supplied, and only those. See the [previous + section][payload-attr] for the specification of how the properties must be + set. - we repurpose the [`ForkchoiceStateV1`] structure with the following property semantics: @@ -219,7 +224,8 @@ except that: block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of - the first L1 block for which an L2 block was produced). + the first L1 block for which an L2 block was produced). See the + [Finalization Guarantees][finalization] section for more details. [`ForkchoiceStateV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#ForkchoiceStateV1 From eccb8e50d8426222a3c7913f905a3caf10d0fb74 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 20:02:12 +0100 Subject: [PATCH 073/585] add TODO for handling error conditions --- rollup-node.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rollup-node.md b/rollup-node.md index 54662e6d51eb..976a69caf09a 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -233,6 +233,9 @@ except that: > to the regular (non-engine-API) JSON-RPC endpoint of the execution engine. > [See here for more information.][L2-JSON-RPC-API] +> **TODO** specify the behaviour in case the resulting object reports `"SYNCING"` +> or an error + [L2-JSON-RPC-API]: TODO > **TODO LINK** L2 JSON RPC API (might be the same as [L1's][JSON-RPC-API]) @@ -244,6 +247,8 @@ fully defines a new L2 block. [`engine_getPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_getpayloadv1 [`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 +> **TODO** specify the behaviour in case the resulting object reports an error + ## Handling L1 Re-Orgs [l1-reorgs]: #handling-L1-re-orgs From dd42e89e15e805559f0dd86d4ee819de287ff538 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 2 Dec 2021 20:18:21 +0100 Subject: [PATCH 074/585] l2 deposit feed contract -> deposit feed contract --- glossary.md | 12 ++++++------ rollup-node.md | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/glossary.md b/glossary.md index 64df49b884c5..5baa87ec3cdf 100644 --- a/glossary.md +++ b/glossary.md @@ -160,7 +160,7 @@ cf. [L1 Attributes Predeployed Contract Specification](TODO) [deposits]: /glossary.md#deposits A deposit is an L2 transaction that has been submitted on L1, via a transaction -sent to the [L2 deposit feed contract][deposit-feed]. +sent to the [deposit feed contract][deposit-feed]. While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be understood as "a transaction @@ -168,11 +168,11 @@ tokens to L2, the word *deposit* should be understood as "a transaction Deposits are one kind of [L2 derivation input][deriv-input]. -## L2 Deposit Feed Contract -[deposit-feed]: /glossary.md#L2-deposit-feed-contract +## Deposit Feed Contract +[deposit-feed]: /glossary.md#deposit-feed-contract -A contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits -are emitted as log records (in Solidity, these are called *events*) for +An [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The +deposits are emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. Advanced note: the deposits are not stored in calldata because they can be send @@ -180,7 +180,7 @@ by contracts, in which case the calldata is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 block. -cf. [L2 Deposit Feed Contract Specification](TODO) +cf. [Deposit Feed Contract Specification](TODO) > **TODO LINK** deposit feed contract specification diff --git a/rollup-node.md b/rollup-node.md index 976a69caf09a..0aec364141c9 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -68,16 +68,16 @@ The rollup reads the following [L2 derivation inputs] for each L1 block: [random]: https://eips.ethereum.org/EIPS/eip-4399 A deposit is an L2 transaction that has been submitted on L1, via a transaction -sent to the [L2 deposit feed contract][deposit-feed]. +sent to the [deposit feed contract][deposit-feed]. While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be understood as "a transaction *deposited* to L2". The L1 attributes are read from the L1 block header, while deposits are read -from the block's log entries. Refer to the [**L2 deposit feed contract -specification**][deposit-feed] for details on how deposits are encoded as -log entries. +from the block's log entries. Refer to the [**deposit feed contract +specification**][deposit-feed] for details on how deposits are encoded as log +entries. [deposit-feed-spec]: TODO From 6a8b1863e474b99a4853cb28467e998e466c065d Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 6 Dec 2021 17:54:25 +0100 Subject: [PATCH 075/585] misc small fixes from reviews --- glossary.md | 6 +++--- rollup-node.md | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/glossary.md b/glossary.md index 5baa87ec3cdf..4e554212e6df 100644 --- a/glossary.md +++ b/glossary.md @@ -27,7 +27,7 @@ found in code comments [here][nano-header], or in the [Ethereum yellow paper (pdf)][yellow], section 4.3. It is useful to distinguish between input block properties, which are known -before executing the transactions in the block, and output bblock properties, +before executing the transactions in the block, and output block properties, which are derived after executing the block's transactions. These include various [Merkle roots][Merkle root] that notably commit to the L2 state and to the log events emitted during the execution. @@ -60,9 +60,9 @@ consequence of L1 re-orgs, mediated via [L2 chain derivation][derivation]. ## Predeployed Contract ("Predeploy") [predeploy]: /glossary.md#predeployed-contract-predeploy -A contract that was deployed on-chain at genesis (i.e. at the start of the chain). +A contract placed in the L2 genesis state (i.e. at the start of the chain). -Optimistic Ethereum has the following pre-compiles: +Optimistic Ethereum has the following predeploys: - [L1 Attributes Predeployed Contract][l1-attr-predeploy] diff --git a/rollup-node.md b/rollup-node.md index 0aec364141c9..f7c5ae3ea068 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -44,8 +44,8 @@ rollup driver. ## L2 Chain Derivation [l2-chain-derivation]: #l2-chain-derivation -This section specifies how the [rollup driver] derives one L2 block from every -L1 block. The L2 block will carry the L1 block attributes (as a *[L1 attributes +This section specifies how the [rollup driver] derives one L2 block per every L1 +block. The L2 block will carry the L1 block attributes (as a *[L1 attributes transaction]*) well as all L2 transactions deposited by users in the L1 block (*[deposits]*). @@ -67,8 +67,8 @@ The rollup reads the following [L2 derivation inputs] for each L1 block: [random]: https://eips.ethereum.org/EIPS/eip-4399 -A deposit is an L2 transaction that has been submitted on L1, via a transaction -sent to the [deposit feed contract][deposit-feed]. +A deposit is an L2 transaction that has been submitted on L1, via a call sent to +the [deposit feed contract][deposit-feed]. While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be understood as "a transaction @@ -108,6 +108,7 @@ The object properties must be set as follows: - `timestamp` is set to the current [unix time] (number of elapsed seconds since 00:00:00 UTC on 1 January 1970), rounded to the closest multiple of 2 seconds. + No two blocks may have the same timestamp. - `random` is set to the *random* L1 block attribute - `suggestedFeeRecipient` is set to an address where the sequencer would like to direct the fees From 8690000958300dac9c75ea6b15d267efdf300e66 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 6 Dec 2021 19:49:31 +0100 Subject: [PATCH 076/585] excise 'L2 derivation inputs' from the spec --- glossary.md | 24 ++++++++++++++++++------ rollup-node.md | 29 ++++++++++++++--------------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/glossary.md b/glossary.md index 4e554212e6df..f1d190c339e5 100644 --- a/glossary.md +++ b/glossary.md @@ -66,6 +66,18 @@ Optimistic Ethereum has the following predeploys: - [L1 Attributes Predeployed Contract][l1-attr-predeploy] +## Receipt +[receipt]: /glossary.md#receipt + +A receipt is an output generated by a transaction, comprising a status code, the +amount of gas used, a list of log entries, and a [bloom filter] indexing these +entries. Log entries are most notably used to encode [Solidity events]. + +Receipts are not stored in blocks, but blocks store a [Merkle root] for a tree +containing the receipt for every transaction in the block. + +Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. + -------------------------------------------------------------------------------- # L2 Chain Concepts @@ -79,8 +91,8 @@ The L1 block number for which the first block of the L2 chain was generated. [rollup node]: /glossary.md#rollup-node The rollup node is responsible for [deriving the L2 chain][derivation] from the -[L2 derivation inputs][deriv-inputs] available on L1. This is done by its -[rollup driver] component. +L1 chain (L1 [blocks][block] and their associated [receipts][receipt]). This is +done by its [rollup driver] component. - cf. [Rollup Node Specification](/rollup-node.md) @@ -88,8 +100,8 @@ The rollup node is responsible for [deriving the L2 chain][derivation] from the [rollup driver]: /glossary.md#rollup-driver The rollup driver is the [rollup node] component responsible for [deriving the -L2 chain][derivation] from the [L2 derivation inputs][deriv-inputs] available on -L1. +L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their associated +[receipts][receipt]). ## L2 Chain Derivation [derivation]: /glossary.md#L2-chain-derivation @@ -207,11 +219,11 @@ blocks][derivations]. In these specifications, "execution engine" always refer to the L2 execution engine, unless otherwise specified. - - [Merkle Patricia tree]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md [trie]: https://en.wikipedia.org/wiki/Trie +[bloom filter]: https://en.wikipedia.org/wiki/Bloom_filter +[Solidity events]: https://docs.soliditylang.org/en/latest/contracts.html?highlight=events#events [nano-header]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/blocks/BlockHeader.java#L22-L156 [yellow]: https://ethereum.github.io/yellowpaper/paper.pdf [engine-api]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#PayloadAttributesV1 diff --git a/rollup-node.md b/rollup-node.md index f7c5ae3ea068..65d30b74457e 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -3,7 +3,6 @@ [rollup node]: /glossary.md#rollup-node [derivation]: /glossary.md#L2-chain-derivation -[L2 derivation inputs]: /glossary.md#L2-derivation-inputs [payload attributes]: /glossary.md#payload-attributes [block]: /glossary.md#block [execution engine]: /glossary.md#execution-engine @@ -13,20 +12,21 @@ [deposits]: /glossary.md#deposits [deposit-feed]: /glossary.md#L2-deposit-feed-contract [L2 chain inception]: /glossary.md#L2-chain-inception +[receipts]: /glossary.md#receipt The [rollup node] is the component responsible for [deriving the L2 -chain][derivation] from L1 blocks. This process happens in two steps: +chain][derivation] from L1 blocks (and their associated [receipts]). This process +happens in two steps: -1. Read [L2 derivation inputs] from L1 and generate [payload attributes] (essentially - [a block without output properties][block]). +1. Read from L1 blocks and associated receipts, in order to generate [payload + attributes] (essentially [a block without output properties][block]). 2. Pass the payload attributes to the [execution engine], so that [output block properties][block] may be computed. While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The L2 chain is extended whenever new L1 -blocks (and hence new L2 derivation inputs) are added to the L1 chain. -Similarly, the L2 chain re-organizes whenever the L1 chain -[re-organizes][reorg]. +blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever +the L1 chain [re-organizes][reorg]. The part of the rollup node that derives the L2 chain is called the [rollup driver]. This document is currently only concerned with the specification of the @@ -35,7 +35,7 @@ rollup driver. ## Table of Contents - [L2 Chain Derivation][l2-chain-derivation] - - [From L2 derivation inputs to payload attributes][payload-attr] + - [From L1 blocks to payload attributes][payload-attr] - [Payload Transaction Format][payload-format] - [Building the L2 block with the execution engine][calling-exec-engine] - [Handling L1 Re-Orgs][l1-reorgs] @@ -51,12 +51,11 @@ transaction]*) well as all L2 transactions deposited by users in the L1 block [L1 attributes transaction]: /glossary.md#l1-attributes-transaction -### From L2 derivation inputs to payload attributes -[payload-attr]: #From-L2-derivation-inputs-to-payload-attributes +### From L1 blocks to payload attributes +[payload-attr]: #From-L1-blocks-to-payload-attributes +[`PayloadAttributesOPV1`]: #From-L1-blocks-to-payload-attributes -[`PayloadAttributesOPV1`]: #From-L2-derivation-inputs-to-payload-attributes - -The rollup reads the following [L2 derivation inputs] for each L1 block: +The rollup reads the following data from each L1 block: - L1 block attributes - block number @@ -75,7 +74,7 @@ tokens to L2, the word *deposit* should be understood as "a transaction *deposited* to L2". The L1 attributes are read from the L1 block header, while deposits are read -from the block's log entries. Refer to the [**deposit feed contract +from the block's [receipts]. Refer to the [**deposit feed contract specification**][deposit-feed] for details on how deposits are encoded as log entries. @@ -83,7 +82,7 @@ entries. > **TODO LINK** deposit feed contract specification -From these L2 derivation inputs, the rollup node constructs an expanded version +From the data read from , the rollup node constructs an expanded version of the [Engine API PayloadAttributesV1 object][PayloadAttributesV1]: [PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 From 718c04a6e1b1c77f64969412e262e756d308ceff Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 7 Dec 2021 15:34:03 +0100 Subject: [PATCH 077/585] basic linting --- glossary.md | 26 +++++++++++++++++++++++--- rollup-node.md | 24 +++++++++++++++--------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/glossary.md b/glossary.md index f1d190c339e5..afa66e48c007 100644 --- a/glossary.md +++ b/glossary.md @@ -5,18 +5,21 @@ # General Terms ## Layer 1 (L1) + [L1]: /glossary.md#layer-1-L1 Refers the Ethereum blockchain, used in contrast to [layer 2][L2], which refers to Optimistic Ethereum. ## Layer 2 (L2) + [L2]: /glossary.md#layer-2-L2 Refers to the Optimistic Ethereum blockchain (specified in this repository), used in contrast to [layer 1][L1], which refers to the Ethereum blockchain. ## Block + [block]: /glossary.md#block Can refer to an [L1] block, or to an [L2] block, which are structured similarly. @@ -33,12 +36,14 @@ various [Merkle roots][Merkle root] that notably commit to the L2 state and to the log events emitted during the execution. ## EOA + [EOA]: /glossary.md#EOA "Externally Owned Account", an Ethereum term to designate addresses operated by users, as opposed to contract addresses. ## Merkle Root + [Merkle root]: /glossary.md#merkle-roots The Merkle root is the root hash of a [Merkle Patricia tree] (MPT). A MPT is a @@ -48,6 +53,7 @@ to be constructed for any key-value mapping encoded in the tree. Such a proof is called a Merkle proof, and can be verified against the Merkle root. ## Chain Re-Organization + [reorg]: /glossary.md#chain-re-organization A re-organization, or re-org for short, is whenever the head of a blockchain @@ -58,6 +64,7 @@ L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a consequence of L1 re-orgs, mediated via [L2 chain derivation][derivation]. ## Predeployed Contract ("Predeploy") + [predeploy]: /glossary.md#predeployed-contract-predeploy A contract placed in the L2 genesis state (i.e. at the start of the chain). @@ -67,6 +74,7 @@ Optimistic Ethereum has the following predeploys: - [L1 Attributes Predeployed Contract][l1-attr-predeploy] ## Receipt + [receipt]: /glossary.md#receipt A receipt is an output generated by a transaction, comprising a status code, the @@ -83,11 +91,13 @@ Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. # L2 Chain Concepts ## L2 Chain Inception + [L2 chain inception]: /glossary.md#L2-chain-inception The L1 block number for which the first block of the L2 chain was generated. ## Rollup Node + [rollup node]: /glossary.md#rollup-node The rollup node is responsible for [deriving the L2 chain][derivation] from the @@ -97,6 +107,7 @@ done by its [rollup driver] component. - cf. [Rollup Node Specification](/rollup-node.md) ## Rollup Driver + [rollup driver]: /glossary.md#rollup-driver The rollup driver is the [rollup node] component responsible for [deriving the @@ -104,6 +115,7 @@ L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their associated [receipts][receipt]). ## L2 Chain Derivation + [derivation]: /glossary.md#L2-chain-derivation A process that reads [L2 derivation inputs][deriv-inputs] from L1 in order to @@ -113,19 +125,22 @@ cf. [L2 Chain Derivation (in Rollup Node Specification)](/rollup-node.md#l2-chain-derivation) ## L2 Derivation Inputs + [deriv-inputs]: /glossary.md#l2-chain-derivation-inputs This term refers to data that is found in L1 blocks and is read by the [rollup node] to construct [payload attributes]. Chain derivation attributes include: + - L1 block attributes - - block number - - timestamp - - basefee + - block number + - timestamp + - basefee - [deposits] ## Payload Attributes + [payload attributes]: /glossary.md#payload-attributes This term refers to data that can be derived from [L2 chain derivation @@ -143,6 +158,7 @@ Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using this term. ## L1 Attributes Transaction + [l1-attributes-tx]: /glossary.md#l1-attributes-transaction A transaction with an Optimistic-Ethereum-specific transaction type, that is @@ -159,6 +175,7 @@ cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-forma > not carrying a signature. ## L1 Attributes Predeployed Contract + [l1-attr-predeploy]: /glossary.md#l1-attributes-predeployed-contract A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 @@ -169,6 +186,7 @@ cf. [L1 Attributes Predeployed Contract Specification](TODO) > **TODO LINK** L1 attributes predeployed contract spec ## Deposits + [deposits]: /glossary.md#deposits A deposit is an L2 transaction that has been submitted on L1, via a transaction @@ -181,6 +199,7 @@ tokens to L2, the word *deposit* should be understood as "a transaction Deposits are one kind of [L2 derivation input][deriv-input]. ## Deposit Feed Contract + [deposit-feed]: /glossary.md#deposit-feed-contract An [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The @@ -201,6 +220,7 @@ cf. [Deposit Feed Contract Specification](TODO) # Execution Engine Concepts ## Execution Engine + [execution engine]: /glossary.md#execution-engine The execution engine is responsible for executing transactions in blocks and diff --git a/rollup-node.md b/rollup-node.md index 65d30b74457e..a3953c0b1cf5 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -42,6 +42,7 @@ rollup driver. - [Finalization Guarantees][finalization] ## L2 Chain Derivation + [l2-chain-derivation]: #l2-chain-derivation This section specifies how the [rollup driver] derives one L2 block per every L1 @@ -52,16 +53,17 @@ transaction]*) well as all L2 transactions deposited by users in the L1 block [L1 attributes transaction]: /glossary.md#l1-attributes-transaction ### From L1 blocks to payload attributes + [payload-attr]: #From-L1-blocks-to-payload-attributes [`PayloadAttributesOPV1`]: #From-L1-blocks-to-payload-attributes The rollup reads the following data from each L1 block: - L1 block attributes - - block number - - timestamp - - basefee - - *random* (the output of the [`RANDOM` opcode][random]) + - block number + - timestamp + - basefee + - *random* (the output of the [`RANDOM` opcode][random]) - [deposits] [random]: https://eips.ethereum.org/EIPS/eip-4399 @@ -87,12 +89,12 @@ of the [Engine API PayloadAttributesV1 object][PayloadAttributesV1]: [PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 -``` +```js PayloadAttributesOPV1: { - timestamp: QUANTITY - random: DATA (32 bytes) - suggestedFeeRecipient: DATA (20 bytes) - transactions: array of DATA + timestamp: QUANTITY + random: DATA (32 bytes) + suggestedFeeRecipient: DATA (20 bytes) + transactions: array of DATA } ``` @@ -127,6 +129,7 @@ The [EIP-2718] transactions must have a transaction type that is valid on L1, or be an *[L1 attributes transaction]* (see below). #### Payload Transaction Format + [payload-format]: #payload-transaction-format The `transactions` array is filled with the deposits, prefixed by the (single) @@ -171,6 +174,7 @@ attributes transaction as well as a single deposit: ``` ### Building the L2 block with the execution engine + [calling-exec-engine]: #building-the-L2-block-with-the-execution-engine The Optimistic Ethereum [execution engine] is specified in the [Execution Engine @@ -250,6 +254,7 @@ fully defines a new L2 block. > **TODO** specify the behaviour in case the resulting object reports an error ## Handling L1 Re-Orgs + [l1-reorgs]: #handling-L1-re-orgs The [previous section on L2 chain derivation][l2-chain-derivation] assumes @@ -282,6 +287,7 @@ those case, the rollup driver must: > should be impossible and should cause the node to stop deriving the L2 chain. ## Finalization Guarantees + [finalization]: #finalization-guarantees As already alluded to in the section on [interacting with the execution From d5d2bee1211919afb2e80e94b96e0c8422ef445f Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 7 Dec 2021 16:09:18 +0100 Subject: [PATCH 078/585] refill text to 120 character lines --- glossary.md | 138 ++++++++++++++------------------ rollup-node.md | 210 ++++++++++++++++++++----------------------------- 2 files changed, 145 insertions(+), 203 deletions(-) diff --git a/glossary.md b/glossary.md index afa66e48c007..a3667e2aed7d 100644 --- a/glossary.md +++ b/glossary.md @@ -1,6 +1,6 @@ # Glossary --------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------------------------ # General Terms @@ -8,15 +8,14 @@ [L1]: /glossary.md#layer-1-L1 -Refers the Ethereum blockchain, used in contrast to [layer 2][L2], which -refers to Optimistic Ethereum. +Refers the Ethereum blockchain, used in contrast to [layer 2][L2], which refers to Optimistic Ethereum. ## Layer 2 (L2) [L2]: /glossary.md#layer-2-L2 -Refers to the Optimistic Ethereum blockchain (specified in this repository), -used in contrast to [layer 1][L1], which refers to the Ethereum blockchain. +Refers to the Optimistic Ethereum blockchain (specified in this repository), used in contrast to [layer 1][L1], which +refers to the Ethereum blockchain. ## Block @@ -24,44 +23,38 @@ used in contrast to [layer 1][L1], which refers to the Ethereum blockchain. Can refer to an [L1] block, or to an [L2] block, which are structured similarly. -A block is a sequential list of transactions, along with a couple of properties -stored in the *header* of the block. A description of these properties can be -found in code comments [here][nano-header], or in the [Ethereum yellow paper +A block is a sequential list of transactions, along with a couple of properties stored in the *header* of the block. A +description of these properties can be found in code comments [here][nano-header], or in the [Ethereum yellow paper (pdf)][yellow], section 4.3. -It is useful to distinguish between input block properties, which are known -before executing the transactions in the block, and output block properties, -which are derived after executing the block's transactions. These include -various [Merkle roots][Merkle root] that notably commit to the L2 state and to -the log events emitted during the execution. +It is useful to distinguish between input block properties, which are known before executing the transactions in the +block, and output block properties, which are derived after executing the block's transactions. These include various +[Merkle roots][Merkle root] that notably commit to the L2 state and to the log events emitted during the execution. ## EOA [EOA]: /glossary.md#EOA -"Externally Owned Account", an Ethereum term to designate addresses operated by -users, as opposed to contract addresses. +"Externally Owned Account", an Ethereum term to designate addresses operated by users, as opposed to contract addresses. ## Merkle Root [Merkle root]: /glossary.md#merkle-roots -The Merkle root is the root hash of a [Merkle Patricia tree] (MPT). A MPT is a -sparse [trie], which is a tree-like structure that maps keys to values. The root -hash of a MPT is a commitment to the contents of the tree, which allows a proof -to be constructed for any key-value mapping encoded in the tree. Such a proof is -called a Merkle proof, and can be verified against the Merkle root. +The Merkle root is the root hash of a [Merkle Patricia tree] (MPT). A MPT is a sparse [trie], which is a tree-like +structure that maps keys to values. The root hash of a MPT is a commitment to the contents of the tree, which allows a +proof to be constructed for any key-value mapping encoded in the tree. Such a proof is called a Merkle proof, and can be +verified against the Merkle root. ## Chain Re-Organization [reorg]: /glossary.md#chain-re-organization -A re-organization, or re-org for short, is whenever the head of a blockchain -(its last block) changes (as dictated by the [fork choice rule]) to a block that -is not a child of the previous head. +A re-organization, or re-org for short, is whenever the head of a blockchain (its last block) changes (as dictated by +the [fork choice rule]) to a block that is not a child of the previous head. -L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a -consequence of L1 re-orgs, mediated via [L2 chain derivation][derivation]. +L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a consequence of L1 re-orgs, mediated via +[L2 chain derivation][derivation]. ## Predeployed Contract ("Predeploy") @@ -77,16 +70,15 @@ Optimistic Ethereum has the following predeploys: [receipt]: /glossary.md#receipt -A receipt is an output generated by a transaction, comprising a status code, the -amount of gas used, a list of log entries, and a [bloom filter] indexing these -entries. Log entries are most notably used to encode [Solidity events]. +A receipt is an output generated by a transaction, comprising a status code, the amount of gas used, a list of log +entries, and a [bloom filter] indexing these entries. Log entries are most notably used to encode [Solidity events]. -Receipts are not stored in blocks, but blocks store a [Merkle root] for a tree -containing the receipt for every transaction in the block. +Receipts are not stored in blocks, but blocks store a [Merkle root] for a tree containing the receipt for every +transaction in the block. Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. --------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------------------------ # L2 Chain Concepts @@ -100,9 +92,8 @@ The L1 block number for which the first block of the L2 chain was generated. [rollup node]: /glossary.md#rollup-node -The rollup node is responsible for [deriving the L2 chain][derivation] from the -L1 chain (L1 [blocks][block] and their associated [receipts][receipt]). This is -done by its [rollup driver] component. +The rollup node is responsible for [deriving the L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their +associated [receipts][receipt]). This is done by its [rollup driver] component. - cf. [Rollup Node Specification](/rollup-node.md) @@ -110,16 +101,14 @@ done by its [rollup driver] component. [rollup driver]: /glossary.md#rollup-driver -The rollup driver is the [rollup node] component responsible for [deriving the -L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their associated -[receipts][receipt]). +The rollup driver is the [rollup node] component responsible for [deriving the L2 chain][derivation] from the L1 chain +(L1 [blocks][block] and their associated [receipts][receipt]). ## L2 Chain Derivation [derivation]: /glossary.md#L2-chain-derivation -A process that reads [L2 derivation inputs][deriv-inputs] from L1 in order to -derive the L2 chain. +A process that reads [L2 derivation inputs][deriv-inputs] from L1 in order to derive the L2 chain. cf. [L2 Chain Derivation (in Rollup Node Specification)](/rollup-node.md#l2-chain-derivation) @@ -128,8 +117,7 @@ Specification)](/rollup-node.md#l2-chain-derivation) [deriv-inputs]: /glossary.md#l2-chain-derivation-inputs -This term refers to data that is found in L1 blocks and is read by the [rollup -node] to construct [payload attributes]. +This term refers to data that is found in L1 blocks and is read by the [rollup node] to construct [payload attributes]. Chain derivation attributes include: @@ -143,34 +131,34 @@ Chain derivation attributes include: [payload attributes]: /glossary.md#payload-attributes -This term refers to data that can be derived from [L2 chain derivation -inputs][deriv-inputs] found on L1, which are then passed to the [execution -engine] to construct L2 blocks. +This term refers to data that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are then +passed to the [execution engine] to construct L2 blocks. -"Payload attributes" is a term that originates and is specified in the [Ethereum -Engine API specification][engine-api], which we extend in this specification. +"Payload attributes" is a term that originates and is specified in the [Ethereum Engine API specification][engine-api], +which we extend in this specification. cf. [Execution Engine Specification](TODO) > **TODO LINK** execution engine specification -Payload attributes were historically called "L2 block inputs" in the L2 spec and -you might still hear some people using this term. +Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using +this term. ## L1 Attributes Transaction [l1-attributes-tx]: /glossary.md#l1-attributes-transaction -A transaction with an Optimistic-Ethereum-specific transaction type, that is -used to register the L1 block attributes (number, timestamp, ...) on L2. +A transaction with an Optimistic-Ethereum-specific transaction type, that is used to register the L1 block attributes +(number, timestamp, ...) on L2. -The L1 attributes for a given L1 block can be read on L2 from the [L1 Attributes -Predeployed Contract][l1-attr-predeploy]. +The L1 attributes for a given L1 block can be read on L2 from the [L1 Attributes Predeployed +Contract][l1-attr-predeploy]. -cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-format) -(in the section on [payload attributes]) +cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-format) (in the section on [payload +attributes]) > **TODO** We might want to move this the format spec to the execution engine. + > **TODO** We might wish to make this a "normal transaction" if deposits end up > not carrying a signature. @@ -178,8 +166,8 @@ cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-forma [l1-attr-predeploy]: /glossary.md#l1-attributes-predeployed-contract -A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 -block attributes of L1 blocks with a given block number or a given block hash. +A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given +block number or a given block hash. cf. [L1 Attributes Predeployed Contract Specification](TODO) @@ -189,12 +177,11 @@ cf. [L1 Attributes Predeployed Contract Specification](TODO) [deposits]: /glossary.md#deposits -A deposit is an L2 transaction that has been submitted on L1, via a transaction -sent to the [deposit feed contract][deposit-feed]. +A deposit is an L2 transaction that has been submitted on L1, via a transaction sent to the [deposit feed +contract][deposit-feed]. -While deposits are notably (but not only) used to "deposit" (bridge) ETH and -tokens to L2, the word *deposit* should be understood as "a transaction -*deposited* to L2". +While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be +understood as "a transaction *deposited* to L2". Deposits are one kind of [L2 derivation input][deriv-input]. @@ -202,20 +189,18 @@ Deposits are one kind of [L2 derivation input][deriv-input]. [deposit-feed]: /glossary.md#deposit-feed-contract -An [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The -deposits are emitted as log records (in Solidity, these are called *events*) for -consumption by [rollup nodes][rollup node]. +An [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are emitted as log records (in +Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. -Advanced note: the deposits are not stored in calldata because they can be send -by contracts, in which case the calldata is part of the execution, but its value -is not captured in one of the [Merkle roots][Merkle root] included in the L1 +Advanced note: the deposits are not stored in calldata because they can be send by contracts, in which case the calldata +is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 block. cf. [Deposit Feed Contract Specification](TODO) > **TODO LINK** deposit feed contract specification --------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------------------------ # Execution Engine Concepts @@ -223,21 +208,18 @@ cf. [Deposit Feed Contract Specification](TODO) [execution engine]: /glossary.md#execution-engine -The execution engine is responsible for executing transactions in blocks and -computing the resulting state roots, receipts roots and block hash. +The execution engine is responsible for executing transactions in blocks and computing the resulting state roots, +receipts roots and block hash. Both L1 (post-[merge]) and L2 have an execution engine. -On L1, the executed blocks can come from L1 block synchronization; or from a block -freshly minted by the execution engine (using transactions from the L1 -[mempool]), at the request of the L1 consensus layer. +On L1, the executed blocks can come from L1 block synchronization; or from a block freshly minted by the execution +engine (using transactions from the L1 [mempool]), at the request of the L1 consensus layer. -On L2, the executed blocks are freshly minted by the execution engine at the -request of the [rollup node], using transactions [derived from L1 -blocks][derivations]. +On L2, the executed blocks are freshly minted by the execution engine at the request of the [rollup node], using +transactions [derived from L1 blocks][derivations]. -In these specifications, "execution engine" always refer to the L2 execution -engine, unless otherwise specified. +In these specifications, "execution engine" always refer to the L2 execution engine, unless otherwise specified. [Merkle Patricia tree]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md diff --git a/rollup-node.md b/rollup-node.md index a3953c0b1cf5..b575eccb2769 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -14,23 +14,19 @@ [L2 chain inception]: /glossary.md#L2-chain-inception [receipts]: /glossary.md#receipt -The [rollup node] is the component responsible for [deriving the L2 -chain][derivation] from L1 blocks (and their associated [receipts]). This process -happens in two steps: +The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their +associated [receipts]). This process happens in two steps: -1. Read from L1 blocks and associated receipts, in order to generate [payload - attributes] (essentially [a block without output properties][block]). -2. Pass the payload attributes to the [execution engine], so that [output block - properties][block] may be computed. +1. Read from L1 blocks and associated receipts, in order to generate [payload attributes] (essentially [a block without + output properties][block]). +2. Pass the payload attributes to the [execution engine], so that [output block properties][block] may be computed. -While this process is conceptually a pure function from the L1 chain to the L2 -chain, it is in practice incremental. The L2 chain is extended whenever new L1 -blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever -the L1 chain [re-organizes][reorg]. +While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The +L2 chain is extended whenever new L1 blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the +L1 chain [re-organizes][reorg]. -The part of the rollup node that derives the L2 chain is called the [rollup -driver]. This document is currently only concerned with the specification of the -rollup driver. +The part of the rollup node that derives the L2 chain is called the [rollup driver]. This document is currently only +concerned with the specification of the rollup driver. ## Table of Contents @@ -45,9 +41,8 @@ rollup driver. [l2-chain-derivation]: #l2-chain-derivation -This section specifies how the [rollup driver] derives one L2 block per every L1 -block. The L2 block will carry the L1 block attributes (as a *[L1 attributes -transaction]*) well as all L2 transactions deposited by users in the L1 block +This section specifies how the [rollup driver] derives one L2 block per every L1 block. The L2 block will carry the L1 +block attributes (as a *[L1 attributes transaction]*) well as all L2 transactions deposited by users in the L1 block (*[deposits]*). [L1 attributes transaction]: /glossary.md#l1-attributes-transaction @@ -68,24 +63,21 @@ The rollup reads the following data from each L1 block: [random]: https://eips.ethereum.org/EIPS/eip-4399 -A deposit is an L2 transaction that has been submitted on L1, via a call sent to -the [deposit feed contract][deposit-feed]. +A deposit is an L2 transaction that has been submitted on L1, via a call sent to the [deposit feed +contract][deposit-feed]. -While deposits are notably (but not only) used to "deposit" (bridge) ETH and -tokens to L2, the word *deposit* should be understood as "a transaction -*deposited* to L2". +While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be +understood as "a transaction *deposited* to L2". -The L1 attributes are read from the L1 block header, while deposits are read -from the block's [receipts]. Refer to the [**deposit feed contract -specification**][deposit-feed] for details on how deposits are encoded as log -entries. +The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the +[**deposit feed contract specification**][deposit-feed] for details on how deposits are encoded as log entries. [deposit-feed-spec]: TODO > **TODO LINK** deposit feed contract specification -From the data read from , the rollup node constructs an expanded version -of the [Engine API PayloadAttributesV1 object][PayloadAttributesV1]: +From the data read from , the rollup node constructs an expanded version of the [Engine API PayloadAttributesV1 +object][PayloadAttributesV1]: [PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 @@ -98,24 +90,20 @@ PayloadAttributesOPV1: { } ``` -The type notation used here refers to the [HEX value encoding] used by the -[Ethereum JSON-RPC API specification][JSON-RPC-API], as this structure will need to -be sent over JSON-RPC. `array` refers to a JSON array. +The type notation used here refers to the [HEX value encoding] used by the [Ethereum JSON-RPC API +specification][JSON-RPC-API], as this structure will need to be sent over JSON-RPC. `array` refers to a JSON array. [HEX value encoding]: https://eth.wiki/json-rpc/API#hex-value-encoding [JSON-RPC-API]: https://eth.wiki/json-rpc/API The object properties must be set as follows: -- `timestamp` is set to the current [unix time] (number of elapsed seconds since - 00:00:00 UTC on 1 January 1970), rounded to the closest multiple of 2 seconds. - No two blocks may have the same timestamp. +- `timestamp` is set to the current [unix time] (number of elapsed seconds since 00:00:00 UTC on 1 January 1970), + rounded to the closest multiple of 2 seconds. No two blocks may have the same timestamp. - `random` is set to the *random* L1 block attribute -- `suggestedFeeRecipient` is set to an address where the sequencer would like to - direct the fees -- `transactions` is an array of transactions, encoded in the [EIP-2718] format - (i.e. as a single byte defining the transaction type, concatenated with an - opaque byte array whose meaning depends on the type). +- `suggestedFeeRecipient` is set to an address where the sequencer would like to direct the fees +- `transactions` is an array of transactions, encoded in the [EIP-2718] format (i.e. as a single byte defining the + transaction type, concatenated with an opaque byte array whose meaning depends on the type). > **TODO** we need to handle non-EIP-2718 transactions too @@ -125,41 +113,35 @@ The object properties must be set as follows: [encode-tx]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/transactions/Transaction.java#L84-L130 -The [EIP-2718] transactions must have a transaction type that is valid on L1, or -be an *[L1 attributes transaction]* (see below). +The [EIP-2718] transactions must have a transaction type that is valid on L1, or be an *[L1 attributes transaction]* +(see below). #### Payload Transaction Format [payload-format]: #payload-transaction-format -The `transactions` array is filled with the deposits, prefixed by the (single) -[L1 attributes transaction]. The deposits are simply copied byte-for-byte — it -is the role of the [execution engine] to reject invalidly-formatted -transactions. +The `transactions` array is filled with the deposits, prefixed by the (single) [L1 attributes transaction]. The deposits +are simply copied byte-for-byte — it is the role of the [execution engine] to reject invalidly-formatted transactions. > **TODO** must offer some precisions on the format of deposits: sender, > receivers both in-tx-as-encoded, and on-L2-tx. What about the fees? -The Optimistic Ethereum specific *[L1 attributes transaction]* has the following -[EIP-2718]-compatible format: `0x7E || [block_number, timestamp, basefee]` -where: +The Optimistic Ethereum specific *[L1 attributes transaction]* has the following [EIP-2718]-compatible format: `0x7E || +[block_number, timestamp, basefee]` where: -- `0x7E` is the transaction type identifier. It is selected because transaction - type identifiers are currently allowed to go up to `0x7F`. Picking a high - identifier minimizes the risk that the identifier will be used by Ethereum in - the future. We don't pick `0x7F` itself in case it becomes used for a - variable-length encoding scheme. +- `0x7E` is the transaction type identifier. It is selected because transaction type identifiers are currently allowed + to go up to `0x7F`. Picking a high identifier minimizes the risk that the identifier will be used by Ethereum in the + future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. - `block_number` is the L1 block number as a 64-bit integer (4 bytes) - `timestamp` is the L1 block timestamp as a 64-bit integer (4 bytes) - `basefee` is the L1 block basefee as a 64-bit integer (4 bytes) -When included in the `transactions` array, this transaction should be -RLP-encoded in the same way as other transactions. +When included in the `transactions` array, this transaction should be RLP-encoded in the same way as other transactions. > **TODO** move this section into a doc specific to the execution-engine -Here is an example valid `PayloadAttributesOPV1` object, which contains an L1 -attributes transaction as well as a single deposit: +Here is an example valid `PayloadAttributesOPV1` object, which contains an L1 attributes transaction as well as a single +deposit: ```js { @@ -177,76 +159,63 @@ attributes transaction as well as a single deposit: [calling-exec-engine]: #building-the-L2-block-with-the-execution-engine -The Optimistic Ethereum [execution engine] is specified in the [Execution Engine -Specification]. +The Optimistic Ethereum [execution engine] is specified in the [Execution Engine Specification]. > **TODO LINK** execution engine spec [Execution Engine Specification]: TODO -This section defines how the rollup driver must interact with the execution -engine's in order to convert [payload attributes] into L2 blocks. +This section defines how the rollup driver must interact with the execution engine's in order to convert [payload +attributes] into L2 blocks. > **TODO** This section probably includes too much redundant details that will > need to be removed once the execution engine spec is up. -Optimistic Ethereum's execution engine API is built upon [Ethereum's Engine API -specification][eth-engine-api], with a couple of modifications. That -specification builds upon [Ethereum's JSON-RPC API specification][JSON-RPC-API], -which itself builds upon the [JSON-RPC specification][JSON-RPC]. +Optimistic Ethereum's execution engine API is built upon [Ethereum's Engine API specification][eth-engine-api], with a +couple of modifications. That specification builds upon [Ethereum's JSON-RPC API specification][JSON-RPC-API], which +itself builds upon the [JSON-RPC specification][JSON-RPC]. [eth-engine-api]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md [JSON-RPC]: https://www.jsonrpc.org/specification -In particular, the [Ethereum's Engine API specification][eth-engine-api] -specifies a [JSON-RPC] endpoint with a number of JSON-RPC routes, which are the -means through which the rollup driver interacts with the execution engine. +In particular, the [Ethereum's Engine API specification][eth-engine-api] specifies a [JSON-RPC] endpoint with a number +of JSON-RPC routes, which are the means through which the rollup driver interacts with the execution engine. -Instead of calling [`engine_forkchoiceUpdatedV1`], the rollup driver must call -the new [`engine_forkchoiceUpdatedOPV1`] route. This has the same signature, -except that: +Instead of calling [`engine_forkchoiceUpdatedV1`], the rollup driver must call the new [`engine_forkchoiceUpdatedOPV1`] +route. This has the same signature, except that: [`engine_forkchoiceUpdatedV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_forkchoiceupdatedv1 [`engine_forkchoiceUpdatedOPV1`]: TODO > **TODO LINK** forkchoiceUpdatedOPV1 from spec -- it takes a [`PayloadAttributesOPV1`] object as input instead of - [`PayloadAttributesV1`][PayloadAttributesV1]. The execution engine must - include the valid transactions supplied in this object in the block, in the - same order as they were supplied, and only those. See the [previous - section][payload-attr] for the specification of how the properties must be - set. - -- we repurpose the [`ForkchoiceStateV1`] structure with the following property - semantics: - - `headBlockHash`: block hash of the last block of the L2 chain, according to - the rollup driver. +- it takes a [`PayloadAttributesOPV1`] object as input instead of [`PayloadAttributesV1`][PayloadAttributesV1]. The + execution engine must include the valid transactions supplied in this object in the block, in the same order as they + were supplied, and only those. See the [previous section][payload-attr] for the specification of how the properties + must be set. + +- we repurpose the [`ForkchoiceStateV1`] structure with the following property semantics: + - `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. - `safeBlockHash`: same as `headBlockHash`. - - `finalizedBlockHash`: the hash of the block whose number is - `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if the number of that - block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where - `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 - blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of - the first L1 block for which an L2 block was produced). See the - [Finalization Guarantees][finalization] section for more details. + - `finalizedBlockHash`: the hash of the block whose number is `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if + the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS == 50400` + (approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the + first L1 block for which an L2 block was produced). See the [Finalization Guarantees][finalization] section for more + details. [`ForkchoiceStateV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#ForkchoiceStateV1 -> **Note:** the properties of this `ForkchoiceStateV1` can be used to anchor queries -> to the regular (non-engine-API) JSON-RPC endpoint of the execution engine. -> [See here for more information.][L2-JSON-RPC-API] +> **Note:** the properties of this `ForkchoiceStateV1` can be used to anchor queries to the regular (non-engine-API) +> JSON-RPC endpoint of the execution engine. [See here for more information.][L2-JSON-RPC-API] -> **TODO** specify the behaviour in case the resulting object reports `"SYNCING"` -> or an error +> **TODO** specify the behaviour in case the resulting object reports `"SYNCING"` or an error [L2-JSON-RPC-API]: TODO > **TODO LINK** L2 JSON RPC API (might be the same as [L1's][JSON-RPC-API]) -The `payloadID` returned by [`engine_forkchoiceUpdatedOPV1`] can then be passed -to [`engine_getPayloadV1`] in order to obtain an [`ExecutionPayloadV1`], which -fully defines a new L2 block. +The `payloadID` returned by [`engine_forkchoiceUpdatedOPV1`] can then be passed to [`engine_getPayloadV1`] in order to +obtain an [`ExecutionPayloadV1`], which fully defines a new L2 block. [`engine_getPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_getpayloadv1 [`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 @@ -257,46 +226,37 @@ fully defines a new L2 block. [l1-reorgs]: #handling-L1-re-orgs -The [previous section on L2 chain derivation][l2-chain-derivation] assumes -linear progression of the L1 chain. It is also applicable for batch processing, -meaning that any given point in time, the canonical L2 chain is given by +The [previous section on L2 chain derivation][l2-chain-derivation] assumes linear progression of the L1 chain. It is +also applicable for batch processing, meaning that any given point in time, the canonical L2 chain is given by processing the whole L1 chain since the [L2 chain inception]. -The L1 chain may occasionally re-organize, meaning the head of the L1 chain -changes to a block that is not the child of the previous head but rather one of -its "cousins" (i.e. the descendant of an ancestor of the previous head). In -those case, the rollup driver must: +The L1 chain may occasionally re-organize, meaning the head of the L1 chain changes to a block that is not the child of +the previous head but rather one of its "cousins" (i.e. the descendant of an ancestor of the previous head). In those +case, the rollup driver must: -1. Locate the *common ancestor*, a block that is an ancestor of both the - previous and new head. +1. Locate the *common ancestor*, a block that is an ancestor of both the previous and new head. 2. Isolate the range of L1 blocks `]common ancestor, ..., new head]`. -3. For each such block, call [`engine_forkchoiceUpdatedOPV1`] and - [`engine_getPayloadV1`]. +3. For each such block, call [`engine_forkchoiceUpdatedOPV1`] and [`engine_getPayloadV1`]. - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. - - Fill the [`ForkchoiceStateV1`] object according to [the section on the - execution engine][calling-exec-engine], but set `headBlockHash` to the hash - of the last processed L2 block (use the hash of the common ancestor - initially) instead of the last L2 chain head. `safeBlockHash` and - `finalizedBlockHash` must be updated accordingly. + - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but + set `headBlockHash` to the hash of the last processed L2 block (use the hash of the common ancestor initially) + instead of the last L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated accordingly. -> Note that post-[merge], the L1 chain will offer finalization guarantees -> meaning that it won't be able to re-org more than `FINALIZATION_DELAY_BLOCKS` -> in the past, hence preserving our finalization guarantees. +> Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more +> than `FINALIZATION_DELAY_BLOCKS` in the past, hence preserving our finalization guarantees. -> **TODO** Must enunciate error cases more precisely, as well as state what -> should be impossible and should cause the node to stop deriving the L2 chain. +> **TODO** Must enunciate error cases more precisely, as well as state what should be impossible and should cause the +> node to stop deriving the L2 chain. ## Finalization Guarantees [finalization]: #finalization-guarantees -As already alluded to in the section on [interacting with the execution -engine][calling-exec-engine], an L2 block is considered *finalized* after a -delay of `FINALIZATION_DELAY_BLOCKS == 50400` blocks after the L1 block that -generated it. This is a duration of approximately 7 days worth of L1 blocks. +As already alluded to in the section on [interacting with the execution engine][calling-exec-engine], an L2 block is +considered *finalized* after a delay of `FINALIZATION_DELAY_BLOCKS == 50400` blocks after the L1 block that generated +it. This is a duration of approximately 7 days worth of L1 blocks. -L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality], so -these L2 blocks can safely be considered to be final: they will never disappear -from the chain's history because of a re-org. +L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality], so these L2 blocks can safely be considered +to be final: they will never disappear from the chain's history because of a re-org. [l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge/ From 742cbafdc16f8b915230b2dfcc8237ea6df8f6f2 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 7 Dec 2021 16:20:59 +0100 Subject: [PATCH 079/585] add more linting exemptions --- .markdownlint.json | 7 +++++-- meta/linting.md | 13 +++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 meta/linting.md diff --git a/.markdownlint.json b/.markdownlint.json index 91b5460c00a0..f4e96a2481d0 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -5,5 +5,8 @@ "stern": true, "code_blocks": false, "tables": false, - } -} \ No newline at end of file + }, + "no-blanks-blockquote": false, + "single-title": false, + "no-emphasis-as-heading": false, +} diff --git a/meta/linting.md b/meta/linting.md new file mode 100644 index 000000000000..2796ea33686d --- /dev/null +++ b/meta/linting.md @@ -0,0 +1,13 @@ +# Linting + +See + +- [markdownlint rule reference](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md) +- [exemple .markdownlint.json file](https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.jsonc) + +Justification for linting rules in [.markdownlint.json](/.markdownlint.json): + +- *line_length* (`!strict && stern`): don't trip up on url lines +- *no-blanks-blockquote*: enable multiple consecutive blockquotes separated by white lines +- *single-title*: enable reusing `

` for content +- *no-emphasis-as-heading*: enable emphasized paragraphs From 9ab5a206ce54fba6b64070a1d13f5682039598e8 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 7 Dec 2021 17:22:48 +0100 Subject: [PATCH 080/585] make lint commands compatible with Windows quote expansion --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3d1da8f3b882..5269996b2270 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,7 @@ }, "scripts": { "lint": "yarn lint:fix && yarn lint:check", - "lint:fix": "markdownlint-cli2-fix '**/*.md' '#node_modules'", - "lint:check": "markdownlint-cli2 '**/*.md' '#node_modules'" + "lint:fix": "markdownlint-cli2-fix \"**/*.md\" \"#node_modules\"", + "lint:check": "markdownlint-cli2 \"**/*.md\" \"#node_modules\"" } } - From d34a9c3de35da934a4804e45a787f19080632086 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 7 Dec 2021 17:23:18 +0100 Subject: [PATCH 081/585] add yarn-error.log to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3c3629e647f5..93cab344de41 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +yarn-error.log From 1d549bf1fde5fc7dbb168c6a9190c088cfa42178 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 6 Dec 2021 21:10:58 -0500 Subject: [PATCH 082/585] First pass at Deposits spec --- deposit-transactions.md | 165 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 deposit-transactions.md diff --git a/deposit-transactions.md b/deposit-transactions.md new file mode 100644 index 000000000000..93ca2f71d402 --- /dev/null +++ b/deposit-transactions.md @@ -0,0 +1,165 @@ +# Deposit Transactions + +Although the L2 execution engine is nearly identical to that of L1, an important difference is the +introduction of a new 'Deposit' Transaction Type. Deposit transactions have the following notable +distinctions from existing transaction types: + +1. They are initiated by the System as part of the protocol. +2. Do not require signature validation. + +## Deposit Transaction Type + +We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following +fields: + +[EIP-2718]: + + +- `address to` +- `address from` +- `uint256 value` +- `bytes data` + +This transaction type contains a subset of the fields used in [EIP-155], but does not include +signature information. + +[EIP-155]: https://eips.ethereum.org/EIPS/eip-155 + +Although in practice we define only one new Transaction Type we can distinguish between two distinct +transactions which occur in the deposit block, based on their positioning. The first transaction +MUST be the [L1 Attributes Deposit Transaction][l1-attributes-deposit-transaction], followed by a +dynamic array of [Deposited Transactions][deposited-transactions] submitted to the Deposit Feed +contract by accounts on L1. + +## L1 Attributes Deposit Transaction + +[l1-attributes-deposit-transaction]: #l1-attributes-deposit-transaction + +This transaction is a call to the [Layer 1 Attributes Predeploy][l1-attributes-predeploy] contract. + +This transaction MUST have the following values: + +1. `from` is the Depositor Account `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. +1. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 attributes predeploy + contract). +1. `value` is `0` +1. `data` is an abi encoded call to the [L1 Attributes Predeploy] contract's `setL1BlockValues()` + function with correct values associated with the corresponding L1 block. + +## Special Accounts on L2 + +The L1 Attributes Deposit Transaction involves two special purpose accounts: + +1. The L1 Attributes Depositor Account +2. The L1 Attributes Predeploy + +### L1 Attributes Depositor Account + +[l1-attributes-depositor-account]: #l1-attributes-depositor-account + +The Depositor Account is an EOA with no known private key. It has the address +`0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value returned by the `CALLER` and `ORIGIN` +opcodes during execution of the L1 Attributes Deposit Transaction. + +### L1 Attributes Predeploy + +[l1-attributes-predeploy]: #l1-attributes-predeploy + +A predeployed contract on L2 at address `0x4200000000000000000000000000000000000014`, which holds +certain block variables from the corresponding L1 block in storage, so that they may be accessed +during the execution of the subsequent deposited transactions. + +The contract implements an authorization scheme, such that it only accepts state-changing calls from +the [Depositor Account]. + +The contract has the following solidity interface, and can be interacted with according to the +[contract ABI specification][ABI]. + +[ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html + +```solidity +interface L1BlockValues { + + function setL1BlockValues( + uint256 number, + uint256 timestamp, + uint256 baseFee, + bytes32 hash + ) external; + + function l1Number() view; + function l1Timestamp() view; + function l1BaseFee() view; + function l1Hash() view; +} +``` + +## Deposited Transactions + +[deposited-transactions]: #deposited-transactions + +"Deposited Transactions" are derived from logs emitted by the [Deposit Feed +contract][deposit-feed-contract] on L1. + +### Deposit Feed Contract + +[deposit-feed-contract]: #deposit-feed-contract + +The Deposit Feed contract is deployed to L1. Deposited Transactions are derived from the values in +the `TransactionDeposited` event(s) emitted by the Deposit Feed contract. + +The Deposit Feed handles two special cases: + +1. A `to` value of `0`, which results in a contract creation on L2. +2. A call from a contract account, in which case the `from` value is transformed to its L2 alias. + This prevents attacks in which a contract on L1 has the same address as a contract on L2 but + doesn't have the same code. We can safely ignore this for EOAs because they're guaranteed to have + the same "code" (i.e. no code at all). This also makes it possible for users to interact with + contracts on L2 even when the Sequencer is down. + +A solidity like pseudocode implementation demonstrates the functionality: + +```solidity +contract DepositFeed { + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 value, + bytes _data + ); + + event TransactionDeposited( + address indexed from, + uint256 value, + bytes _data + ); + + function depositTransaction( + address to, + uint256 value, + bytes memory _data + ) external { + address from; + if (msg.sender == tx.origin) { + from = msg.sender; + } else { + from = msg.sender + 0x1111000000000000000000000000000000001111; + } + + if(_to == address(0)) { + emit TransactionDeposited( + msg.sender, + value, + initCode + ); + } else { + emit TransactionDeposited( + msg.sender, + to, + value, + initCode + ); + } + } +} +``` From c50c9c292426b376af00c351d2a4ecfb711ab9fd Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 7 Dec 2021 21:26:15 -0500 Subject: [PATCH 083/585] Add ToC to glossary --- glossary.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/glossary.md b/glossary.md index a3667e2aed7d..d45794912e08 100644 --- a/glossary.md +++ b/glossary.md @@ -1,6 +1,29 @@ # Glossary ------------------------------------------------------------------------------------------------------------------------- +## Table of Contents +- [Glossary](#glossary) +- [General Terms](#general-terms) + - [Layer 1 (L1)](#layer-1-l1) + - [Layer 2 (L2)](#layer-2-l2) + - [Block](#block) + - [EOA](#eoa) + - [Merkle Root](#merkle-root) + - [Chain Re-Organization](#chain-re-organization) + - [Predeployed Contract ("Predeploy")](#predeployed-contract-predeploy) + - [Receipt](#receipt) +- [L2 Chain Concepts](#l2-chain-concepts) + - [L2 Chain Inception](#l2-chain-inception) + - [Rollup Node](#rollup-node) + - [Rollup Driver](#rollup-driver) + - [L2 Chain Derivation](#l2-chain-derivation) + - [L2 Derivation Inputs](#l2-derivation-inputs) + - [Payload Attributes](#payload-attributes) + - [L1 Attributes Transaction](#l1-attributes-transaction) + - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) + - [Deposits](#deposits) + - [Deposit Feed Contract](#deposit-feed-contract) +- [Execution Engine Concepts](#execution-engine-concepts) + - [Execution Engine](#execution-engine) # General Terms From fff9beba200e3c14431074fc33bd771987929368 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 7 Dec 2021 21:43:35 -0500 Subject: [PATCH 084/585] Add Transaction Type to glossary Also does some clean up to the intro of the deposit specs doc. --- deposit-transactions.md | 18 +++++++++++------- glossary.md | 11 +++++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/deposit-transactions.md b/deposit-transactions.md index 93ca2f71d402..9bf92ad46e75 100644 --- a/deposit-transactions.md +++ b/deposit-transactions.md @@ -1,14 +1,18 @@ -# Deposit Transactions +# Deposits -Although the L2 execution engine is nearly identical to that of L1, an important difference is the -introduction of a new 'Deposit' Transaction Type. Deposit transactions have the following notable -distinctions from existing transaction types: + +[transaction-type]: /glossary.md#transaction-type -1. They are initiated by the System as part of the protocol. -2. Do not require signature validation. +Deposits are transactions initiated on L1, and executed on L2. This document outlines a new +[Transaction Type][transaction-type] for deposits. It also describes how deposits are initiated on +L1, along with the authorization and validation conditions on L2. -## Deposit Transaction Type +## The Deposit Transaction Type +Deposit transactions have the following notable distinctions from existing transaction types: + +1. They are initiated by the system as part of the protocol. +2. They do not require signature validation. We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following fields: diff --git a/glossary.md b/glossary.md index d45794912e08..ee2c291c9752 100644 --- a/glossary.md +++ b/glossary.md @@ -101,6 +101,17 @@ transaction in the block. Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. + +## Transaction Type + +[transaction-type]: /glossary.md#transaction-type + +Ethereum provides a mechanism (as described in [EIP-2718]) for defining different transaction types. +Different transaction types can contain different payloads, and be handled differently by the protocol. + + +[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 + ------------------------------------------------------------------------------------------------------------------------ # L2 Chain Concepts From 736ea18081cff8d138572585c168ebd0075b533b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 8 Dec 2021 14:40:42 -0500 Subject: [PATCH 085/585] Move deposit transaction prefix rationale to deposit spec --- deposit-transactions.md | 3 +++ rollup-node.md | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/deposit-transactions.md b/deposit-transactions.md index 9bf92ad46e75..aab3fbf58907 100644 --- a/deposit-transactions.md +++ b/deposit-transactions.md @@ -28,6 +28,9 @@ This transaction type contains a subset of the fields used in [EIP-155], but doe signature information. [EIP-155]: https://eips.ethereum.org/EIPS/eip-155 +We select `0x7E` because transaction type identifiers are currently allowed to go up to `0x7F`. +Picking a high identifier minimizes the risk that the identifier will be used by Ethereum in the +future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. Although in practice we define only one new Transaction Type we can distinguish between two distinct transactions which occur in the deposit block, based on their positioning. The first transaction diff --git a/rollup-node.md b/rollup-node.md index b575eccb2769..935c6e642b6c 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -129,9 +129,7 @@ are simply copied byte-for-byte — it is the role of the [execution engine] to The Optimistic Ethereum specific *[L1 attributes transaction]* has the following [EIP-2718]-compatible format: `0x7E || [block_number, timestamp, basefee]` where: -- `0x7E` is the transaction type identifier. It is selected because transaction type identifiers are currently allowed - to go up to `0x7F`. Picking a high identifier minimizes the risk that the identifier will be used by Ethereum in the - future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. +- `0x7E` is the transaction type identifier. - `block_number` is the L1 block number as a 64-bit integer (4 bytes) - `timestamp` is the L1 block timestamp as a 64-bit integer (4 bytes) - `basefee` is the L1 block basefee as a 64-bit integer (4 bytes) From 2bc10913f017c0e7a915fa1720547b1218e13ac3 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 8 Dec 2021 15:30:05 -0500 Subject: [PATCH 086/585] Rename file to deposits.md --- deposit-transactions.md => deposits.md | 0 exec-engine.md | 2 +- rollup-node.md | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename deposit-transactions.md => deposits.md (100%) diff --git a/deposit-transactions.md b/deposits.md similarity index 100% rename from deposit-transactions.md rename to deposits.md diff --git a/exec-engine.md b/exec-engine.md index 3e11ba302cee..5d657d45796d 100644 --- a/exec-engine.md +++ b/exec-engine.md @@ -14,7 +14,7 @@ and introduce L1 information to enshrined contracts in the execution state. > **TODO**: implement deposit spec doc -[deposit-spec]: ./deposits#transaction-type +[deposit-spec]: ./deposits#deposit-transaction-type ### Deposit boundaries diff --git a/rollup-node.md b/rollup-node.md index 935c6e642b6c..6c54fc9581d9 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -72,7 +72,7 @@ understood as "a transaction *deposited* to L2". The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the [**deposit feed contract specification**][deposit-feed] for details on how deposits are encoded as log entries. -[deposit-feed-spec]: TODO +[deposit-feed-spec]: [/deposits.md#deposit-feed-contract] > **TODO LINK** deposit feed contract specification From ee12e9042950bc689d9bca834bffc9a4023aff59 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 8 Dec 2021 15:47:59 -0500 Subject: [PATCH 087/585] Clean up deposits file --- deposits.md | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/deposits.md b/deposits.md index aab3fbf58907..a02ce2020763 100644 --- a/deposits.md +++ b/deposits.md @@ -1,8 +1,5 @@ # Deposits - -[transaction-type]: /glossary.md#transaction-type - Deposits are transactions initiated on L1, and executed on L2. This document outlines a new [Transaction Type][transaction-type] for deposits. It also describes how deposits are initiated on L1, along with the authorization and validation conditions on L2. @@ -11,12 +8,11 @@ L1, along with the authorization and validation conditions on L2. Deposit transactions have the following notable distinctions from existing transaction types: -1. They are initiated by the system as part of the protocol. -2. They do not require signature validation. -We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following -fields: +1. They are derived from Layer 1 blocks, and must be included as part of the protocol. +2. They do not include signature validation (see [Deposited Transactions][deposited-transactions] for the rationale). -[EIP-2718]: +We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`. and the following +fields: - `address to` @@ -24,10 +20,8 @@ fields: - `uint256 value` - `bytes data` -This transaction type contains a subset of the fields used in [EIP-155], but does not include -signature information. +This is a subset of the fields used in [EIP-155], but does not include signature information. -[EIP-155]: https://eips.ethereum.org/EIPS/eip-155 We select `0x7E` because transaction type identifiers are currently allowed to go up to `0x7F`. Picking a high identifier minimizes the risk that the identifier will be used by Ethereum in the future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. @@ -38,19 +32,22 @@ MUST be the [L1 Attributes Deposit Transaction][l1-attributes-deposit-transactio dynamic array of [Deposited Transactions][deposited-transactions] submitted to the Deposit Feed contract by accounts on L1. -## L1 Attributes Deposit Transaction +> **TODO** Specify deposit block + -[l1-attributes-deposit-transaction]: #l1-attributes-deposit-transaction +## L1 Attributes Deposit -This transaction is a call to the [Layer 1 Attributes Predeploy][l1-attributes-predeploy] contract. +[l1-attributes-deposit]: #l1-attributes-deposit + +This is a deposit sent to the [Layer 1 Attributes Predeploy][l1-attributes-predeploy] contract. This transaction MUST have the following values: -1. `from` is the Depositor Account `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. -1. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 attributes predeploy +1. `from` is the L1 Attributes Depositor Account `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. +2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 Attributes Predeploy contract). -1. `value` is `0` -1. `data` is an abi encoded call to the [L1 Attributes Predeploy] contract's `setL1BlockValues()` +3. `value` is `0` +4. `data` is an abi encoded call to the [L1 Attributes Predeploy] contract's `setL1BlockValues()` function with correct values associated with the corresponding L1 block. ## Special Accounts on L2 @@ -82,7 +79,6 @@ the [Depositor Account]. The contract has the following solidity interface, and can be interacted with according to the [contract ABI specification][ABI]. -[ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html ```solidity interface L1BlockValues { @@ -101,9 +97,8 @@ interface L1BlockValues { } ``` -## Deposited Transactions - -[deposited-transactions]: #deposited-transactions +## L1 Transaction Deposits +[l1-transaction-deposits]: #l1-transaction-deposits "Deposited Transactions" are derived from logs emitted by the [Deposit Feed contract][deposit-feed-contract] on L1. @@ -117,7 +112,7 @@ the `TransactionDeposited` event(s) emitted by the Deposit Feed contract. The Deposit Feed handles two special cases: -1. A `to` value of `0`, which results in a contract creation on L2. +1. A `to` value of `bytes20(0)`, which results in a contract creation on L2. 2. A call from a contract account, in which case the `from` value is transformed to its L2 alias. This prevents attacks in which a contract on L1 has the same address as a contract on L2 but doesn't have the same code. We can safely ignore this for EOAs because they're guaranteed to have @@ -170,3 +165,12 @@ contract DepositFeed { } } ``` + + + +[transaction-type]: /glossary.md#transaction-type + + +[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 +[ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html + From 1d92df757caefd4aff4357807cd290319bc0f4c0 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 8 Dec 2021 16:14:17 -0500 Subject: [PATCH 088/585] Add isCreation flag This change also enables sending an L1-L2 transaction to address(0) --- deposits.md | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/deposits.md b/deposits.md index a02ce2020763..6915fe294626 100644 --- a/deposits.md +++ b/deposits.md @@ -103,6 +103,25 @@ interface L1BlockValues { "Deposited Transactions" are derived from logs emitted by the [Deposit Feed contract][deposit-feed-contract] on L1. +When an L1 Transaction Deposit is executed the nonce is incremented. In the context of a deposit + only roll up, this is not required for transaction ordering or replay prevention, however it + maintains consistency with the use of nonces during contract creation. It may also be simplify + integration with downstream tooling (such as wallets and block explorers). + +Rather, authorization is outsourced to the [L1 Deposit Feed contract][deposit-feed-contract], and the [Block Derivation][/glossary.md#L2-chain-derivation] process. + + +- increment nonce +- signature validation is handled by L1 +- a state transition requiring a transaction not +- mints ETH on L2 +- validity: + - inclusion of an un + + + + + ### Deposit Feed Contract [deposit-feed-contract]: #deposit-feed-contract @@ -112,7 +131,8 @@ the `TransactionDeposited` event(s) emitted by the Deposit Feed contract. The Deposit Feed handles two special cases: -1. A `to` value of `bytes20(0)`, which results in a contract creation on L2. +1. A contract creation deposit, which is indicated by setting the `isCreation` flag to `true`. + In the event that the `to` address is non-zero, the contract will revert. 2. A call from a contract account, in which case the `from` value is transformed to its L2 alias. This prevents attacks in which a contract on L1 has the same address as a contract on L2 but doesn't have the same code. We can safely ignore this for EOAs because they're guaranteed to have @@ -123,16 +143,12 @@ A solidity like pseudocode implementation demonstrates the functionality: ```solidity contract DepositFeed { - event TransactionDeposited( - address indexed from, - address indexed to, - uint256 value, - bytes _data - ); event TransactionDeposited( address indexed from, + address indexed to, uint256 value, + bool isCreation, bytes _data ); @@ -148,17 +164,14 @@ contract DepositFeed { from = msg.sender + 0x1111000000000000000000000000000000001111; } - if(_to == address(0)) { - emit TransactionDeposited( - msg.sender, - value, - initCode - ); + if(isCreation && _to != address(0)) { + revert('Contract creation deposits must not specify a recipient address.'); } else { emit TransactionDeposited( msg.sender, to, value, + isCreation, initCode ); } From 85f5b7b1e211ad5ae324962ed54c3800e7553080 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 9 Dec 2021 03:08:35 +0100 Subject: [PATCH 089/585] change Ethereum JSON-RPC API link --- rollup-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollup-node.md b/rollup-node.md index b575eccb2769..ccc9e8625385 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -94,7 +94,7 @@ The type notation used here refers to the [HEX value encoding] used by the [Ethe specification][JSON-RPC-API], as this structure will need to be sent over JSON-RPC. `array` refers to a JSON array. [HEX value encoding]: https://eth.wiki/json-rpc/API#hex-value-encoding -[JSON-RPC-API]: https://eth.wiki/json-rpc/API +[JSON-RPC-API]: https://github.com/ethereum/execution-apis The object properties must be set as follows: From 11e992dc55ac74eb109dce3b70bc00561fbe4d93 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 9 Dec 2021 03:12:31 +0100 Subject: [PATCH 090/585] add specification links + fix typos --- glossary.md | 8 ++------ rollup-node.md | 9 +++------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/glossary.md b/glossary.md index a3667e2aed7d..a149f6bb2b7c 100644 --- a/glossary.md +++ b/glossary.md @@ -137,9 +137,7 @@ passed to the [execution engine] to construct L2 blocks. "Payload attributes" is a term that originates and is specified in the [Ethereum Engine API specification][engine-api], which we extend in this specification. -cf. [Execution Engine Specification](TODO) - -> **TODO LINK** execution engine specification +cf. [Execution Engine Specification](exec-engine.md) Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using this term. @@ -196,9 +194,7 @@ Advanced note: the deposits are not stored in calldata because they can be send is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 block. -cf. [Deposit Feed Contract Specification](TODO) - -> **TODO LINK** deposit feed contract specification +cf. [Deposits Specification](deposits.md) ------------------------------------------------------------------------------------------------------------------------ diff --git a/rollup-node.md b/rollup-node.md index ccc9e8625385..a2c4c8a9af78 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -63,8 +63,7 @@ The rollup reads the following data from each L1 block: [random]: https://eips.ethereum.org/EIPS/eip-4399 -A deposit is an L2 transaction that has been submitted on L1, via a call sent to the [deposit feed -contract][deposit-feed]. +A deposit is an L2 transaction that has been submitted on L1, via a call to the [deposit feed contract][deposit-feed]. While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be understood as "a transaction *deposited* to L2". @@ -72,11 +71,9 @@ understood as "a transaction *deposited* to L2". The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the [**deposit feed contract specification**][deposit-feed] for details on how deposits are encoded as log entries. -[deposit-feed-spec]: TODO +[deposit-feed-spec]: deposits.md -> **TODO LINK** deposit feed contract specification - -From the data read from , the rollup node constructs an expanded version of the [Engine API PayloadAttributesV1 +From the data read from L1, the rollup node constructs an expanded version of the [Engine API PayloadAttributesV1 object][PayloadAttributesV1]: [PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 From 01862f22d785cf23000acaf7616ede4a5b6d8a72 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 9 Dec 2021 03:56:15 +0100 Subject: [PATCH 091/585] link execution-engine spec, specify how sync can help in case of re-orgs, indicate errors are not supposed to happen --- rollup-node.md | 64 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/rollup-node.md b/rollup-node.md index a2c4c8a9af78..0e7296a61394 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -74,7 +74,7 @@ The L1 attributes are read from the L1 block header, while deposits are read fro [deposit-feed-spec]: deposits.md From the data read from L1, the rollup node constructs an expanded version of the [Engine API PayloadAttributesV1 -object][PayloadAttributesV1]: +object][PayloadAttributesV1], which includes an additional `transactions` field: [PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 @@ -158,9 +158,7 @@ deposit: The Optimistic Ethereum [execution engine] is specified in the [Execution Engine Specification]. -> **TODO LINK** execution engine spec - -[Execution Engine Specification]: TODO +[Execution Engine Specification]: exec-engine.md This section defines how the rollup driver must interact with the execution engine's in order to convert [payload attributes] into L2 blocks. @@ -182,9 +180,7 @@ Instead of calling [`engine_forkchoiceUpdatedV1`], the rollup driver must call t route. This has the same signature, except that: [`engine_forkchoiceUpdatedV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_forkchoiceupdatedv1 -[`engine_forkchoiceUpdatedOPV1`]: TODO - -> **TODO LINK** forkchoiceUpdatedOPV1 from spec +[`engine_forkchoiceUpdatedOPV1`]: exec-engine.md#engine_forkchoiceupdatedv1 - it takes a [`PayloadAttributesOPV1`] object as input instead of [`PayloadAttributesV1`][PayloadAttributesV1]. The execution engine must include the valid transactions supplied in this object in the block, in the same order as they @@ -205,8 +201,6 @@ route. This has the same signature, except that: > **Note:** the properties of this `ForkchoiceStateV1` can be used to anchor queries to the regular (non-engine-API) > JSON-RPC endpoint of the execution engine. [See here for more information.][L2-JSON-RPC-API] -> **TODO** specify the behaviour in case the resulting object reports `"SYNCING"` or an error - [L2-JSON-RPC-API]: TODO > **TODO LINK** L2 JSON RPC API (might be the same as [L1's][JSON-RPC-API]) @@ -214,10 +208,24 @@ route. This has the same signature, except that: The `payloadID` returned by [`engine_forkchoiceUpdatedOPV1`] can then be passed to [`engine_getPayloadV1`] in order to obtain an [`ExecutionPayloadV1`], which fully defines a new L2 block. -[`engine_getPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_getpayloadv1 -[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 +The rollup driver must then instruct the execution engine to execute the block by calling [`engine_executePayloadV1`]. +This returns the new L2 block hash. + +All invocations of [`engine_forkchoiceUpdatedOPV1`], [`engine_getPayloadV1`] and [`engine_executePayloadV1`] by the +rollup driver should not result in errors assuming conformity with the specification. Said otherwise, all errors are +implementation concerns and it is up to them to handle them (e.g. by retrying, or by stopping the chain derivation and +requiring manual user intervention). -> **TODO** specify the behaviour in case the resulting object reports an error +The following scenarios are assimilated to errors: + +- [`engine_forkchoiceUpdateOPV1`] returning a `status` of "`SYNCING`" instead of "`SUCCESS`" whenever passed a + `headBlockHash` that it retrieved from a previous call to [`engine_executePayloadV1`]. +- [`engine_executePayloadV1`] returning a `status` of "`SYNCING`" or `"INVALID"` whenever passed an execution payload + that was obtained by a previous call to [`engine_getPayloadV1`]. + +[`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 +[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 +[`engine_executePayloadV1`]: exec-engine.md#engine_executepayloadv1 ## Handling L1 Re-Orgs @@ -227,23 +235,35 @@ The [previous section on L2 chain derivation][l2-chain-derivation] assumes linea also applicable for batch processing, meaning that any given point in time, the canonical L2 chain is given by processing the whole L1 chain since the [L2 chain inception]. -The L1 chain may occasionally re-organize, meaning the head of the L1 chain changes to a block that is not the child of -the previous head but rather one of its "cousins" (i.e. the descendant of an ancestor of the previous head). In those -case, the rollup driver must: - -1. Locate the *common ancestor*, a block that is an ancestor of both the previous and new head. -2. Isolate the range of L1 blocks `]common ancestor, ..., new head]`. -3. For each such block, call [`engine_forkchoiceUpdatedOPV1`] and [`engine_getPayloadV1`]. +> By itself, the previous section fully specifies the behaviour of the rollup driver. **The current section is +> non-specificative** but shows how L1 re-orgs can be handled in practice. + +In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally re-organize, meaning the +head of the L1 chain changes to a block that is not the child of the previous head but rather one of its "cousins" (i.e. +the descendant of an ancestor of the previous head). In those case, the rollup driver must: + +1. Call [`engine_forkchoiceUpdatedOPV1`] for the new L2 chain head + - Pass `null` for the `payloadAttributes` parameter. + - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but + set `headBlockHash` to the hash of the new L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated + accordingly. +2. If the call returns `"SUCCESS"`, we are done: the execution engine retrieved all the new L2 blocks via [block sync]. +3. Otherwise the call returns `"SYNCING"`, and we must derive the new blocks ourselves. Start by locating the *common + ancestor*, a block that is an ancestor of both the previous and new head. +4. Isolate the range of L1 blocks `]common ancestor, ..., new head]`. +5. For each such block, call [`engine_forkchoiceUpdatedOPV1`], [`engine_getPayloadV1`], and [`engine_executePayloadV1`]. - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but set `headBlockHash` to the hash of the last processed L2 block (use the hash of the common ancestor initially) instead of the last L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated accordingly. +[block sync]: https://github.com/ethereum-optimism/optimistic-specs/blob/main/exec-engine.md#sync + > Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more -> than `FINALIZATION_DELAY_BLOCKS` in the past, hence preserving our finalization guarantees. +> than `FINALIZATION_DELAY_BLOCKS == 50400` in the past, hence preserving our finalization guarantees. -> **TODO** Must enunciate error cases more precisely, as well as state what should be impossible and should cause the -> node to stop deriving the L2 chain. +Just like before, the meaning of errors returned by RPC calls is unspecified and must be handled at the implementer's +discretion, while remaining compatible with the specification. ## Finalization Guarantees From 78536943b448266292bfd448c0edc7aa896ba962 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 8 Dec 2021 15:48:34 -0500 Subject: [PATCH 092/585] Specify authorization and validation for deposit transactions --- deposits.md | 52 +++++++++++++++++++++++++++++++------------------- exec-engine.md | 4 +--- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/deposits.md b/deposits.md index 6915fe294626..f55518988215 100644 --- a/deposits.md +++ b/deposits.md @@ -6,6 +6,8 @@ L1, along with the authorization and validation conditions on L2. ## The Deposit Transaction Type +[deposit-transaction-type]: #deposit-transaction-type + Deposit transactions have the following notable distinctions from existing transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. @@ -32,7 +34,23 @@ MUST be the [L1 Attributes Deposit Transaction][l1-attributes-deposit-transactio dynamic array of [Deposited Transactions][deposited-transactions] submitted to the Deposit Feed contract by accounts on L1. -> **TODO** Specify deposit block +> **TODO** Specify and link to deposit blocks + +### Validation and Authorization of Deposit Transaction Types + +[authorization]: #authorization + +As noted above, the Deposit Transaction Type does not include a signature for validation. Rather, +authorization is handled by the [L1 Deposit Feed contract][deposit-feed-contract] and the +[Block Derivation][/glossary.md#L2-chain-derivation] process itself. + +### Nonce handling + +Despite the lack of signature validation, we still increment the nonce of the `from` account when an +Deposit Transaction is executed. In the context of a deposit-only roll up, this is not necessary +for transaction ordering or replay prevention, however it maintains consistency with the use of +nonces during contract creation. It may also simplify integration with downstream tooling (such +as wallets and block explorers). ## L1 Attributes Deposit @@ -98,29 +116,20 @@ interface L1BlockValues { ``` ## L1 Transaction Deposits + [l1-transaction-deposits]: #l1-transaction-deposits -"Deposited Transactions" are derived from logs emitted by the [Deposit Feed +L1 Transaction Deposits are [Deposit Transactions][deposit-transaction-type] generated by the +[L2 Chain Derivation][derivation] process. The values of each transaction are determined by the +corresponding `TransactionDeposited` event emitted by the [Deposit Feed contract][deposit-feed-contract] on L1. -When an L1 Transaction Deposit is executed the nonce is incremented. In the context of a deposit - only roll up, this is not required for transaction ordering or replay prevention, however it - maintains consistency with the use of nonces during contract creation. It may also be simplify - integration with downstream tooling (such as wallets and block explorers). - -Rather, authorization is outsourced to the [L1 Deposit Feed contract][deposit-feed-contract], and the [Block Derivation][/glossary.md#L2-chain-derivation] process. - - -- increment nonce -- signature validation is handled by L1 -- a state transition requiring a transaction not -- mints ETH on L2 -- validity: - - inclusion of an un - - - - +1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in the Deposit Feed contract). +2. `to` may be either: + 1. any 20-byte address (including the zero-address) + 2. `null` in which case a contract is created. +3. `value` is unchanged from the emitted value. +4. `data` is unchanged from the emitted value, and is handled as either calldata or initialization code depending on the value of `to`. ### Deposit Feed Contract @@ -139,6 +148,8 @@ The Deposit Feed handles two special cases: the same "code" (i.e. no code at all). This also makes it possible for users to interact with contracts on L2 even when the Sequencer is down. +> **TODO** Define if/how ETH withdrawals occur. + A solidity like pseudocode implementation demonstrates the functionality: ```solidity @@ -182,6 +193,7 @@ contract DepositFeed { [transaction-type]: /glossary.md#transaction-type +[derivation]: /glossary.md#L2-chain-derivation [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 diff --git a/exec-engine.md b/exec-engine.md index 5d657d45796d..f3259c2e2e9e 100644 --- a/exec-engine.md +++ b/exec-engine.md @@ -12,8 +12,6 @@ is implemented by the engine, see the [deposit specification][deposit-spec]. This type of transaction can mint L2 ETH, run EVM, and introduce L1 information to enshrined contracts in the execution state. -> **TODO**: implement deposit spec doc - [deposit-spec]: ./deposits#deposit-transaction-type ### Deposit boundaries @@ -61,7 +59,7 @@ This `transactions` field is an optional JSON field: Utilized by sequencers (if enabled) to consume the transaction pool. - If present and non-empty: the payload MUST only be produced with this exact list of transactions. Utilized by [rollup driver][rollup-driver] to compute full block payloads based on deterministic inputs. - + > **TODO**: derivation function spec in rollup node doc or separate driver doc [rollup-driver]: ./rollup-driver.md From a3a0efd55394df1b6566cf502c32a036141ab9ff Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 8 Dec 2021 16:21:49 -0500 Subject: [PATCH 093/585] Add payable to deposit contract --- deposits.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deposits.md b/deposits.md index f55518988215..0fd0fd78a74e 100644 --- a/deposits.md +++ b/deposits.md @@ -166,8 +166,9 @@ contract DepositFeed { function depositTransaction( address to, uint256 value, + bool isCreation, bytes memory _data - ) external { + ) external payable { address from; if (msg.sender == tx.origin) { from = msg.sender; @@ -181,7 +182,7 @@ contract DepositFeed { emit TransactionDeposited( msg.sender, to, - value, + msg.value, isCreation, initCode ); From c62704754354c855a903abe559250303835b6edd Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 9 Dec 2021 06:25:48 -0500 Subject: [PATCH 094/585] Add gasLimit --- deposits.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deposits.md b/deposits.md index 0fd0fd78a74e..4defec294bff 100644 --- a/deposits.md +++ b/deposits.md @@ -21,6 +21,7 @@ fields: - `address from` - `uint256 value` - `bytes data` +- `uint256 gasLimit` This is a subset of the fields used in [EIP-155], but does not include signature information. @@ -66,6 +67,7 @@ This transaction MUST have the following values: contract). 3. `value` is `0` 4. `data` is an abi encoded call to the [L1 Attributes Predeploy] contract's `setL1BlockValues()` +4. `gasLimit` is set to the maximum available. function with correct values associated with the corresponding L1 block. ## Special Accounts on L2 @@ -130,6 +132,7 @@ contract][deposit-feed-contract] on L1. 2. `null` in which case a contract is created. 3. `value` is unchanged from the emitted value. 4. `data` is unchanged from the emitted value, and is handled as either calldata or initialization code depending on the value of `to`. +4. `gaslimit` is unchanged from the emitted value. ### Deposit Feed Contract @@ -159,6 +162,7 @@ contract DepositFeed { address indexed from, address indexed to, uint256 value, + uint256 gasLimit, bool isCreation, bytes _data ); @@ -166,6 +170,7 @@ contract DepositFeed { function depositTransaction( address to, uint256 value, + uint256 gasLimit, bool isCreation, bytes memory _data ) external payable { From e0307caca65b71458a73d5e9d973e0060140fb2d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 9 Dec 2021 06:26:44 -0500 Subject: [PATCH 095/585] Specify EE initialization --- deposits.md | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/deposits.md b/deposits.md index 4defec294bff..d32a479d32cb 100644 --- a/deposits.md +++ b/deposits.md @@ -16,7 +16,6 @@ Deposit transactions have the following notable distinctions from existing trans We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`. and the following fields: - - `address to` - `address from` - `uint256 value` @@ -45,7 +44,24 @@ As noted above, the Deposit Transaction Type does not include a signature for va authorization is handled by the [L1 Deposit Feed contract][deposit-feed-contract] and the [Block Derivation][/glossary.md#L2-chain-derivation] process itself. -### Nonce handling +### Execution + +First, the balance of the `from` account MUST be increased by the amount of `value`. + +Then, the execution environment for a deposit transaction is initialized based on the transactions +values, in exactly the same manner as it would be for an EIP-155 transaction. + + + +Specifically, a new EVM call frame targeting the `to` address is created with values initialized as +follows: + +- `CALLER` and `ORIGIN` set to `from` +- `context.calldata` set to `data` +- `context.gas` set to `gasLimit` +- `context.value` set to `value` + +#### Nonce handling Despite the lack of signature validation, we still increment the nonce of the `from` account when an Deposit Transaction is executed. In the context of a deposit-only roll up, this is not necessary @@ -53,7 +69,6 @@ for transaction ordering or replay prevention, however it maintains consistency nonces during contract creation. It may also simplify integration with downstream tooling (such as wallets and block explorers). - ## L1 Attributes Deposit [l1-attributes-deposit]: #l1-attributes-deposit @@ -66,8 +81,8 @@ This transaction MUST have the following values: 2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 Attributes Predeploy contract). 3. `value` is `0` -4. `data` is an abi encoded call to the [L1 Attributes Predeploy] contract's `setL1BlockValues()` 4. `gasLimit` is set to the maximum available. +5. `data` is an abi encoded call to the [L1 Attributes Predeploy] contract's `setL1BlockValues()` function with correct values associated with the corresponding L1 block. ## Special Accounts on L2 @@ -131,8 +146,8 @@ contract][deposit-feed-contract] on L1. 1. any 20-byte address (including the zero-address) 2. `null` in which case a contract is created. 3. `value` is unchanged from the emitted value. -4. `data` is unchanged from the emitted value, and is handled as either calldata or initialization code depending on the value of `to`. 4. `gaslimit` is unchanged from the emitted value. +5. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as either calldata or initialization code depending on the value of `to`. ### Deposit Feed Contract @@ -145,11 +160,12 @@ The Deposit Feed handles two special cases: 1. A contract creation deposit, which is indicated by setting the `isCreation` flag to `true`. In the event that the `to` address is non-zero, the contract will revert. -2. A call from a contract account, in which case the `from` value is transformed to its L2 alias. - This prevents attacks in which a contract on L1 has the same address as a contract on L2 but - doesn't have the same code. We can safely ignore this for EOAs because they're guaranteed to have - the same "code" (i.e. no code at all). This also makes it possible for users to interact with - contracts on L2 even when the Sequencer is down. +2. A call from a contract account, in which case the `from` value is transformed to its L2 alias (by + adding `0x1111000000000000000000000000000000001111`). This prevents attacks in which a contract + on L1 has the same address as a contract on L2 but doesn't have the same code. We can safely + ignore this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). + This also makes it possible for users to interact with contracts on L2 even when the Sequencer is + down. > **TODO** Define if/how ETH withdrawals occur. From e124d332f39a36d5a36050bc65a004f05fdf8c2c Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 9 Dec 2021 06:55:47 -0500 Subject: [PATCH 096/585] Clean up deposits file --- deposits.md | 42 ++++++++++++++++++++++-------------------- glossary.md | 3 +-- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/deposits.md b/deposits.md index d32a479d32cb..ff5e5a92c7f2 100644 --- a/deposits.md +++ b/deposits.md @@ -1,6 +1,6 @@ # Deposits -Deposits are transactions initiated on L1, and executed on L2. This document outlines a new +Deposits are transactions which are initiated on L1, and executed on L2. This document outlines a new [Transaction Type][transaction-type] for deposits. It also describes how deposits are initiated on L1, along with the authorization and validation conditions on L2. @@ -11,9 +11,9 @@ L1, along with the authorization and validation conditions on L2. Deposit transactions have the following notable distinctions from existing transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. -2. They do not include signature validation (see [Deposited Transactions][deposited-transactions] for the rationale). +2. They do not include signature validation (see [L1 Transaction deposits][#l1-transaction-deposits] for the rationale). -We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`. and the following +We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following fields: - `address to` @@ -30,9 +30,9 @@ future. We don't pick `0x7F` itself in case it becomes used for a variable-lengt Although in practice we define only one new Transaction Type we can distinguish between two distinct transactions which occur in the deposit block, based on their positioning. The first transaction -MUST be the [L1 Attributes Deposit Transaction][l1-attributes-deposit-transaction], followed by a -dynamic array of [Deposited Transactions][deposited-transactions] submitted to the Deposit Feed -contract by accounts on L1. +MUST be a [L1 attributes deposit][l1-attributes-deposit], followed by a an array of zero-or-more +[L1 transaction deposits][l1-transaction-deposits] submitted to the Deposit Feed contract by +accounts on L1. > **TODO** Specify and link to deposit blocks @@ -42,17 +42,20 @@ contract by accounts on L1. As noted above, the Deposit Transaction Type does not include a signature for validation. Rather, authorization is handled by the [L1 Deposit Feed contract][deposit-feed-contract] and the -[Block Derivation][/glossary.md#L2-chain-derivation] process itself. +[L2 chain Derivation][derivation] process itself. + +If a Deposit Transaction is included which is not derived using the correct derivation algorithm, +the resulting state transition would be invalid. ### Execution +In order to execute a deposit transaction: + First, the balance of the `from` account MUST be increased by the amount of `value`. -Then, the execution environment for a deposit transaction is initialized based on the transactions +Then, the execution environment for a deposit transaction is initialized based on the transaction's values, in exactly the same manner as it would be for an EIP-155 transaction. - - Specifically, a new EVM call frame targeting the `to` address is created with values initialized as follows: @@ -63,7 +66,7 @@ follows: #### Nonce handling -Despite the lack of signature validation, we still increment the nonce of the `from` account when an +Despite the lack of signature validation, we still increment the nonce of the `from` account when a Deposit Transaction is executed. In the context of a deposit-only roll up, this is not necessary for transaction ordering or replay prevention, however it maintains consistency with the use of nonces during contract creation. It may also simplify integration with downstream tooling (such @@ -97,7 +100,7 @@ The L1 Attributes Deposit Transaction involves two special purpose accounts: [l1-attributes-depositor-account]: #l1-attributes-depositor-account The Depositor Account is an EOA with no known private key. It has the address -`0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value returned by the `CALLER` and `ORIGIN` +`0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value is returned by the `CALLER` and `ORIGIN` opcodes during execution of the L1 Attributes Deposit Transaction. ### L1 Attributes Predeploy @@ -114,7 +117,6 @@ the [Depositor Account]. The contract has the following solidity interface, and can be interacted with according to the [contract ABI specification][ABI]. - ```solidity interface L1BlockValues { @@ -141,13 +143,15 @@ L1 Transaction Deposits are [Deposit Transactions][deposit-transaction-type] gen corresponding `TransactionDeposited` event emitted by the [Deposit Feed contract][deposit-feed-contract] on L1. -1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in the Deposit Feed contract). +1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in + the Deposit Feed contract). 2. `to` may be either: - 1. any 20-byte address (including the zero-address) - 2. `null` in which case a contract is created. + 1. any 20-byte address (including the zero-address) + 2. `null` in which case a contract is created. 3. `value` is unchanged from the emitted value. 4. `gaslimit` is unchanged from the emitted value. -5. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as either calldata or initialization code depending on the value of `to`. +5. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as + either calldata or initialization code depending on the value of `to`. ### Deposit Feed Contract @@ -169,7 +173,7 @@ The Deposit Feed handles two special cases: > **TODO** Define if/how ETH withdrawals occur. -A solidity like pseudocode implementation demonstrates the functionality: +A solidity-like pseudocode implementation demonstrates the functionality: ```solidity contract DepositFeed { @@ -212,7 +216,6 @@ contract DepositFeed { } ``` - [transaction-type]: /glossary.md#transaction-type [derivation]: /glossary.md#L2-chain-derivation @@ -220,4 +223,3 @@ contract DepositFeed { [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 [ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html - diff --git a/glossary.md b/glossary.md index ee2c291c9752..9c28e4263426 100644 --- a/glossary.md +++ b/glossary.md @@ -1,6 +1,7 @@ # Glossary ## Table of Contents + - [Glossary](#glossary) - [General Terms](#general-terms) - [Layer 1 (L1)](#layer-1-l1) @@ -101,7 +102,6 @@ transaction in the block. Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. - ## Transaction Type [transaction-type]: /glossary.md#transaction-type @@ -109,7 +109,6 @@ Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. Ethereum provides a mechanism (as described in [EIP-2718]) for defining different transaction types. Different transaction types can contain different payloads, and be handled differently by the protocol. - [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 ------------------------------------------------------------------------------------------------------------------------ From 6cbe3d02b765eaef4e3e1e130fcda9ad662342b2 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 9 Dec 2021 16:08:02 -0500 Subject: [PATCH 097/585] Polish with review feedback --- deposits.md | 116 ++++++++++++++++++++++++++++++---------------------- glossary.md | 24 ++++++++++- 2 files changed, 88 insertions(+), 52 deletions(-) diff --git a/deposits.md b/deposits.md index ff5e5a92c7f2..79cfb29c47f1 100644 --- a/deposits.md +++ b/deposits.md @@ -1,51 +1,63 @@ # Deposits + +[transaction-type]: /glossary.md#transaction-type +[derivation]: /glossary.md#L2-chain-derivation +[execution-engine]: /glossary.md#execution-engine + Deposits are transactions which are initiated on L1, and executed on L2. This document outlines a new -[Transaction Type][transaction-type] for deposits. It also describes how deposits are initiated on +[transaction type][transaction-type] for deposits. It also describes how deposits are initiated on L1, along with the authorization and validation conditions on L2. ## The Deposit Transaction Type -[deposit-transaction-type]: #deposit-transaction-type +[deposit-transaction-type]: #the-deposit-transaction-type Deposit transactions have the following notable distinctions from existing transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. -2. They do not include signature validation (see [L1 Transaction deposits][#l1-transaction-deposits] for the rationale). +2. They do not include signature validation (see [L1 transaction deposits][l1-transaction-deposits] for the rationale). We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following -fields: +fields (rlp encoded in the order they appear here): + +[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -- `address to` - `address from` +- `address to` - `uint256 value` - `bytes data` - `uint256 gasLimit` -This is a subset of the fields used in [EIP-155], but does not include signature information. +In contrast to [EIP-155] transactions, this transaction type does not include signature information, +and makes the `from` address explicit. + +[EIP-155]:https://eips.ethereum.org/EIPS/eip-155 We select `0x7E` because transaction type identifiers are currently allowed to go up to `0x7F`. -Picking a high identifier minimizes the risk that the identifier will be used by Ethereum in the -future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. +Picking a high identifier minimizes the risk that the identifier will be used be claimed by another +transaction type on the L1 chain in the future. We don't pick `0x7F` itself in case it becomes used +for a variable-length encoding scheme. -Although in practice we define only one new Transaction Type we can distinguish between two distinct +Although in practice we define only one new transaction type we can distinguish between two distinct transactions which occur in the deposit block, based on their positioning. The first transaction MUST be a [L1 attributes deposit][l1-attributes-deposit], followed by a an array of zero-or-more -[L1 transaction deposits][l1-transaction-deposits] submitted to the Deposit Feed contract by +[L1 transaction deposits][l1-transaction-deposits] submitted to the deposit feed contract by accounts on L1. > **TODO** Specify and link to deposit blocks ### Validation and Authorization of Deposit Transaction Types -[authorization]: #authorization +[authorization]: #validation-and-authorization-of-deposit-transaction-types -As noted above, the Deposit Transaction Type does not include a signature for validation. Rather, -authorization is handled by the [L1 Deposit Feed contract][deposit-feed-contract] and the -[L2 chain Derivation][derivation] process itself. +As noted above, the deposit transaction type does not include a signature for validation. Rather, +authorization is handled by the [L2 chain Derivation][derivation] process, which when +correctly processed will only derive transactions with a `from` address attested to +by the logs of the [L1 deposit feed contract][deposit-feed-contract]. -If a Deposit Transaction is included which is not derived using the correct derivation algorithm, -the resulting state transition would be invalid. +In the event a deposit transaction is included which is not derived by the [execution engine][execution-engine] +using the correct derivation algorithm, the resulting state transition would be invalid. ### Execution @@ -60,6 +72,8 @@ Specifically, a new EVM call frame targeting the `to` address is created with va follows: - `CALLER` and `ORIGIN` set to `from` + - `from` is unchanged from the deposit feed contract's logs (though the address may have been + [aliased][address-aliasing] by the deposit feed contract). - `context.calldata` set to `data` - `context.gas` set to `gasLimit` - `context.value` set to `value` @@ -67,56 +81,61 @@ follows: #### Nonce handling Despite the lack of signature validation, we still increment the nonce of the `from` account when a -Deposit Transaction is executed. In the context of a deposit-only roll up, this is not necessary +deposit transaction is executed. In the context of a deposit-only roll up, this is not necessary for transaction ordering or replay prevention, however it maintains consistency with the use of -nonces during contract creation. It may also simplify integration with downstream tooling (such -as wallets and block explorers). +nonces during [contract creation][create-nonce]. It may also simplify integration with downstream +tooling (such as wallets and block explorers). + +[create-nonce]: https://github.com/ethereum/execution-specs/blob/617903a8f8d7b50cf71bf1aa733c37897c8d75c1/src/ethereum/frontier/utils/address.py#L40 ## L1 Attributes Deposit [l1-attributes-deposit]: #l1-attributes-deposit -This is a deposit sent to the [Layer 1 Attributes Predeploy][l1-attributes-predeploy] contract. +This is a deposit transaction sent to the [L1 attributes predeploy][predeploy] contract. This transaction MUST have the following values: -1. `from` is the L1 Attributes Depositor Account `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. -2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 Attributes Predeploy +1. `from` is `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001` (the address of the +[L1 Attributes depositor account][depositor-account]) +2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 attributes predeploy contract). 3. `value` is `0` 4. `gasLimit` is set to the maximum available. -5. `data` is an abi encoded call to the [L1 Attributes Predeploy] contract's `setL1BlockValues()` +5. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's `setL1BlockValues()` function with correct values associated with the corresponding L1 block. ## Special Accounts on L2 -The L1 Attributes Deposit Transaction involves two special purpose accounts: +The L1 attributes deposit transaction involves two special purpose accounts: -1. The L1 Attributes Depositor Account -2. The L1 Attributes Predeploy +1. The L1 attributes depositor account +2. The L1 attributes predeploy ### L1 Attributes Depositor Account -[l1-attributes-depositor-account]: #l1-attributes-depositor-account +[depositor-account]: #l1-attributes-depositor-account -The Depositor Account is an EOA with no known private key. It has the address +The depositor account is an EOA with no known private key. It has the address `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value is returned by the `CALLER` and `ORIGIN` -opcodes during execution of the L1 Attributes Deposit Transaction. +opcodes during execution of the L1 attributes deposit transaction. ### L1 Attributes Predeploy -[l1-attributes-predeploy]: #l1-attributes-predeploy +[predeploy]: #l1-attributes-predeploy A predeployed contract on L2 at address `0x4200000000000000000000000000000000000014`, which holds certain block variables from the corresponding L1 block in storage, so that they may be accessed during the execution of the subsequent deposited transactions. The contract implements an authorization scheme, such that it only accepts state-changing calls from -the [Depositor Account]. +the [depositor account]. The contract has the following solidity interface, and can be interacted with according to the [contract ABI specification][ABI]. +[ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html + ```solidity interface L1BlockValues { @@ -138,13 +157,13 @@ interface L1BlockValues { [l1-transaction-deposits]: #l1-transaction-deposits -L1 Transaction Deposits are [Deposit Transactions][deposit-transaction-type] generated by the +L1 transaction deposits are [deposit transactions][deposit-transaction-type] generated by the [L2 Chain Derivation][derivation] process. The values of each transaction are determined by the -corresponding `TransactionDeposited` event emitted by the [Deposit Feed +corresponding `TransactionDeposited` event emitted by the [deposit feed contract][deposit-feed-contract] on L1. -1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in - the Deposit Feed contract). +1. `from` is unchanged from the emitted value (though it may have been transformed to an in + the deposit feed contract). 2. `to` may be either: 1. any 20-byte address (including the zero-address) 2. `null` in which case a contract is created. @@ -157,19 +176,14 @@ contract][deposit-feed-contract] on L1. [deposit-feed-contract]: #deposit-feed-contract -The Deposit Feed contract is deployed to L1. Deposited Transactions are derived from the values in -the `TransactionDeposited` event(s) emitted by the Deposit Feed contract. +The deposit feed contract is deployed to L1. Deposited transactions are derived from the values in +the `TransactionDeposited` event(s) emitted by the deposit feed contract. -The Deposit Feed handles two special cases: +The deposit feed handles two special cases: 1. A contract creation deposit, which is indicated by setting the `isCreation` flag to `true`. In the event that the `to` address is non-zero, the contract will revert. -2. A call from a contract account, in which case the `from` value is transformed to its L2 alias (by - adding `0x1111000000000000000000000000000000001111`). This prevents attacks in which a contract - on L1 has the same address as a contract on L2 but doesn't have the same code. We can safely - ignore this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). - This also makes it possible for users to interact with contracts on L2 even when the Sequencer is - down. +2. A call from a contract account, in which case the `from` value is transformed to its L2 . > **TODO** Define if/how ETH withdrawals occur. @@ -216,10 +230,12 @@ contract DepositFeed { } ``` - -[transaction-type]: /glossary.md#transaction-type -[derivation]: /glossary.md#L2-chain-derivation +#### Address aliasing - -[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -[ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html +[address-aliasing]: #address-aliasing + +If the caller is not a contract, the address will be ed by adding +`0x1111000000000000000000000000000000001111`. This prevents attacks in which a contract on L1 +has the same address as a contract on L2 but doesn't have the same code. We can safely ignore +this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also +makes it possible for users to interact with contracts on L2 even when the Sequencer is down. diff --git a/glossary.md b/glossary.md index 9c28e4263426..463dc889183f 100644 --- a/glossary.md +++ b/glossary.md @@ -2,7 +2,6 @@ ## Table of Contents -- [Glossary](#glossary) - [General Terms](#general-terms) - [Layer 1 (L1)](#layer-1-l1) - [Layer 2 (L2)](#layer-2-l2) @@ -12,7 +11,9 @@ - [Chain Re-Organization](#chain-re-organization) - [Predeployed Contract ("Predeploy")](#predeployed-contract-predeploy) - [Receipt](#receipt) + - [Transaction Type](#transaction-type) - [L2 Chain Concepts](#l2-chain-concepts) + - [Address Aliasing](#address-aliasing) - [L2 Chain Inception](#l2-chain-inception) - [Rollup Node](#rollup-node) - [Rollup Driver](#rollup-driver) @@ -22,6 +23,7 @@ - [L1 Attributes Transaction](#l1-attributes-transaction) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - [Deposits](#deposits) + - [Deposit Transaction Type](#deposit-transaction-type) - [Deposit Feed Contract](#deposit-feed-contract) - [Execution Engine Concepts](#execution-engine-concepts) - [Execution Engine](#execution-engine) @@ -115,6 +117,15 @@ Different transaction types can contain different payloads, and be handled diffe # L2 Chain Concepts +## Address Aliasing + +[address-aliasing]: /glossary.md#address-aliasing + +When a contract submits a [deposit] from L1 to L2, it's address (as returned by `ORIGIN` and `CALLER`) + will be aliased with a modified representation of the address of a contract. + +- cf. [Deposit Specification](/deposits.md#address-aliasing) + ## L2 Chain Inception [L2 chain inception]: /glossary.md#L2-chain-inception @@ -218,6 +229,13 @@ understood as "a transaction *deposited* to L2". Deposits are one kind of [L2 derivation input][deriv-input]. +## Deposit Transaction Type + +[deposit-tx-type]: /glossary.md#deposit-transaction-type + +The deposit transaction type is an [EIP-2718] [transaction type][transaction-type], which specifies +the input fields and correct handling of a [deposit][deposits]. + ## Deposit Feed Contract [deposit-feed]: /glossary.md#deposit-feed-contract @@ -239,7 +257,7 @@ cf. [Deposit Feed Contract Specification](TODO) ## Execution Engine -[execution engine]: /glossary.md#execution-engine +[execution-engine]: /glossary.md#execution-engine The execution engine is responsible for executing transactions in blocks and computing the resulting state roots, receipts roots and block hash. @@ -254,6 +272,8 @@ transactions [derived from L1 blocks][derivations]. In these specifications, "execution engine" always refer to the L2 execution engine, unless otherwise specified. +- cf. [Execution Engine Specification](/exec-engine.md) + [Merkle Patricia tree]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md [trie]: https://en.wikipedia.org/wiki/Trie From 4729f5ec12e92417314d6727d97cd488e3e59292 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 10 Dec 2021 10:37:19 -0500 Subject: [PATCH 098/585] Clarify rationale for only one new tx type --- deposits.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/deposits.md b/deposits.md index 79cfb29c47f1..ca544e07abb5 100644 --- a/deposits.md +++ b/deposits.md @@ -39,11 +39,17 @@ Picking a high identifier minimizes the risk that the identifier will be used be transaction type on the L1 chain in the future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. +### Uses of the Deposit Transaction Type + Although in practice we define only one new transaction type we can distinguish between two distinct -transactions which occur in the deposit block, based on their positioning. The first transaction -MUST be a [L1 attributes deposit][l1-attributes-deposit], followed by a an array of zero-or-more -[L1 transaction deposits][l1-transaction-deposits] submitted to the deposit feed contract by -accounts on L1. +situations which occur in the deposit block, based on their positioning. + +1. The first transaction MUST be a [L1 attributes deposit][l1-attributes-deposit], followed by +2. an array of zero-or-more [L1 transaction deposits][l1-transaction-deposits] submitted to the +deposit feed contract on L1. + +The rationale for creating only one new transaction type is to minimize both +modifications to L1 client software and complexity in general. > **TODO** Specify and link to deposit blocks From 99a881a095125c2ac9a79ac9f97a6cac79f13f1d Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Tue, 14 Dec 2021 15:45:57 +0100 Subject: [PATCH 099/585] clarify range notation Co-authored-by: Diederik Loerakker --- rollup-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollup-node.md b/rollup-node.md index 5f87473c6a00..4ddd91424999 100644 --- a/rollup-node.md +++ b/rollup-node.md @@ -248,7 +248,7 @@ the descendant of an ancestor of the previous head). In those case, the rollup d 2. If the call returns `"SUCCESS"`, we are done: the execution engine retrieved all the new L2 blocks via [block sync]. 3. Otherwise the call returns `"SYNCING"`, and we must derive the new blocks ourselves. Start by locating the *common ancestor*, a block that is an ancestor of both the previous and new head. -4. Isolate the range of L1 blocks `]common ancestor, ..., new head]`. +4. Isolate the range of L1 blocks from `common ancestor` (excluded) to `new head` (included). 5. For each such block, call [`engine_forkchoiceUpdatedOPV1`], [`engine_getPayloadV1`], and [`engine_executePayloadV1`]. - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but From bbd92ac57fd934482e4dea44b35d55191a113e55 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 13 Dec 2021 10:20:12 -0500 Subject: [PATCH 100/585] Add contracts package with hardhat and associated tooling fixup! Add contracts package with hardhat and associated tooling --- packages/contracts/.eslintignore | 5 + packages/contracts/.eslintrc.js | 24 + packages/contracts/.gitignore | 3 + packages/contracts/.npmignore | 3 + packages/contracts/.prettierignore | 6 + packages/contracts/.prettierrc.js | 24 + packages/contracts/.solhint.json | 16 + packages/contracts/.solhintignore | 1 + packages/contracts/README.md | 17 + packages/contracts/hardhat.config.ts | 24 + packages/contracts/package.json | 53 + packages/contracts/tsconfig.json | 12 + packages/contracts/yarn.lock | 10320 +++++++++++++++++++++++++ 13 files changed, 10508 insertions(+) create mode 100644 packages/contracts/.eslintignore create mode 100644 packages/contracts/.eslintrc.js create mode 100644 packages/contracts/.gitignore create mode 100644 packages/contracts/.npmignore create mode 100644 packages/contracts/.prettierignore create mode 100644 packages/contracts/.prettierrc.js create mode 100644 packages/contracts/.solhint.json create mode 100644 packages/contracts/.solhintignore create mode 100644 packages/contracts/README.md create mode 100644 packages/contracts/hardhat.config.ts create mode 100644 packages/contracts/package.json create mode 100644 packages/contracts/tsconfig.json create mode 100644 packages/contracts/yarn.lock diff --git a/packages/contracts/.eslintignore b/packages/contracts/.eslintignore new file mode 100644 index 000000000000..d08b03625b96 --- /dev/null +++ b/packages/contracts/.eslintignore @@ -0,0 +1,5 @@ +node_modules +artifacts +cache +typechain +coverage* diff --git a/packages/contracts/.eslintrc.js b/packages/contracts/.eslintrc.js new file mode 100644 index 000000000000..97852d4c7764 --- /dev/null +++ b/packages/contracts/.eslintrc.js @@ -0,0 +1,24 @@ +module.exports = { + env: { + browser: false, + es2021: true, + mocha: true, + node: true, + }, + plugins: ['@typescript-eslint'], + extends: [ + 'standard', + 'plugin:prettier/recommended', + 'plugin:node/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 12, + }, + rules: { + 'node/no-unsupported-features/es-syntax': [ + 'error', + { ignores: ['modules'] }, + ], + }, +} diff --git a/packages/contracts/.gitignore b/packages/contracts/.gitignore new file mode 100644 index 000000000000..674f13159b32 --- /dev/null +++ b/packages/contracts/.gitignore @@ -0,0 +1,3 @@ +artifacts +cache +typechain diff --git a/packages/contracts/.npmignore b/packages/contracts/.npmignore new file mode 100644 index 000000000000..dc037817bf3a --- /dev/null +++ b/packages/contracts/.npmignore @@ -0,0 +1,3 @@ +hardhat.config.ts +scripts +test diff --git a/packages/contracts/.prettierignore b/packages/contracts/.prettierignore new file mode 100644 index 000000000000..db04f3ca875d --- /dev/null +++ b/packages/contracts/.prettierignore @@ -0,0 +1,6 @@ +node_modules +artifacts +cache +typechain +coverage* +gasReporterOutput.json diff --git a/packages/contracts/.prettierrc.js b/packages/contracts/.prettierrc.js new file mode 100644 index 000000000000..e52f309d6e1a --- /dev/null +++ b/packages/contracts/.prettierrc.js @@ -0,0 +1,24 @@ +module.exports = { + $schema: 'http://json.schemastore.org/prettierrc', + trailingComma: 'es5', + tabWidth: 2, + semi: false, + singleQuote: true, + arrowParens: 'always', + overrides: [ + { + files: '*.sol', + options: { + // These options are native to Prettier. + printWidth: 100, + tabWidth: 4, + useTabs: false, + singleQuote: false, + bracketSpacing: true, + // These options are specific to the Solidity Plugin + explicitTypes: 'always', + compiler: '0.8.10', + }, + }, + ], +} diff --git a/packages/contracts/.solhint.json b/packages/contracts/.solhint.json new file mode 100644 index 000000000000..c0db83a45cc3 --- /dev/null +++ b/packages/contracts/.solhint.json @@ -0,0 +1,16 @@ +{ + "extends": "solhint:recommended", + "plugins": ["prettier"], + "rules": { + "prettier/prettier": "error", + "compiler-version": "off", + "code-complexity": ["warn", 5], + "max-line-length": ["error", 100], + "func-param-name-mixedcase": "error", + "modifier-name-mixedcase": "error", + "ordering": "warn", + "avoid-low-level-calls": "off", + "reason-string": "off", + "avoid-tx-origin": "off" + } +} diff --git a/packages/contracts/.solhintignore b/packages/contracts/.solhintignore new file mode 100644 index 000000000000..3c3629e647f5 --- /dev/null +++ b/packages/contracts/.solhintignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/contracts/README.md b/packages/contracts/README.md new file mode 100644 index 000000000000..ba40b3d099a9 --- /dev/null +++ b/packages/contracts/README.md @@ -0,0 +1,17 @@ +# Contracts for OVM 1.0 + +## Usage + +Install with yarn (v1), and Node.js (14+). + +```shell +yarn +``` + +### Running Tests + +Tests are executed via `yarn`: + +```shell +yarn test +``` diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts new file mode 100644 index 000000000000..b21653a8b4ae --- /dev/null +++ b/packages/contracts/hardhat.config.ts @@ -0,0 +1,24 @@ +import { HardhatUserConfig, task } from 'hardhat/config' +import '@nomiclabs/hardhat-waffle' +import '@typechain/hardhat' +import 'hardhat-gas-reporter' +import 'solidity-coverage' + +task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { + const accounts = await hre.ethers.getSigners() + + for (const account of accounts) { + console.log(account.address) + } +}) + +const config: HardhatUserConfig = { + solidity: '0.8.10', + networks: {}, + gasReporter: { + enabled: process.env.REPORT_GAS !== undefined, + currency: 'USD', + }, +} + +export default config diff --git a/packages/contracts/package.json b/packages/contracts/package.json new file mode 100644 index 000000000000..7b8be6263000 --- /dev/null +++ b/packages/contracts/package.json @@ -0,0 +1,53 @@ +{ + "name": "@eth-optimism/specs-contracts", + "version": "0.1.0", + "description": "Contracts for Optimism Specs", + "main": "index.js", + "license": "MIT", + "dependencies": { + "hardhat": "^2.7.1" + }, + "scripts": { + "test": "hardhat test", + "lint:ts:check": "eslint .", + "lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol'", + "lint:check": "yarn lint:contracts:check && yarn lint:ts:check", + "lint:ts:fix": "prettier --write .", + "lint:contracts:fix": "prettier --write 'contracts/**/*.sol'", + "lint:fix": "yarn lint:contracts:fix && yarn lint:ts:fix", + "lint": "yarn lint:fix && yarn lint:check" + }, + "devDependencies": { + "@eth-optimism/core-utils": "^0.7.3", + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^2.1.3", + "@nomiclabs/hardhat-waffle": "^2.0.0", + "@typechain/ethers-v5": "^7.0.1", + "@typechain/hardhat": "^2.3.0", + "@types/chai": "^4.2.21", + "@types/mocha": "^9.0.0", + "@types/node": "^12.0.0", + "@typescript-eslint/eslint-plugin": "^4.29.1", + "@typescript-eslint/parser": "^4.29.1", + "chai": "^4.2.0", + "dotenv": "^10.0.0", + "eslint": "^7.29.0", + "eslint-config-prettier": "^8.3.0", + "eslint-config-standard": "^16.0.3", + "eslint-plugin-import": "^2.23.4", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-promise": "^5.1.0", + "ethereum-waffle": "^3.0.0", + "ethers": "^5.0.0", + "hardhat-gas-reporter": "^1.0.4", + "prettier": "^2.3.2", + "prettier-plugin-solidity": "^1.0.0-beta.13", + "solhint": "^3.3.6", + "solhint-plugin-prettier": "^0.0.5", + "solidity-coverage": "^0.7.16", + "ts-node": "^10.1.0", + "typechain": "^5.1.2", + "typescript": "^4.5.2" + } +} diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json new file mode 100644 index 000000000000..47f802e43de1 --- /dev/null +++ b/packages/contracts/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "declaration": true + }, + "include": ["./scripts", "./test", "./typechain"], + "files": ["./hardhat.config.ts"] +} diff --git a/packages/contracts/yarn.lock b/packages/contracts/yarn.lock new file mode 100644 index 000000000000..ad3a127b70ef --- /dev/null +++ b/packages/contracts/yarn.lock @@ -0,0 +1,10320 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" + integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== + dependencies: + "@babel/highlight" "^7.16.0" + +"@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" + integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== + dependencies: + "@babel/helper-validator-identifier" "^7.15.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@eth-optimism/core-utils@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.7.3.tgz#67a7ec3cd65a555c6b5ef50d03ea66aa8df9f6c8" + integrity sha512-e531gfcMN6LWvGgJGfB37cU8HNUXfCkT6OO84KT8qKHMT4mOxyUqnApTYOHBxXGetLd3z/n67KwBCkJLZBr9jw== + dependencies: + "@ethersproject/abstract-provider" "^5.4.1" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/providers" "^5.4.5" + "@ethersproject/web" "^5.5.0" + chai "^4.3.4" + ethers "^5.4.5" + lodash "^4.17.21" + +"@ethereum-waffle/chai@^3.4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.1.tgz#500b59db766a490cb19a7f74ac75a1c3cf86049b" + integrity sha512-8mjgjWCe8XSCWuyJgVtJY8sm00VTczGBTDxBejgEBWN/J9x7QD8jdmWW8bfxdnqZbxiDCTvRFL58Wmd254BEqQ== + dependencies: + "@ethereum-waffle/provider" "^3.4.0" + ethers "^5.4.7" + +"@ethereum-waffle/compiler@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.0.tgz#68917321212563544913de33e408327745cb1284" + integrity sha512-a2wxGOoB9F1QFRE+Om7Cz2wn+pxM/o7a0a6cbwhaS2lECJgFzeN9xEkVrKahRkF4gEfXGcuORg4msP0Asxezlw== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.3.0.tgz#d54f4c8e6b7bcafdc13ab294433f45416b2b2791" + integrity sha512-zVIH/5cQnIEgJPg1aV8+ehYicpcfuAisfrtzYh1pN3UbfeqPylFBeBaIZ7xj/xYzlJjkrek/h9VfULl6EX9Aqw== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.0.1" + +"@ethereum-waffle/mock-contract@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.3.0.tgz#7b331f1c95c5d46ee9478f7a6be2869f707d307a" + integrity sha512-apwq0d+2nQxaNwsyLkE+BNMBhZ1MKGV28BtI9WjD3QD2Ztdt1q9II4sKA4VrLTUneYSmkYbJZJxw89f+OpJGyw== + dependencies: + "@ethersproject/abi" "^5.0.1" + ethers "^5.0.1" + +"@ethereum-waffle/provider@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.0.tgz#a36a0890d4fbc230e807870c8d3b683594efef00" + integrity sha512-QgseGzpwlzmaHXhqfdzthCGu5a6P1SBF955jQHf/rBkK1Y7gGo2ukt3rXgxgfg/O5eHqRU+r8xw5MzVyVaBscQ== + dependencies: + "@ethereum-waffle/ens" "^3.3.0" + ethers "^5.0.1" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + +"@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.0.tgz#5cf89ea748607597a3f8b038abc986e4ac0b05db" + integrity sha512-dqLo1LtsLG+Oelu5S5tWUDG0pah3QUwV5TJZy2cm19BXDr4ka/S9XBSgao0i09gTcuPlovlHgcs6d7EZ37urjQ== + dependencies: + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + ethereumjs-util "^7.1.3" + merkle-patricia-tree "^4.2.2" + +"@ethereumjs/blockchain@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.1.tgz#60f1f50592c06cc47e1704800b88b7d32f609742" + integrity sha512-JS2jeKxl3tlaa5oXrZ8mGoVBCz6YqsGG350XVNtHAtNZXKk7pU3rH4xzF2ru42fksMMqzFLzKh9l4EQzmNWDqA== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/ethash" "^1.1.0" + debug "^2.2.0" + ethereumjs-util "^7.1.3" + level-mem "^5.0.1" + lru-cache "^5.1.1" + semaphore-async-await "^1.5.1" + +"@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348" + integrity sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.3" + +"@ethereumjs/ethash@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.1.0.tgz#7c5918ffcaa9cb9c1dc7d12f77ef038c11fb83fb" + integrity sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA== + dependencies: + "@ethereumjs/block" "^3.5.0" + "@types/levelup" "^4.3.0" + buffer-xor "^2.0.1" + ethereumjs-util "^7.1.1" + miller-rabin "^4.0.0" + +"@ethereumjs/tx@^3.2.1", "@ethereumjs/tx@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.4.0.tgz#7eb1947eefa55eb9cf05b3ca116fb7a3dbd0bce7" + integrity sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw== + dependencies: + "@ethereumjs/common" "^2.6.0" + ethereumjs-util "^7.1.3" + +"@ethereumjs/vm@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.6.0.tgz#e0ca62af07de820143674c30b776b86c1983a464" + integrity sha512-J2m/OgjjiGdWF2P9bj/4LnZQ1zRoZhY8mRNVw/N3tXliGI8ai1sI1mlDPkLpeUUM4vq54gH6n0ZlSpz8U/qlYQ== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/blockchain" "^5.5.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + async-eventemitter "^0.2.4" + core-js-pure "^3.0.1" + debug "^2.2.0" + ethereumjs-util "^7.1.3" + functional-red-black-tree "^1.0.1" + mcl-wasm "^0.7.1" + merkle-patricia-tree "^4.2.2" + rustbn.js "~0.2.0" + +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + +"@ethersproject/abi@5.0.7": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" + integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== + dependencies: + "@ethersproject/address" "^5.0.4" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/hash" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/strings" "^5.0.4" + +"@ethersproject/abi@5.5.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" + integrity sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w== + dependencies: + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/abstract-provider@5.5.1", "@ethersproject/abstract-provider@^5.4.1", "@ethersproject/abstract-provider@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" + integrity sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/networks" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.0" + +"@ethersproject/abstract-signer@5.5.0", "@ethersproject/abstract-signer@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" + integrity sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + +"@ethersproject/address@5.5.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" + integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + +"@ethersproject/base64@5.5.0", "@ethersproject/base64@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" + integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + +"@ethersproject/basex@5.5.0", "@ethersproject/basex@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.5.0.tgz#e40a53ae6d6b09ab4d977bd037010d4bed21b4d3" + integrity sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + +"@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" + integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + bn.js "^4.11.9" + +"@ethersproject/bytes@5.5.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" + integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/constants@5.5.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" + integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + +"@ethersproject/contracts@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.5.0.tgz#b735260d4bd61283a670a82d5275e2a38892c197" + integrity sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg== + dependencies: + "@ethersproject/abi" "^5.5.0" + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + +"@ethersproject/hash@5.5.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" + integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/hdnode@5.5.0", "@ethersproject/hdnode@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.5.0.tgz#4a04e28f41c546f7c978528ea1575206a200ddf6" + integrity sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/basex" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/pbkdf2" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/wordlists" "^5.5.0" + +"@ethersproject/json-wallets@5.5.0", "@ethersproject/json-wallets@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz#dd522d4297e15bccc8e1427d247ec8376b60e325" + integrity sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hdnode" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/pbkdf2" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" + integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.5.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" + integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== + +"@ethersproject/networks@5.5.1", "@ethersproject/networks@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.1.tgz#b7f7b9fb88dec1ea48f739b7fb9621311aa8ce6c" + integrity sha512-tYRDM4zZtSUcKnD4UMuAlj7SeXH/k5WC4SP2u1Pn57++JdXHkRu2zwNkgNogZoxHzhm9Q6qqurDBVptHOsW49Q== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/pbkdf2@5.5.0", "@ethersproject/pbkdf2@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz#e25032cdf02f31505d47afbf9c3e000d95c4a050" + integrity sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + +"@ethersproject/properties@5.5.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" + integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/providers@5.5.1", "@ethersproject/providers@^5.4.5": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.1.tgz#ba87e3c93219bbd2e2edf8b369873aee774abf04" + integrity sha512-2zdD5sltACDWhjUE12Kucg2PcgM6V2q9JMyVvObtVGnzJu+QSmibbP+BHQyLWZUBfLApx2942+7DC5D+n4wBQQ== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/basex" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/networks" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.5.0", "@ethersproject/random@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.0.tgz#305ed9e033ca537735365ac12eed88580b0f81f9" + integrity sha512-egGYZwZ/YIFKMHcoBUo8t3a8Hb/TKYX8BCBoLjudVCZh892welR3jOxgOmb48xznc9bTcMm7Tpwc1gHC1PFNFQ== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/rlp@5.5.0", "@ethersproject/rlp@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" + integrity sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/sha2@5.5.0", "@ethersproject/sha2@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" + integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.5.0", "@ethersproject/signing-key@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" + integrity sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.5.0.tgz#2662eb3e5da471b85a20531e420054278362f93f" + integrity sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/strings@5.5.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" + integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/transactions@5.5.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" + integrity sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA== + dependencies: + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + +"@ethersproject/units@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.5.0.tgz#104d02db5b5dc42cc672cc4587bafb87a95ee45e" + integrity sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/wallet@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.5.0.tgz#322a10527a440ece593980dca6182f17d54eae75" + integrity sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/hdnode" "^5.5.0" + "@ethersproject/json-wallets" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/wordlists" "^5.5.0" + +"@ethersproject/web@5.5.1", "@ethersproject/web@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316" + integrity sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg== + dependencies: + "@ethersproject/base64" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/wordlists@5.5.0", "@ethersproject/wordlists@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.5.0.tgz#aac74963aa43e643638e5172353d931b347d584f" + integrity sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nomiclabs/hardhat-ethers@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.3.tgz#06e20a57274f6ce3148132910e723948a711edf1" + integrity sha512-IJ0gBotVtO7YyLZyHNgbxzskUtFok+JkRlKPo8YELqj1ms9XL6Qm3vsfsGdZr22wnJeVEF5TQPotKuwQk21Dag== + +"@nomiclabs/hardhat-etherscan@^2.1.3": + version "2.1.8" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.8.tgz#e206275e96962cd15e5ba9148b44388bc922d8c2" + integrity sha512-0+rj0SsZotVOcTLyDOxnOc3Gulo8upo0rsw/h+gBPcmtj91YqYJNhdARHoBxOhhE8z+5IUQPx+Dii04lXT14PA== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^5.0.2" + debug "^4.1.1" + fs-extra "^7.0.1" + node-fetch "^2.6.0" + semver "^6.3.0" + +"@nomiclabs/hardhat-waffle@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.1.tgz#5d43654fba780720c5033dea240fe14f70ef4bd2" + integrity sha512-2YR2V5zTiztSH9n8BYWgtv3Q+EL0N5Ltm1PAr5z20uAY4SkkfylJ98CIqt18XFvxTD5x4K2wKBzddjV9ViDAZQ== + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + hosted-git-info "^2.6.0" + path-browserify "^1.0.0" + url "^0.11.0" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^7.1.0": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" + integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@solidity-parser/parser@^0.13.2": + version "0.13.2" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.13.2.tgz#b6c71d8ca0b382d90a7bbed241f9bc110af65cbe" + integrity sha512-RwHnpRnfrnD2MSPveYoPh8nhofEvX7fgjHk1Oq+NNvCcLx4r1js91CO9o+F/F3fBzOCyvm8kKRTriFICX/odWw== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@solidity-parser/parser@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.0.tgz#d51f074efb0acce0e953ec48133561ed710cebc0" + integrity sha512-cX0JJRcmPtNUJpzD2K7FdA7qQsTOk1UZnFx2k7qAg9ZRvuaH5NBe5IEdBMXGlmf2+FmjhqbygJ26H8l2SV7aKQ== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@truffle/error@^0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.0.14.tgz#59683b5407bede7bddf16d80dc5592f9c5e5fa05" + integrity sha512-utJx+SZYoMqk8wldQG4gCVKhV8GwMJbWY7sLXFT/D8wWZTnE2peX7URFJh/cxkjTRCO328z1s2qewkhyVsu2HA== + +"@truffle/interface-adapter@^0.5.8": + version "0.5.8" + resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.8.tgz#76cfd34374d85849e1164de1a3d5a3dce0dc5d01" + integrity sha512-vvy3xpq36oLgjjy8KE9l2Jabg3WcGPOt18tIyMfTQX9MFnbHoQA2Ne2i8xsd4p6KfxIqSjAB53Q9/nScAqY0UQ== + dependencies: + bn.js "^5.1.3" + ethers "^4.0.32" + web3 "1.5.3" + +"@truffle/provider@^0.2.24": + version "0.2.42" + resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.2.42.tgz#9da6a144b3c9188cdb587451dd7bd907b4c7164b" + integrity sha512-ZNoglPho4alYIjJR+sLTgX0x6ho7m4OAUWuJ50RAWmoEqYc4AM6htdrI+lTSoRrOHHbmgasv22a7rFPMnmDrTg== + dependencies: + "@truffle/error" "^0.0.14" + "@truffle/interface-adapter" "^0.5.8" + web3 "1.5.3" + +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@typechain/ethers-v5@^7.0.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz#d559cffe0efe6bdbc20e644b817f6fa8add5e8f8" + integrity sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/hardhat@^2.3.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-2.3.1.tgz#1e8a6e3795e115a5d5348526282b5c597fab0b78" + integrity sha512-BQV8OKQi0KAzLXCdsPO0pZBNQQ6ra8A2ucC26uFX/kquRBtJu1yEyWnVSmtr07b5hyRoJRpzUeINLnyqz4/MAw== + dependencies: + fs-extra "^9.1.0" + +"@types/abstract-leveldown@*": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.2.tgz#ee81917fe38f770e29eec8139b6f16ee4a8b0a5f" + integrity sha512-+jA1XXF3jsz+Z7FcuiNqgK53hTa/luglT2TyTpKPqoYbxVY+mCPF22Rm+q3KPBrMHJwNXFrTViHszBOfU4vftQ== + +"@types/bn.js@*", "@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/chai@*", "@types/chai@^4.2.21": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" + integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== + +"@types/concat-stream@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" + integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== + dependencies: + "@types/node" "*" + +"@types/form-data@0.0.33": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" + integrity sha1-yayFsqX9GENbjIXZ7LUObWyJP/g= + dependencies: + "@types/node" "*" + +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/json-schema@^7.0.7": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/level-errors@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/level-errors/-/level-errors-3.0.0.tgz#15c1f4915a5ef763b51651b15e90f6dc081b96a8" + integrity sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ== + +"@types/levelup@^4.3.0": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-4.3.3.tgz#4dc2b77db079b1cf855562ad52321aa4241b8ef4" + integrity sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA== + dependencies: + "@types/abstract-leveldown" "*" + "@types/level-errors" "*" + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/minimatch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/mocha@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.0.0.tgz#3205bcd15ada9bc681ac20bef64e9e6df88fd297" + integrity sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA== + +"@types/node-fetch@^2.5.5": + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "16.11.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10" + integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw== + +"@types/node@^10.0.3": + version "10.17.60" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" + integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== + +"@types/node@^12.0.0", "@types/node@^12.12.6": + version "12.20.37" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.37.tgz#abb38afa9d6e8a2f627a8cb52290b3c80fbe61ed" + integrity sha512-i1KGxqcvJaLQali+WuypQnXwcplhtNtjs66eNsZpp2P2FL/trJJxx/VWsM0YCL2iMoIJrbXje48lvIQAQ4p2ZA== + +"@types/node@^8.0.0": + version "8.10.66" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" + integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.2.tgz#4c62fae93eb479660c3bd93f9d24d561597a8281" + integrity sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA== + +"@types/qs@^6.2.31": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@types/sinon-chai@^3.2.3": + version "3.2.6" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.6.tgz#3504a744e2108646394766fb1339f52ea5d6bd0f" + integrity sha512-Z57LprQ+yOQNu9d6mWdHNvnmncPXzDWGSeLj+8L075/QahToapC4Q13zAFRVKV4clyBmdJ5gz4xBfVkOso5lXw== + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "10.0.6" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.6.tgz#bc3faff5154e6ecb69b797d311b7cf0c1b523a1d" + integrity sha512-6EF+wzMWvBNeGrfP3Nx60hhx+FfwSg1JJBLAAP/IdIUq0EYkqCYf70VT3PhuhPX9eLD+Dp+lNdpb/ZeHG8Yezg== + dependencies: + "@sinonjs/fake-timers" "^7.1.0" + +"@types/underscore@*": + version "1.11.4" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3" + integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg== + +"@types/web3@1.0.19": + version "1.0.19" + resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" + integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + +"@typescript-eslint/eslint-plugin@^4.29.1": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== + dependencies: + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@^4.29.1": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== + dependencies: + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + debug "^4.3.1" + +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a" + integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb" + integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-jsx@^5.0.0, acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^6.0.7: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.4.1: + version "8.6.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" + integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== + +address@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" + integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +antlr4@4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" + integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + +anymatch@~3.1.1, anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + integrity sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs= + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-includes@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" + integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-uniq@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +array.prototype.flat@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +ast-parents@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha1-UI/Q8F0MSHddnszaLhdEIyYejdM= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@1.x, async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +async@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= + dependencies: + precond "0.2" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bignumber.js@^9.0.0, bignumber.js@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" + integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +bip66@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" + integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= + dependencies: + safe-buffer "^5.0.1" + +blakejs@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" + integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== + +bluebird@^3.5.0, bluebird@^3.5.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +body-parser@^1.16.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" + integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== + dependencies: + bytes "3.1.1" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.9.6" + raw-body "2.4.2" + type-is "~1.6.18" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bufferutil@^4.0.1: + version "4.0.5" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.5.tgz#da9ea8166911cc276bf677b8aed2d02d31f59028" + integrity sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A== + dependencies: + node-gyp-build "^4.3.0" + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +bytes@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" + integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== + +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI= + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4= + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" + integrity sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU= + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-lite@^1.0.30000844: + version "1.0.30001286" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001286.tgz#3e9debad420419618cfdf52dc9b6572b28a8fff6" + integrity sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ== + +caseless@^0.12.0, caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +cbor@^5.0.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" + integrity sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A== + dependencies: + bignumber.js "^9.0.1" + nofilter "^1.0.4" + +chai@^4.2.0, chai@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +"charenc@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= + dependencies: + functional-red-black-tree "^1.0.1" + +chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + +chokidar@^3.4.0: + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cids@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@2.1.2, clone@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +commander@2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" + integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-hash@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" + integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== + dependencies: + cids "^0.7.1" + multicodec "^0.5.5" + multihashes "^0.4.15" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.5.1: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +cookie@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +cookiejar@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" + integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-pure@^3.0.1: + version "3.19.3" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.19.3.tgz#c69b2b36b58927317824994b532ec3f0f7e49607" + integrity sha512-N3JruInmCyt7EJj5mAq3csCgGYgiSqu7p7TQp2KOztr180/OAIxyIvL1FCjzgmQk/t3Yniua50Fsak7FShI9lA== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cosmiconfig@^5.0.7: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +crc-32@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" + integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.1.0" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.5.tgz#afaf5729f3b6c78d89c9296115c9f142541a5705" + integrity sha512-xqYAhQb4NhCJSRym03dwxpP1bYXpK3y7UN83Bo2WFi3x1Zmzn0SL/6xGoPr+gpt4WmNrgCCX3HPysvOwFOW36w== + dependencies: + node-fetch "2.6.1" + whatwg-fetch "2.0.4" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +"crypt@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + +crypto-browserify@3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +death@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@^3.1.0, debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.1, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.2.0, decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +deferred-leveldown@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058" + integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw== + dependencies: + abstract-leveldown "~6.2.1" + inherits "^2.0.3" + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= + dependencies: + repeating "^2.0.0" + +detect-port@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" + integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== + dependencies: + address "^1.0.1" + debug "^2.6.0" + +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + +drbg.js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" + integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= + dependencies: + browserify-aes "^1.0.6" + create-hash "^1.1.2" + create-hmac "^1.1.4" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +electron-to-chromium@^1.3.47: + version "1.4.16" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.16.tgz#38ddecc616385e6f101359d1b978c802664157d2" + integrity sha512-BQb7FgYwnu6haWLU63/CdVW+9xhmHls3RCQUFiV4lvw3wimEHTVcUk2hkuZo76QhR8nnDdfZE7evJIZqijwPdA== + +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.0.0.tgz#96559e19f82231b436403e059571241d627c42b8" + integrity sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + +encoding-down@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" + integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw== + dependencies: + abstract-leveldown "^6.2.1" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.0, enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +eslint-config-prettier@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" + integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== + +eslint-config-standard@^16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" + integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== + +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz#b435001c9f8dd4ab7f6d0efcae4b9696d4c24b7c" + integrity sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + pkg-dir "^2.0.0" + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-import@^2.23.4: + version "2.25.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766" + integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.1" + has "^1.0.3" + is-core-module "^2.8.0" + is-glob "^4.0.3" + minimatch "^3.0.4" + object.values "^1.1.5" + resolve "^1.20.0" + tsconfig-paths "^3.11.0" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-prettier@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" + integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-promise@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz#a596acc32981627eb36d9d75f9666ac1a4564971" + integrity sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw== + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^1.3.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@^5.6.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + +eslint@^7.29.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.1.2" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.0.1, esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0, esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-gas-reporter@^0.2.23: + version "0.2.23" + resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.23.tgz#7a2a412b41285298cdad810cf54adac11d406208" + integrity sha512-T8KsVakDEupvQxW3MfFfHDfJ7y8zl2+XhyEQk4hZ3qQsAh/FE27BfFHM9UhqNQvrJLz8zVWnPZWNcARwLT/lsA== + dependencies: + "@ethersproject/abi" "^5.0.0-beta.146" + "@solidity-parser/parser" "^0.14.0" + cli-table3 "^0.5.0" + colors "^1.1.2" + ethereumjs-util "6.2.0" + ethers "^4.0.40" + fs-readdir-recursive "^1.1.0" + lodash "^4.17.14" + markdown-table "^1.1.3" + mocha "^7.1.1" + req-cwd "^2.0.0" + request "^2.88.0" + request-promise-native "^1.0.5" + sha1 "^1.1.1" + sync-request "^6.0.0" + +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + dependencies: + buffer "^5.2.1" + elliptic "^6.4.0" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.0" + tweetnacl-util "^0.15.0" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-sig-util@^2.5.2: + version "2.5.4" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.4.tgz#577b01fe491b6bf59b0464be09633e20c1677bc5" + integrity sha512-aCMBwp8q/4wrW4QLsF/HYBOSA7TpLKmkVwP3pYQNkEEseW2Rr8Z5Uxc9/h6HX+OG3tuHo+2bINVSihIeBfym6A== + dependencies: + ethereumjs-abi "0.6.8" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.0" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + dependencies: + async "^2.1.2" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.6.0" + through2 "^2.0.3" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= + +ethereum-cryptography@^0.1.2, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-waffle@^3.0.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.0.tgz#990b3c6c26db9c2dd943bf26750a496f60c04720" + integrity sha512-ADBqZCkoSA5Isk486ntKJVjFEawIiC+3HxNqpJqONvh3YXBTNiRfXvJtGuAFLXPG91QaqkGqILEHANAo7j/olQ== + dependencies: + "@ethereum-waffle/chai" "^3.4.0" + "@ethereum-waffle/compiler" "^3.4.0" + "@ethereum-waffle/mock-contract" "^3.3.0" + "@ethereum-waffle/provider" "^3.4.0" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE= + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.1" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + dependencies: + async "^2.0.1" + ethereum-common "0.2.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + dependencies: + async "^2.6.1" + ethashjs "~0.0.7" + ethereumjs-block "~2.2.2" + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.1.0" + flow-stoplight "^1.0.0" + level-mem "^3.0.1" + lru-cache "^5.1.1" + rlp "^2.2.2" + semaphore "^1.1.0" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz#23ec79b2488a7d041242f01e25f24e5ad0357960" + integrity sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + ethjs-util "0.1.6" + keccak "^2.0.0" + rlp "^2.2.3" + secp256k1 "^3.0.1" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23" + integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + core-js-pure "^3.0.1" + ethereumjs-account "^3.0.0" + ethereumjs-block "^2.2.2" + ethereumjs-blockchain "^4.0.3" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.2" + ethereumjs-util "^6.2.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + util.promisify "^1.0.0" + +ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + +ethereumjs-wallet@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== + dependencies: + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^6.0.0" + randombytes "^2.0.6" + safe-buffer "^5.1.2" + scryptsy "^1.2.1" + utf8 "^3.0.0" + uuid "^3.3.2" + +ethers@^4.0.32, ethers@^4.0.40: + version "4.0.49" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" + integrity sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg== + dependencies: + aes-js "3.0.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.4" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + +ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.5, ethers@^5.4.7: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.2.tgz#cd2e508c7342c44fa70392f722e8de8f2416489f" + integrity sha512-EF5W+6Wwcu6BqVwpgmyR5U2+L4c1FQzlM/02dkZOugN3KF0cG9bzHZP+TDJglmPm2/IzCEJDT7KBxzayk7SAHw== + dependencies: + "@ethersproject/abi" "5.5.0" + "@ethersproject/abstract-provider" "5.5.1" + "@ethersproject/abstract-signer" "5.5.0" + "@ethersproject/address" "5.5.0" + "@ethersproject/base64" "5.5.0" + "@ethersproject/basex" "5.5.0" + "@ethersproject/bignumber" "5.5.0" + "@ethersproject/bytes" "5.5.0" + "@ethersproject/constants" "5.5.0" + "@ethersproject/contracts" "5.5.0" + "@ethersproject/hash" "5.5.0" + "@ethersproject/hdnode" "5.5.0" + "@ethersproject/json-wallets" "5.5.0" + "@ethersproject/keccak256" "5.5.0" + "@ethersproject/logger" "5.5.0" + "@ethersproject/networks" "5.5.1" + "@ethersproject/pbkdf2" "5.5.0" + "@ethersproject/properties" "5.5.0" + "@ethersproject/providers" "5.5.1" + "@ethersproject/random" "5.5.0" + "@ethersproject/rlp" "5.5.0" + "@ethersproject/sha2" "5.5.0" + "@ethersproject/signing-key" "5.5.0" + "@ethersproject/solidity" "5.5.0" + "@ethersproject/strings" "5.5.0" + "@ethersproject/transactions" "5.5.0" + "@ethersproject/units" "5.5.0" + "@ethersproject/wallet" "5.5.0" + "@ethersproject/web" "5.5.1" + "@ethersproject/wordlists" "5.5.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.3: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +express@^4.14.0: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= + dependencies: + checkpoint-store "^1.1.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.0.3, fast-glob@^3.1.1: + version "3.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= + dependencies: + node-fetch "~1.7.1" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A= + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flat@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== + dependencies: + is-buffer "~2.0.3" + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +flatted@^3.1.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" + integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" + integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= + +follow-redirects@^1.12.1: + version "1.14.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd" + integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A== + +for-each@^0.3.3, for-each@~0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^4.0.2, fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +ganache-cli@^6.12.2: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.12.2.tgz#c0920f7db0d4ac062ffe2375cb004089806f627a" + integrity sha512-bnmwnJDBDsOWBUP8E/BExWf85TsdDEFelQSzihSJm9VChVO1SHp94YXLP5BlA4j/OTxp0wR4R1Tje9OHOuAJVw== + dependencies: + ethereumjs-util "6.2.1" + source-map-support "0.5.12" + yargs "13.2.4" + +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + dependencies: + abstract-leveldown "3.0.0" + async "2.6.2" + bip39 "2.5.0" + cachedown "1.0.0" + clone "2.1.2" + debug "3.2.6" + encoding-down "5.0.4" + eth-sig-util "3.0.0" + ethereumjs-abi "0.6.8" + ethereumjs-account "3.0.0" + ethereumjs-block "2.2.2" + ethereumjs-common "1.5.0" + ethereumjs-tx "2.1.2" + ethereumjs-util "6.2.1" + ethereumjs-vm "4.2.0" + heap "0.2.6" + keccak "3.0.1" + level-sublevel "6.6.4" + levelup "3.1.1" + lodash "4.17.20" + lru-cache "5.1.1" + merkle-patricia-tree "3.0.0" + patch-package "6.2.2" + seedrandom "3.0.1" + source-map-support "0.5.12" + tmp "0.1.0" + web3-provider-engine "14.2.1" + websocket "1.0.32" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-port@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0, get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +ghost-testrpc@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz#c4de9557b1d1ae7b2d20bbe474a91378ca90ce92" + integrity sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ== + dependencies: + chalk "^2.4.2" + node-emoji "^1.10.0" + +glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@~7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +global@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^11.7.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" + integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== + dependencies: + type-fest "^0.20.2" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +got@9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +got@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +handlebars@^4.0.1: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +hardhat-gas-reporter@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.6.tgz#699bc0bb96e8c962c7f136a1c1f29cd3c32d569e" + integrity sha512-LlCEmSx1dZpnxKmODb2hmP5eJ1IAM5It3NnBNTUpBTxn9g9qPPI3JQTxj8AbGEiNc3r6V+w/mXYCmiC8pWvnoQ== + dependencies: + array-uniq "1.0.3" + eth-gas-reporter "^0.2.23" + sha1 "^1.1.1" + +hardhat@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.7.1.tgz#576a0420ce874fe00e7749924aefef2a0b14d3ae" + integrity sha512-zmyQe9tOMI9UmFXNnDzdrKMezmKyAawVxU0oIipWPbl9D3zvQJEKaOaNgc9gG31dgkh4WqWCnUR/QxV1U6ctzA== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/blockchain" "^5.5.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + "@ethereumjs/vm" "^5.6.0" + "@ethersproject/abi" "^5.1.2" + "@sentry/node" "^5.18.1" + "@solidity-parser/parser" "^0.14.0" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + eth-sig-util "^2.5.2" + ethereum-cryptography "^0.1.2" + ethereumjs-abi "^0.6.8" + ethereumjs-util "^7.1.3" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "^7.1.3" + https-proxy-agent "^5.0.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + lodash "^4.17.11" + merkle-patricia-tree "^4.2.0" + mnemonist "^0.38.0" + mocha "^7.1.2" + node-fetch "^2.6.0" + qs "^6.7.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + slash "^3.0.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + "true-case-path" "^2.2.1" + tsort "0.0.1" + uuid "^8.3.2" + ws "^7.4.6" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + +has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +heap@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" + integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +http-basic@^8.1.1: + version "8.1.3" + resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" + integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== + dependencies: + caseless "^0.12.0" + concat-stream "^1.6.2" + http-response-object "^3.0.1" + parse-cache-control "^1.0.1" + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= + +http-response-object@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" + integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== + dependencies: + "@types/node" "^10.0.3" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8: + version "5.1.9" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" + integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= + +immutable@^4.0.0-rc.12: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.2.0, is-core-module@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" + integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= + +is-negative-zero@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" + integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-retry-allowed@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.3, is-typed-array@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" + integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-weakref@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +js-sha3@0.5.7, js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + dependencies: + async "^2.0.1" + babel-preset-env "^1.7.0" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonschema@^1.2.4: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" + integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +keccak@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.1.0.tgz#734ea53f2edcfd0f42cdb8d5f4c358fef052752b" + integrity sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q== + dependencies: + bindings "^1.5.0" + inherits "^2.0.4" + nan "^2.14.0" + safe-buffer "^5.2.0" + +keccak@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-concat-iterator@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" + integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-iterator-stream@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c" + integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q== + dependencies: + inherits "^2.0.4" + readable-stream "^3.4.0" + xtend "^4.0.2" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-mem@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-5.0.1.tgz#c345126b74f5b8aa376dc77d36813a177ef8251d" + integrity sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg== + dependencies: + level-packager "^5.0.3" + memdown "^5.0.0" + +level-packager@^5.0.3: + version "5.1.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939" + integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ== + dependencies: + encoding-down "^6.3.0" + levelup "^4.3.2" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + dependencies: + bytewise "~1.1.0" + level-codec "^9.0.0" + level-errors "^2.0.0" + level-iterator-stream "^2.0.3" + ltgt "~2.1.1" + pull-defer "^0.2.2" + pull-level "^2.0.3" + pull-stream "^3.6.8" + typewiselite "~1.0.0" + xtend "~4.0.0" + +level-supports@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" + integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg== + dependencies: + xtend "^4.0.2" + +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + +level-ws@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-2.0.0.tgz#207a07bcd0164a0ec5d62c304b4615c54436d339" + integrity sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA== + dependencies: + inherits "^2.0.3" + readable-stream "^3.1.0" + xtend "^4.0.1" + +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + +levelup@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" + integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ== + dependencies: + deferred-leveldown "~5.3.0" + level-errors "~2.0.0" + level-iterator-stream "~4.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" + integrity sha1-Zs0Md0rz1P7axTeU90LbVtqPCew= + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k= + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@5.1.1, lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= + dependencies: + pseudomap "^1.0.1" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= + +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" + integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-table@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" + integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== + +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= + dependencies: + abstract-leveldown "~2.7.1" + functional-red-black-tree "^1.0.1" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memdown@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-5.1.0.tgz#608e91a9f10f37f5b5fe767667a8674129a833cb" + integrity sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw== + dependencies: + abstract-leveldown "~6.2.1" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.2.0" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + dependencies: + abstract-leveldown "~5.0.0" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge2@^1.2.3, merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + dependencies: + async "^2.6.1" + ethereumjs-util "^5.2.0" + level-mem "^3.0.1" + level-ws "^1.0.0" + readable-stream "^3.0.6" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + dependencies: + async "^1.4.2" + ethereumjs-util "^5.0.0" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^4.2.0, merkle-patricia-tree@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.2.tgz#6dec17855370172458244c2f42c989dd60b773a3" + integrity sha512-eqZYNTshcYx9aESkSPr71EqwsR/QmpnObDEV4iLxkt/x/IoLYZYjJvKY72voP/27Vy61iMOrfOG6jrn7ttXD+Q== + dependencies: + "@types/levelup" "^4.3.0" + ethereumjs-util "^7.1.2" + level-mem "^5.0.1" + level-ws "^2.0.0" + readable-stream "^3.6.0" + rlp "^2.2.4" + semaphore-async-await "^1.5.1" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^7.1.1, mocha@^7.1.2: + version "7.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" + integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + chokidar "3.3.0" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "3.0.0" + minimatch "3.0.4" + mkdirp "0.5.5" + ms "2.1.1" + node-environment-flags "1.0.6" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "1.6.0" + +mock-fs@^4.1.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" + integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multicodec@^0.5.5: + version "0.5.7" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" + integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== + dependencies: + varint "^5.0.0" + +multicodec@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^0.4.15, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +nan@^2.14.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-emoji@^1.10.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== + dependencies: + lodash "^4.17.21" + +node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-fetch@^2.6.0, node-fetch@^2.6.1: + version "2.6.6" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" + integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@~1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" + integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + +nofilter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e" + integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA== + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.11.0, object-inspect@^1.9.0, object-inspect@~1.11.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b" + integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" + integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +obliterator@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.1.tgz#fbdd873bf39fc4f365a53b1fc86617a22526987c" + integrity sha512-XnkiCrrBcIZQitJPAI36mrrpEUvatbte8hLcTcQwKA1v9NkCKasSi+UAguLsLDs/out7MoRzAlmz7VXvY6ph6w== + +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY= + dependencies: + http-https "^1.0.0" + +oboe@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= + dependencies: + http-https "^1.0.0" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +optionator@^0.8.1, optionator@^0.8.2: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + +os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-cache-control@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" + integrity sha1-juqz5U+laSD+Fro493+iGqzC104= + +parse-headers@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" + integrity sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^1.2.1" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +patch-package@^6.2.2: + version "6.4.7" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148" + integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier-plugin-solidity@^1.0.0-beta.13: + version "1.0.0-beta.19" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz#7c3607fc4028f5e6a425259ff03e45eedf733df3" + integrity sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g== + dependencies: + "@solidity-parser/parser" "^0.14.0" + emoji-regex "^10.0.0" + escape-string-regexp "^4.0.0" + semver "^7.3.5" + solidity-comments-extractor "^0.0.7" + string-width "^4.2.3" + +prettier@^1.14.3: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +prettier@^2.1.2, prettier@^2.3.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" + integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== + +printj@~1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" + integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +promise@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" + integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== + dependencies: + asap "~2.0.6" + +proxy-addr@~2.0.5: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" + integrity sha1-tkLdElXaN2pwa220+pYvX9t0wxs= + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + dependencies: + level-post "^1.0.7" + pull-cat "^1.1.9" + pull-live "^1.0.1" + pull-pushable "^2.0.0" + pull-stream "^3.4.0" + pull-window "^2.1.4" + stream-to-pull-stream "^1.7.1" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" + integrity sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU= + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha1-Xy867UethpGfAbEqLpnW8b13ZYE= + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.6.14" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.14.tgz#529dbd5b86131f4a5ed636fdf7f6af00781357ee" + integrity sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" + integrity sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA= + dependencies: + looper "^2.0.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +qs@6.9.6: + version "6.9.6" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" + integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== + +qs@^6.4.0, qs@^6.7.0: + version "6.10.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.2.tgz#c1431bea37fc5b24c5bdbafa20f16bdf2a4b9ffe" + integrity sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw== + dependencies: + side-channel "^1.0.4" + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-body@2.4.2, raw-body@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" + integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== + dependencies: + bytes "3.1.1" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.15: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +recursive-readdir@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" + integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + dependencies: + minimatch "3.0.4" + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +req-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" + integrity sha1-1AgrTURZgDZkD7c93qAe1T20nrw= + dependencies: + req-from "^2.0.0" + +req-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" + integrity sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA= + dependencies: + resolve-from "^3.0.0" + +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + dependencies: + lodash "^4.17.19" + +request-promise-native@^1.0.5: + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + dependencies: + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.79.0, request@^2.85.0, request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= + +require-from-string@^2.0.0, require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.20.0, resolve@^1.8.1, resolve@~1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rimraf@^2.2.8, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-async@^2.2.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sc-istanbul@^0.4.5: + version "0.4.6" + resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" + integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== + +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= + dependencies: + pbkdf2 "^3.0.3" + +secp256k1@^3.0.1: + version "3.8.0" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" + integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== + dependencies: + bindings "^1.5.0" + bip66 "^1.1.5" + bn.js "^4.11.8" + create-hash "^1.2.0" + drbg.js "^1.0.1" + elliptic "^6.5.2" + nan "^2.14.0" + safe-buffer "^5.1.2" + +secp256k1@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.2.tgz#15dd57d0f0b9fdb54ac1fa1694f40e5e9a54f4a1" + integrity sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg== + dependencies: + elliptic "^6.5.2" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore-async-await@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz#857bef5e3644601ca4b9570b87e9df5ca12974fa" + integrity sha1-hXvvXjZEYBykuVcLh+nfXKEpdPo= + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.1.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1, semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha1@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" + integrity sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg= + dependencies: + charenc ">= 0.0.1" + crypt ">= 0.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shelljs@^0.8.3: + version "0.8.4" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" + integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solc@^0.4.20: + version "0.4.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solhint-plugin-prettier@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/solhint-plugin-prettier/-/solhint-plugin-prettier-0.0.5.tgz#e3b22800ba435cd640a9eca805a7f8bc3e3e6a6b" + integrity sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA== + dependencies: + prettier-linter-helpers "^1.0.0" + +solhint@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.3.6.tgz#abe9af185a9a7defefba480047b3e42cbe9a1210" + integrity sha512-HWUxTAv2h7hx3s3hAab3ifnlwb02ZWhwFU/wSudUHqteMS3ll9c+m1FlGn9V8ztE2rf3Z82fQZA005Wv7KpcFA== + dependencies: + "@solidity-parser/parser" "^0.13.2" + ajv "^6.6.1" + antlr4 "4.7.1" + ast-parents "0.0.1" + chalk "^2.4.2" + commander "2.18.0" + cosmiconfig "^5.0.7" + eslint "^5.6.0" + fast-diff "^1.1.2" + glob "^7.1.3" + ignore "^4.0.6" + js-yaml "^3.12.0" + lodash "^4.17.11" + semver "^6.3.0" + optionalDependencies: + prettier "^1.14.3" + +solidity-comments-extractor@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" + integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== + +solidity-coverage@^0.7.16: + version "0.7.17" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.17.tgz#5139de8f6666d4755d88f453d8e35632a7bb3444" + integrity sha512-Erw2hd2xdACAvDX8jUdYkmgJlIIazGznwDJA5dhRaw4def2SisXN9jUjneeyOZnl/E7j6D3XJYug4Zg9iwodsg== + dependencies: + "@solidity-parser/parser" "^0.13.2" + "@truffle/provider" "^0.2.24" + chalk "^2.4.2" + death "^1.1.0" + detect-port "^1.3.0" + fs-extra "^8.1.0" + ganache-cli "^6.12.2" + ghost-testrpc "^0.0.2" + global-modules "^2.0.0" + globby "^10.0.1" + jsonschema "^1.2.4" + lodash "^4.17.15" + node-emoji "^1.10.0" + pify "^4.0.1" + recursive-readdir "^2.2.2" + sc-istanbul "^0.4.5" + semver "^7.3.4" + shelljs "^0.8.3" + web3-utils "^1.3.0" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= + dependencies: + amdefine ">=0.0.4" + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trim@~1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz#a587bcc8bfad8cb9829a577f5de30dd170c1682c" + integrity sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@2.0.1, strip-json-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +swarm-js@^0.1.40: + version "0.1.40" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" + integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^7.1.0" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request "^1.0.1" + +sync-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" + integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== + dependencies: + http-response-object "^3.0.1" + sync-rpc "^1.2.1" + then-request "^6.0.0" + +sync-rpc@^1.2.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" + integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== + dependencies: + get-port "^3.1.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +table@^6.0.9: + version "6.7.5" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.5.tgz#f04478c351ef3d8c7904f0e8be90a1b62417d238" + integrity sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tape@^4.6.3: + version "4.14.0" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.14.0.tgz#e4d46097e129817175b90925f2385f6b1bcfa826" + integrity sha512-z0+WrUUJuG6wIdWrl4W3rTte2CR26G6qcPOj3w1hfRdcmhF3kHBhOBW9VHsPVAkz08ZmGzp7phVpDupbLzrYKQ== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.0" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.1.7" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.3" + minimist "~1.2.5" + object-inspect "~1.11.0" + resolve "~1.20.0" + resumer "~0.0.0" + string.prototype.trim "~1.2.4" + through "~2.3.8" + +tar@^4.0.2: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha1-Edpv9nDzRxpztiXKTz/c97t0gpE= + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +then-request@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" + integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== + dependencies: + "@types/concat-stream" "^1.6.0" + "@types/form-data" "0.0.33" + "@types/node" "^8.0.0" + "@types/qs" "^6.2.31" + caseless "~0.12.0" + concat-stream "^1.6.0" + form-data "^2.2.0" + http-basic "^8.1.1" + http-response-object "^3.0.1" + promise "^8.0.0" + qs "^6.4.0" + +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@^2.3.6, through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +"true-case-path@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-2.2.1.tgz#c5bf04a5bbec3fd118be4084461b3a27c4d796bf" + integrity sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q== + +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + +ts-node@^10.1.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" + integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + yn "3.1.1" + +tsconfig-paths@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" + integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y= + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl-util@^0.15.0: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +tweetnacl@^1.0.0, tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.1.1" + +typechain@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-5.2.0.tgz#10525a44773a34547eb2eed8978cb72c0a39a0f4" + integrity sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw== + dependencies: + "@types/prettier" "^2.1.1" + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + glob "^7.1.6" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.1.2" + ts-essentials "^7.0.1" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^4.5.2: + version "4.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.3.tgz#afaa858e68c7103317d89eb90c5d8906268d353c" + integrity sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ== + +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU= + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE= + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" + integrity sha1-yIgvobsQksBgBal/NO9chQjjZk4= + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= + +uglify-js@^3.1.4: + version "3.14.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.4.tgz#68756f17d1b90b9d289341736cb9a567d6882f90" + integrity sha512-AbiSR44J0GoCeV81+oxcy/jDOElO2Bx3d0MfQCUShq7JRXaM4KtQopZsq2vFv8bCq2yMaGrw1FgygUd03RyRDA== + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf-8-validate@^5.0.2: + version "5.0.7" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.7.tgz#c15a19a6af1f7ad9ec7ddc425747ca28c3644922" + integrity sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0, utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" + integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + for-each "^0.3.3" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.1" + +util@^0.12.0: + version "0.12.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" + integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= + +uuid@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + +web3-bzz@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.5.3.tgz#e36456905ce051138f9c3ce3623cbc73da088c2b" + integrity sha512-SlIkAqG0eS6cBS9Q2eBOTI1XFzqh83RqGJWnyrNZMDxUwsTVHL+zNnaPShVPvrWQA1Ub5b0bx1Kc5+qJVxsTJg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + +web3-core-helpers@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.5.3.tgz#099030235c477aadf39a94199ef40092151d563c" + integrity sha512-Ip1IjB3S8vN7Kf1PPjK41U5gskmMk6IJQlxIVuS8/1U7n/o0jC8krqtpRwiMfAgYyw3TXwBFtxSRTvJtnLyXZw== + dependencies: + web3-eth-iban "1.5.3" + web3-utils "1.5.3" + +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-utils "1.2.11" + +web3-core-method@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.5.3.tgz#6cff97ed19fe4ea2e9183d6f703823a079f5132c" + integrity sha512-8wJrwQ2qD9ibWieF9oHXwrJsUGrv3XAtEkNeyvyNMpktNTIjxJ2jaFGQUuLiyUrMubD18XXgLk4JS6PJU4Loeg== + dependencies: + "@ethereumjs/common" "^2.4.0" + "@ethersproject/transactions" "^5.0.0-beta.135" + web3-core-helpers "1.5.3" + web3-core-promievent "1.5.3" + web3-core-subscriptions "1.5.3" + web3-utils "1.5.3" + +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + +web3-core-promievent@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.5.3.tgz#3f11833c3dc6495577c274350b61144e0a4dba01" + integrity sha512-CFfgqvk3Vk6PIAxtLLuX+pOMozxkKCY+/GdGr7weMh033mDXEPvwyVjoSRO1PqIKj668/hMGQsVoIgbyxkJ9Mg== + dependencies: + eventemitter3 "4.0.4" + +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-http "1.2.11" + web3-providers-ipc "1.2.11" + web3-providers-ws "1.2.11" + +web3-core-requestmanager@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.5.3.tgz#b339525815fd40e3a2a81813c864ddc413f7b6f7" + integrity sha512-9k/Bze2rs8ONix5IZR+hYdMNQv+ark2Ek2kVcrFgWO+LdLgZui/rn8FikPunjE+ub7x7pJaKCgVRbYFXjo3ZWg== + dependencies: + util "^0.12.0" + web3-core-helpers "1.5.3" + web3-providers-http "1.5.3" + web3-providers-ipc "1.5.3" + web3-providers-ws "1.5.3" + +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-core-subscriptions@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.5.3.tgz#d7d69c4caad65074212028656e9dc56ca5c2159d" + integrity sha512-L2m9vG1iRN6thvmv/HQwO2YLhOQlmZU8dpLG6GSo9FBN14Uch868Swk0dYVr3rFSYjZ/GETevSXU+O+vhCummA== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.5.3" + +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-requestmanager "1.2.11" + web3-utils "1.2.11" + +web3-core@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.5.3.tgz#59f8728b27c8305b349051326aa262b9b7e907bf" + integrity sha512-ACTbu8COCu+0eUNmd9pG7Q9EVsNkAg2w3Y7SqhDr+zjTgbSHZV01jXKlapm9z+G3AN/BziV3zGwudClJ4u4xXQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-core-requestmanager "1.5.3" + web3-utils "1.5.3" + +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + +web3-eth-abi@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.5.3.tgz#5aea9394d797f99ca0d9bd40c3417eb07241c96c" + integrity sha512-i/qhuFsoNrnV130CSRYX/z4SlCfSQ4mHntti5yTmmQpt70xZKYZ57BsU0R29ueSQ9/P+aQrL2t2rqkQkAloUxg== + dependencies: + "@ethersproject/abi" "5.0.7" + web3-utils "1.5.3" + +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-eth-accounts@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.5.3.tgz#076c816ff4d68c9dffebdc7fd2bfaddcfc163d77" + integrity sha512-pdGhXgeBaEJENMvRT6W9cmji3Zz/46ugFSvmnLLw79qi5EH7XJhKISNVb41eWCrs4am5GhI67GLx5d2s2a72iw== + dependencies: + "@ethereumjs/common" "^2.3.0" + "@ethereumjs/tx" "^3.2.1" + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-util "^7.0.10" + scrypt-js "^3.0.1" + uuid "3.3.2" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-utils "1.5.3" + +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-utils "1.2.11" + +web3-eth-contract@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.5.3.tgz#12b03a4a16ce583a945f874bea2ff2fb4c5b81ad" + integrity sha512-Gdlt1L6cdHe83k7SdV6xhqCytVtOZkjD0kY/15x441AuuJ4JLubCHuqu69k2Dr3tWifHYVys/vG8QE/W16syGg== + dependencies: + "@types/bn.js" "^4.11.5" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-core-promievent "1.5.3" + web3-core-subscriptions "1.5.3" + web3-eth-abi "1.5.3" + web3-utils "1.5.3" + +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-contract "1.2.11" + web3-utils "1.2.11" + +web3-eth-ens@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.5.3.tgz#ef6eee1ddf32b1ff9536fc7c599a74f2656bafe1" + integrity sha512-QmGFFtTGElg0E+3xfCIFhiUF+1imFi9eg/cdsRMUZU4F1+MZCC/ee+IAelYLfNTGsEslCqfAusliKOT9DdGGnw== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-promievent "1.5.3" + web3-eth-abi "1.5.3" + web3-eth-contract "1.5.3" + web3-utils "1.5.3" + +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + +web3-eth-iban@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.5.3.tgz#91b1475893a877b10eac1de5cce6eb379fb81b5d" + integrity sha512-vMzmGqolYZvRHwP9P4Nf6G8uYM5aTLlQu2a34vz78p0KlDC+eV1th3+90Qeaupa28EG7OO0IT1F0BejiIauOPw== + dependencies: + bn.js "^4.11.9" + web3-utils "1.5.3" + +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-eth-personal@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.5.3.tgz#4ebe09e9a77dd49d23d93b36b36cfbf4a6dae713" + integrity sha512-JzibJafR7ak/Icas8uvos3BmUNrZw1vShuNR5Cxjo+vteOC8XMqz1Vr7RH65B4bmlfb3bm9xLxetUHO894+Sew== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-net "1.5.3" + web3-utils "1.5.3" + +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-accounts "1.2.11" + web3-eth-contract "1.2.11" + web3-eth-ens "1.2.11" + web3-eth-iban "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-eth@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.5.3.tgz#d7d1ac7198f816ab8a2088c01e0bf1eda45862fe" + integrity sha512-saFurA1L23Bd7MEf7cBli6/jRdMhD4X/NaMiO2mdMMCXlPujoudlIJf+VWpRWJpsbDFdu7XJ2WHkmBYT5R3p1Q== + dependencies: + web3-core "1.5.3" + web3-core-helpers "1.5.3" + web3-core-method "1.5.3" + web3-core-subscriptions "1.5.3" + web3-eth-abi "1.5.3" + web3-eth-accounts "1.5.3" + web3-eth-contract "1.5.3" + web3-eth-ens "1.5.3" + web3-eth-iban "1.5.3" + web3-eth-personal "1.5.3" + web3-net "1.5.3" + web3-utils "1.5.3" + +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-net@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.5.3.tgz#545fee49b8e213b0c55cbe74ffd0295766057463" + integrity sha512-0W/xHIPvgVXPSdLu0iZYnpcrgNnhzHMC888uMlGP5+qMCt8VuflUZHy7tYXae9Mzsg1kxaJAS5lHVNyeNw4CoQ== + dependencies: + web3-core "1.5.3" + web3-core-method "1.5.3" + web3-utils "1.5.3" + +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + +web3-providers-http@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.5.3.tgz#74f170fc3d79eb7941d9fbc34e2a067d61ced0b2" + integrity sha512-5DpUyWGHtDAr2RYmBu34Fu+4gJuBAuNx2POeiJIooUtJ+Mu6pIx4XkONWH6V+Ez87tZAVAsFOkJRTYuzMr3rPw== + dependencies: + web3-core-helpers "1.5.3" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-providers-ipc@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.5.3.tgz#4bd7f5e445c2f3c2595fce0929c72bb879320a3f" + integrity sha512-JmeAptugVpmXI39LGxUSAymx0NOFdgpuI1hGQfIhbEAcd4sv7fhfd5D+ZU4oLHbRI8IFr4qfGU0uhR8BXhDzlg== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.5.3" + +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + +web3-providers-ws@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.5.3.tgz#eec6cfb32bb928a4106de506f13a49070a21eabf" + integrity sha512-6DhTw4Q7nm5CFYEUHOJM0gAb3xFx+9gWpVveg3YxJ/ybR1BUvEWo3bLgIJJtX56cYX0WyY6DS35a7f0LOI1kVg== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.5.3" + websocket "^1.0.32" + +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + +web3-shh@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.5.3.tgz#3c04aa4cda9ba0b746d7225262401160f8e38b13" + integrity sha512-COfEXfsqoV/BkcsNLRxQqnWc1Teb8/9GxdGag5GtPC5gQC/vsN+7hYVJUwNxY9LtJPKYTij2DHHnx6UkITng+Q== + dependencies: + web3-core "1.5.3" + web3-core-method "1.5.3" + web3-core-subscriptions "1.5.3" + web3-net "1.5.3" + +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + +web3-utils@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.5.3.tgz#e914c9320cd663b2a09a5cb920ede574043eb437" + integrity sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3-utils@^1.0.0-beta.31, web3-utils@^1.3.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.6.1.tgz#befcb23922b00603ab56d8c5b4158468dc494aca" + integrity sha512-RidGKv5kOkcerI6jQqDFDoTllQQqV+rPhTzZHhmbqtFObbYpU93uc+yG1LHivRTQhA6llIx67iudc/vzisgO+w== + dependencies: + bn.js "^4.11.9" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + dependencies: + web3-bzz "1.2.11" + web3-core "1.2.11" + web3-eth "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-shh "1.2.11" + web3-utils "1.2.11" + +web3@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.5.3.tgz#11882679453c645bf33620fbc255a243343075aa" + integrity sha512-eyBg/1K44flfv0hPjXfKvNwcUfIVDI4NX48qHQe6wd7C8nPSdbWqo9vLy6ksZIt9NLa90HjI8HsGYgnMSUxn6w== + dependencies: + web3-bzz "1.5.3" + web3-core "1.5.3" + web3-eth "1.5.3" + web3-eth-personal "1.5.3" + web3-net "1.5.3" + web3-shh "1.5.3" + web3-utils "1.5.3" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +websocket@^1.0.31, websocket@^1.0.32: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +whatwg-fetch@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which-typed-array@^1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" + integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.7" + +which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + +ws@^7.4.6: + version "7.5.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== + +xhr-request-promise@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" + integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== + dependencies: + xhr-request "^1.1.0" + +xhr-request@^1.0.1, xhr-request@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: + version "2.6.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" + integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== + dependencies: + global "~4.4.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.0" + +yargs@13.3.2, yargs@^13.3.0: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From aaaafdf15ab101e3b9b2b4dc9140a16c872ba9ce Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 13 Dec 2021 10:20:26 -0500 Subject: [PATCH 101/585] Add DepositFeed contract --- packages/contracts/contracts/DepositFeed.sol | 51 ++++ .../contracts/test/DummyContract.sol | 19 ++ packages/contracts/test/DepositFeed.ts | 217 ++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 packages/contracts/contracts/DepositFeed.sol create mode 100644 packages/contracts/contracts/test/DummyContract.sol create mode 100644 packages/contracts/test/DepositFeed.ts diff --git a/packages/contracts/contracts/DepositFeed.sol b/packages/contracts/contracts/DepositFeed.sol new file mode 100644 index 000000000000..59c7150c2be1 --- /dev/null +++ b/packages/contracts/contracts/DepositFeed.sol @@ -0,0 +1,51 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/** + * @title DepositFeed + */ +contract DepositFeed { + // Constant for address aliasing + uint160 private constant OFFSET = uint160(0x1111000000000000000000000000000000001111); + + /** + * Event with the parameters required to derive transactions on L2. + */ + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 value, + uint256 gasLimit, + bool isCreation, + bytes data + ); + + /** + * Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving + * deposit transactions. + * @param _to The L2 destination address. + * @param _gasLimit The L2 gasLimit. + * @param _isCreation Whether or not the transaction should be contract creation. + * @param _data The input data. + */ + function depositTransaction( + address _to, + uint256 _gasLimit, + bool _isCreation, + bytes memory _data + ) external payable { + if (_isCreation && _to != address(0)) { + revert("Contract creation deposits must not specify a recipient address."); + } + + address from = msg.sender; + // Transform the from-address to its alias if the caller is a contract. + if (msg.sender != tx.origin) { + unchecked { + from = address(uint160(msg.sender) + OFFSET); + } + } + + emit TransactionDeposited(from, _to, msg.value, _gasLimit, _isCreation, _data); + } +} diff --git a/packages/contracts/contracts/test/DummyContract.sol b/packages/contracts/contracts/test/DummyContract.sol new file mode 100644 index 000000000000..af6c38bde194 --- /dev/null +++ b/packages/contracts/contracts/test/DummyContract.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.10; + +/** + * For use in testing with a call from a contract rather than an EOA. + */ +contract Dummy { + /** + * Forwards a call. + * @param _target Address to call + * @param _data Data to forward + */ + function forward(address _target, bytes calldata _data) external payable { + (bool success, bytes memory ret) = _target.call{ value: msg.value }(_data); + // Silence the 'Return value of low-level calls not used' warning. + success; + ret; + } +} diff --git a/packages/contracts/test/DepositFeed.ts b/packages/contracts/test/DepositFeed.ts new file mode 100644 index 000000000000..5dc96f9cccf2 --- /dev/null +++ b/packages/contracts/test/DepositFeed.ts @@ -0,0 +1,217 @@ +import { expect } from 'chai' +import { ethers } from 'hardhat' +import { Contract, ContractFactory, Signer, BigNumber } from 'ethers' +import { applyL1ToL2Alias } from '@eth-optimism/core-utils' + +import { DepositFeed__factory, DepositFeed } from '../typechain' + +const ZERO_ADDRESS = '0x' + '00'.repeat(20) +const ZERO_BIGNUMBER = BigNumber.from(0) +const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) +const NON_ZERO_GASLIMIT = BigNumber.from(50_000) +const NON_ZERO_VALUE = BigNumber.from(100) +const NON_ZERO_DATA = '0x' + '11'.repeat(42) + +const decodeDepositEvent = async ( + depositFeed: DepositFeed +): Promise<{ + from: string + to: string + value: BigNumber + gasLimit: BigNumber + isCreation: boolean + data: string +}> => { + const events = await depositFeed.queryFilter( + depositFeed.filters.TransactionDeposited() + ) + const eventArgs = events[events.length - 1].args + + return { + from: eventArgs.from, + to: eventArgs.to, + value: eventArgs.value, + gasLimit: eventArgs.gasLimit, + isCreation: eventArgs.isCreation, + data: eventArgs.data, + } +} + +describe('DepositFeed', () => { + let signer: Signer + let signerAddress: string + let depositFeed: DepositFeed + before(async () => { + ;[signer] = await ethers.getSigners() + signerAddress = await signer.getAddress() + depositFeed = await new DepositFeed__factory(signer).deploy() + await depositFeed.deployed() + }) + it('Should revert if a contract creation has a non-zero destination address', async () => { + await expect( + depositFeed.depositTransaction( + NON_ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + true, + '0x' + ) + ).to.be.revertedWith( + 'Contract creation deposits must not specify a recipient address.' + ) + }) + + describe('Should emit the correct log values...', async () => { + it('when an EOA deposits a transaction with 0 value.', async () => { + await depositFeed.depositTransaction( + ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ) + + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(eventArgs).to.deep.equal({ + from: signerAddress, + to: ZERO_ADDRESS, + value: ZERO_BIGNUMBER, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: false, + data: NON_ZERO_DATA, + }) + }) + + it('when an EOA deposits a contract creation with 0 value.', async () => { + await depositFeed.depositTransaction( + ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ) + + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(eventArgs).to.deep.equal({ + from: signerAddress, + to: ZERO_ADDRESS, + value: ZERO_BIGNUMBER, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: true, + data: NON_ZERO_DATA, + }) + }) + + it('when a contract deposits a contract creation with 0 value.', async () => { + // Deploy a dummy contract so we can impersonate it + const dummy = await (await ethers.getContractFactory('Dummy')).deploy() + await dummy.deployed() + + await dummy.forward( + depositFeed.address, + depositFeed.interface.encodeFunctionData('depositTransaction', [ + ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA, + ]) + ) + + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(eventArgs).to.deep.equal({ + from: applyL1ToL2Alias(dummy.address), + to: ZERO_ADDRESS, + value: ZERO_BIGNUMBER, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: true, + data: NON_ZERO_DATA, + }) + }) + describe('and increase its eth balance...', async () => { + it('when an EOA deposits a transaction with an ETH value.', async () => { + const balBefore = await ethers.provider.getBalance(depositFeed.address) + await depositFeed.depositTransaction( + NON_ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + false, + '0x', + { + value: NON_ZERO_VALUE, + } + ) + const balAfter = await ethers.provider.getBalance(depositFeed.address) + + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(balAfter.sub(balBefore)).to.equal(NON_ZERO_VALUE) + expect(eventArgs).to.deep.equal({ + from: signerAddress, + to: NON_ZERO_ADDRESS, + value: NON_ZERO_VALUE, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: false, + data: '0x', + }) + }) + + it('when an EOA deposits a contract creation with an ETH value.', async () => { + const balBefore = await ethers.provider.getBalance(depositFeed.address) + await depositFeed.depositTransaction( + ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + true, + '0x', + { + value: NON_ZERO_VALUE, + } + ) + + const balAfter = await ethers.provider.getBalance(depositFeed.address) + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(balAfter.sub(balBefore)).to.equal(NON_ZERO_VALUE) + expect(eventArgs).to.deep.equal({ + from: signerAddress, + to: ZERO_ADDRESS, + value: NON_ZERO_VALUE, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: true, + data: '0x', + }) + }) + + it('when a contract deposits a contract creation with an ETH value.', async () => { + // Deploy a dummy contract so we can impersonate it + const dummy = await (await ethers.getContractFactory('Dummy')).deploy() + await dummy.deployed() + + const balBefore = await ethers.provider.getBalance(depositFeed.address) + await dummy.forward( + depositFeed.address, + depositFeed.interface.encodeFunctionData('depositTransaction', [ + ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA, + ]), + { + value: NON_ZERO_VALUE, + } + ) + + const balAfter = await ethers.provider.getBalance(depositFeed.address) + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(balAfter.sub(balBefore)).to.equal(NON_ZERO_VALUE) + expect(eventArgs).to.deep.equal({ + from: applyL1ToL2Alias(dummy.address), + to: ZERO_ADDRESS, + value: NON_ZERO_VALUE, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: true, + data: NON_ZERO_DATA, + }) + }) + }) + }) +}) From 995893c6b4c3044e354e49b67166a528eed63362 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 13 Dec 2021 14:53:48 -0500 Subject: [PATCH 102/585] Update deposit specs Moves the lengthy, not-quite compilable solidity from markdown into a complete reference implementation in the contracts package --- deposits.md | 53 ++++++++--------------------------------------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/deposits.md b/deposits.md index ca544e07abb5..7fa9c3860b53 100644 --- a/deposits.md +++ b/deposits.md @@ -168,7 +168,7 @@ L1 transaction deposits are [deposit transactions][deposit-transaction-type] gen corresponding `TransactionDeposited` event emitted by the [deposit feed contract][deposit-feed-contract] on L1. -1. `from` is unchanged from the emitted value (though it may have been transformed to an in +1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in the deposit feed contract). 2. `to` may be either: 1. any 20-byte address (including the zero-address) @@ -189,53 +189,10 @@ The deposit feed handles two special cases: 1. A contract creation deposit, which is indicated by setting the `isCreation` flag to `true`. In the event that the `to` address is non-zero, the contract will revert. -2. A call from a contract account, in which case the `from` value is transformed to its L2 . +2. A call from a contract account, in which case the `from` value is transformed to its L2 [alias][address-aliasing]. > **TODO** Define if/how ETH withdrawals occur. -A solidity-like pseudocode implementation demonstrates the functionality: - -```solidity -contract DepositFeed { - - event TransactionDeposited( - address indexed from, - address indexed to, - uint256 value, - uint256 gasLimit, - bool isCreation, - bytes _data - ); - - function depositTransaction( - address to, - uint256 value, - uint256 gasLimit, - bool isCreation, - bytes memory _data - ) external payable { - address from; - if (msg.sender == tx.origin) { - from = msg.sender; - } else { - from = msg.sender + 0x1111000000000000000000000000000000001111; - } - - if(isCreation && _to != address(0)) { - revert('Contract creation deposits must not specify a recipient address.'); - } else { - emit TransactionDeposited( - msg.sender, - to, - msg.value, - isCreation, - initCode - ); - } - } -} -``` - #### Address aliasing [address-aliasing]: #address-aliasing @@ -245,3 +202,9 @@ If the caller is not a contract, the address will be ed by adding has the same address as a contract on L2 but doesn't have the same code. We can safely ignore this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes it possible for users to interact with contracts on L2 even when the Sequencer is down. + +#### Reference Implementation + +A reference implementation of the Deposit Feed contract can be found in [DepositFeed.sol]. + +[DepositFeed.sol]: /packages/contracts/contracts/DepositFeed.sol From 710336e7ad58dbf0ffa76a594e426fbe2ce62bcd Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 22 Dec 2021 15:30:25 -0500 Subject: [PATCH 103/585] Move specs into subdir --- deposits.md => specs/deposits.md | 0 exec-engine.md => specs/exec-engine.md | 0 glossary.md => specs/glossary.md | 0 rollup-node.md => specs/rollup-node.md | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename deposits.md => specs/deposits.md (100%) rename exec-engine.md => specs/exec-engine.md (100%) rename glossary.md => specs/glossary.md (100%) rename rollup-node.md => specs/rollup-node.md (100%) diff --git a/deposits.md b/specs/deposits.md similarity index 100% rename from deposits.md rename to specs/deposits.md diff --git a/exec-engine.md b/specs/exec-engine.md similarity index 100% rename from exec-engine.md rename to specs/exec-engine.md diff --git a/glossary.md b/specs/glossary.md similarity index 100% rename from glossary.md rename to specs/glossary.md diff --git a/rollup-node.md b/specs/rollup-node.md similarity index 100% rename from rollup-node.md rename to specs/rollup-node.md From 445a9836c7cfb3dfc722fa6cd8794bb92f881d89 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 21 Dec 2021 08:37:50 -0500 Subject: [PATCH 104/585] Only lint specs package --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5269996b2270..976789013dd6 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "scripts": { "lint": "yarn lint:fix && yarn lint:check", - "lint:fix": "markdownlint-cli2-fix \"**/*.md\" \"#node_modules\"", - "lint:check": "markdownlint-cli2 \"**/*.md\" \"#node_modules\"" + "lint:fix": "markdownlint-cli2-fix \"./specs/**/*.md\" \"#node_modules\"", + "lint:check": "markdownlint-cli2 \"./specs/**/*.md\" \"#node_modules\"" } } From 45ff4b6caaf18c0c8dc1936d1765905dab43c1a9 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 20 Dec 2021 22:11:22 -0500 Subject: [PATCH 105/585] Add L1Block values contract --- .../contracts/{ => L1}/DepositFeed.sol | 0 packages/contracts/contracts/L2/L1Block.sol | 31 ++++++++++ .../DepositFeed.spec.ts} | 2 +- packages/contracts/test/L2/L1Block.spec.ts | 60 +++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) rename packages/contracts/contracts/{ => L1}/DepositFeed.sol (100%) create mode 100644 packages/contracts/contracts/L2/L1Block.sol rename packages/contracts/test/{DepositFeed.ts => L1/DepositFeed.spec.ts} (98%) create mode 100644 packages/contracts/test/L2/L1Block.spec.ts diff --git a/packages/contracts/contracts/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol similarity index 100% rename from packages/contracts/contracts/DepositFeed.sol rename to packages/contracts/contracts/L1/DepositFeed.sol diff --git a/packages/contracts/contracts/L2/L1Block.sol b/packages/contracts/contracts/L2/L1Block.sol new file mode 100644 index 000000000000..6a5dcd6c4c61 --- /dev/null +++ b/packages/contracts/contracts/L2/L1Block.sol @@ -0,0 +1,31 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/** + * @title L1Block + */ +contract L1Block { + address constant depositorAccount = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; + + uint256 public number; + uint256 public timestamp; + uint256 public basefee; + bytes32 public hash; + + function setL1BlockValues( + uint256 _number, + uint256 _timestamp, + uint256 _basefee, + bytes32 _hash + ) external { + require( + msg.sender == depositorAccount, + "Only callable by L1 Attributes Depositor Account" + ); + + number = _number; + timestamp = _timestamp; + basefee = _basefee; + hash = _hash; + } +} \ No newline at end of file diff --git a/packages/contracts/test/DepositFeed.ts b/packages/contracts/test/L1/DepositFeed.spec.ts similarity index 98% rename from packages/contracts/test/DepositFeed.ts rename to packages/contracts/test/L1/DepositFeed.spec.ts index 5dc96f9cccf2..024720afb96f 100644 --- a/packages/contracts/test/DepositFeed.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -3,7 +3,7 @@ import { ethers } from 'hardhat' import { Contract, ContractFactory, Signer, BigNumber } from 'ethers' import { applyL1ToL2Alias } from '@eth-optimism/core-utils' -import { DepositFeed__factory, DepositFeed } from '../typechain' +import { DepositFeed__factory, DepositFeed } from '../../typechain' const ZERO_ADDRESS = '0x' + '00'.repeat(20) const ZERO_BIGNUMBER = BigNumber.from(0) diff --git a/packages/contracts/test/L2/L1Block.spec.ts b/packages/contracts/test/L2/L1Block.spec.ts new file mode 100644 index 000000000000..edd7fffa23e5 --- /dev/null +++ b/packages/contracts/test/L2/L1Block.spec.ts @@ -0,0 +1,60 @@ +import { expect } from 'chai' +import { ethers } from 'hardhat' +import { Signer } from 'ethers' + +import { L1Block__factory, L1Block } from '../../typechain' + +const DEPOSITOR_ACCOUNT = '0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001' +const NON_ZERO_HASH = '0x' + 'ab'.repeat(32) + +describe('L1Block contract', () => { + let signer: Signer + let signerAddress: string + let l1Block: L1Block + let depositor: Signer + before(async () => { + ;[signer] = await ethers.getSigners() + signerAddress = await signer.getAddress() + l1Block = await new L1Block__factory(signer).deploy() + await l1Block.deployed() + + depositor = await ethers.getSigner(DEPOSITOR_ACCOUNT) + + }) + + it('setL1BlockValues: Should revert if not called by L1 Attributes Depositor Account', async () => { + + }) + + describe('Should return the correct block values for:', async () => { + before(async () => { + await ethers.provider.send('hardhat_impersonateAccount', [ + DEPOSITOR_ACCOUNT + ]) + await ethers.provider.send('hardhat_setBalance', [ + DEPOSITOR_ACCOUNT, '0xFFFFFFFFFFFF' + ]) + await l1Block.connect(depositor).setL1BlockValues(1, 2, 3, NON_ZERO_HASH) + await ethers.provider.send('hardhat_stopImpersonatingAccount', [ + DEPOSITOR_ACCOUNT + ]) + l1Block.connect(signer) + }) + + it('number', async () => { + expect(await l1Block.number()).to.equal(1) + }) + + it('timestamp', async () => { + expect(await l1Block.timestamp()).to.equal(2) + }) + + it('basefee', async () => { + expect(await l1Block.basefee()).to.equal(3) + }) + + it('hash', async () => { + expect(await l1Block.hash()).to.equal(NON_ZERO_HASH) + }) + }) +}) From fa3397bd4dbfb5d73f7be66f7766b587e066ec05 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 22 Dec 2021 13:54:55 -0500 Subject: [PATCH 106/585] Move L1Block attributes contract ref-impl out of specs Moves the reference implementation --- specs/deposits.md | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 7fa9c3860b53..64020ff67264 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -142,22 +142,17 @@ The contract has the following solidity interface, and can be interacted with ac [ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html -```solidity -interface L1BlockValues { - - function setL1BlockValues( - uint256 number, - uint256 timestamp, - uint256 baseFee, - bytes32 hash - ) external; - - function l1Number() view; - function l1Timestamp() view; - function l1BaseFee() view; - function l1Hash() view; -} -``` +#### Reference Implementation + +A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. + +[L1Block.sol]: /packages/contracts/contracts/L1Block.sol + +The bytecode to add to the genesis file will be located in the `deployedBytecode` of the +[JSON artifact file][l1-block-artifacts] corresponding to L1Block.sol. + +[l1-block-artifacts]: /packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json + ## L1 Transaction Deposits From 024d43f762c21dab4d1b256d8c784a97ffd81955 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 22 Dec 2021 15:40:31 -0500 Subject: [PATCH 107/585] Fix markdown header naming collision --- specs/deposits.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 64020ff67264..b23f9339f18e 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -142,7 +142,7 @@ The contract has the following solidity interface, and can be interacted with ac [ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html -#### Reference Implementation +#### L1 Attributes: Reference Implementation A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. @@ -153,7 +153,6 @@ The bytecode to add to the genesis file will be located in the `deployedBytecode [l1-block-artifacts]: /packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json - ## L1 Transaction Deposits [l1-transaction-deposits]: #l1-transaction-deposits @@ -198,7 +197,7 @@ has the same address as a contract on L2 but doesn't have the same code. We can this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes it possible for users to interact with contracts on L2 even when the Sequencer is down. -#### Reference Implementation +#### Deposit Feed: Reference Implementation A reference implementation of the Deposit Feed contract can be found in [DepositFeed.sol]. From f0aadd853b4c30301d10fc20c04b5193db145b85 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 22 Dec 2021 10:20:46 -0500 Subject: [PATCH 108/585] Split 'value' into 'depositValue' and 'sendValue' --- .../contracts/contracts/L1/DepositFeed.sol | 7 ++-- .../contracts/test/L1/DepositFeed.spec.ts | 32 ++++++++++++++----- specs/deposits.md | 31 ++++++++++-------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index 59c7150c2be1..132cf83ddd23 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -14,7 +14,8 @@ contract DepositFeed { event TransactionDeposited( address indexed from, address indexed to, - uint256 value, + uint256 depositValue, + uint256 sendValue, uint256 gasLimit, bool isCreation, bytes data @@ -24,12 +25,14 @@ contract DepositFeed { * Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving * deposit transactions. * @param _to The L2 destination address. + * @param _sendValue The ETH value to send in the deposit transaction. * @param _gasLimit The L2 gasLimit. * @param _isCreation Whether or not the transaction should be contract creation. * @param _data The input data. */ function depositTransaction( address _to, + uint256 _sendValue, uint256 _gasLimit, bool _isCreation, bytes memory _data @@ -46,6 +49,6 @@ contract DepositFeed { } } - emit TransactionDeposited(from, _to, msg.value, _gasLimit, _isCreation, _data); + emit TransactionDeposited(from, _to, msg.value, _sendValue, _gasLimit, _isCreation, _data); } } diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index 024720afb96f..b6578f9d9d27 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -17,7 +17,8 @@ const decodeDepositEvent = async ( ): Promise<{ from: string to: string - value: BigNumber + depositValue: BigNumber + sendValue: BigNumber gasLimit: BigNumber isCreation: boolean data: string @@ -30,7 +31,8 @@ const decodeDepositEvent = async ( return { from: eventArgs.from, to: eventArgs.to, - value: eventArgs.value, + depositValue: eventArgs.depositValue, + sendValue: eventArgs.sendValue, gasLimit: eventArgs.gasLimit, isCreation: eventArgs.isCreation, data: eventArgs.data, @@ -51,6 +53,7 @@ describe('DepositFeed', () => { await expect( depositFeed.depositTransaction( NON_ZERO_ADDRESS, + NON_ZERO_VALUE, NON_ZERO_GASLIMIT, true, '0x' @@ -64,6 +67,7 @@ describe('DepositFeed', () => { it('when an EOA deposits a transaction with 0 value.', async () => { await depositFeed.depositTransaction( ZERO_ADDRESS, + ZERO_BIGNUMBER, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA @@ -74,7 +78,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: ZERO_ADDRESS, - value: ZERO_BIGNUMBER, + depositValue: ZERO_BIGNUMBER, + sendValue: ZERO_BIGNUMBER, gasLimit: NON_ZERO_GASLIMIT, isCreation: false, data: NON_ZERO_DATA, @@ -84,6 +89,7 @@ describe('DepositFeed', () => { it('when an EOA deposits a contract creation with 0 value.', async () => { await depositFeed.depositTransaction( ZERO_ADDRESS, + ZERO_BIGNUMBER, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA @@ -94,7 +100,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: ZERO_ADDRESS, - value: ZERO_BIGNUMBER, + sendValue: ZERO_BIGNUMBER, + depositValue: ZERO_BIGNUMBER, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: NON_ZERO_DATA, @@ -110,6 +117,7 @@ describe('DepositFeed', () => { depositFeed.address, depositFeed.interface.encodeFunctionData('depositTransaction', [ ZERO_ADDRESS, + ZERO_BIGNUMBER, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA, @@ -121,17 +129,20 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: applyL1ToL2Alias(dummy.address), to: ZERO_ADDRESS, - value: ZERO_BIGNUMBER, + sendValue: ZERO_BIGNUMBER, + depositValue: ZERO_BIGNUMBER, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: NON_ZERO_DATA, }) }) + describe('and increase its eth balance...', async () => { it('when an EOA deposits a transaction with an ETH value.', async () => { const balBefore = await ethers.provider.getBalance(depositFeed.address) await depositFeed.depositTransaction( NON_ZERO_ADDRESS, + ZERO_BIGNUMBER, NON_ZERO_GASLIMIT, false, '0x', @@ -147,7 +158,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: NON_ZERO_ADDRESS, - value: NON_ZERO_VALUE, + sendValue: ZERO_BIGNUMBER, + depositValue: NON_ZERO_VALUE, gasLimit: NON_ZERO_GASLIMIT, isCreation: false, data: '0x', @@ -158,6 +170,7 @@ describe('DepositFeed', () => { const balBefore = await ethers.provider.getBalance(depositFeed.address) await depositFeed.depositTransaction( ZERO_ADDRESS, + ZERO_BIGNUMBER, NON_ZERO_GASLIMIT, true, '0x', @@ -173,7 +186,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: ZERO_ADDRESS, - value: NON_ZERO_VALUE, + sendValue: ZERO_BIGNUMBER, + depositValue: NON_ZERO_VALUE, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: '0x', @@ -190,6 +204,7 @@ describe('DepositFeed', () => { depositFeed.address, depositFeed.interface.encodeFunctionData('depositTransaction', [ ZERO_ADDRESS, + ZERO_BIGNUMBER, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA, @@ -206,7 +221,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: applyL1ToL2Alias(dummy.address), to: ZERO_ADDRESS, - value: NON_ZERO_VALUE, + sendValue: ZERO_BIGNUMBER, + depositValue: NON_ZERO_VALUE, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: NON_ZERO_DATA, diff --git a/specs/deposits.md b/specs/deposits.md index b23f9339f18e..d21f13bb9576 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -23,11 +23,12 @@ fields (rlp encoded in the order they appear here): [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -- `address from` -- `address to` -- `uint256 value` -- `bytes data` -- `uint256 gasLimit` +- `address from`: The address of the sender account. +- `address to`: The address of the recipient account. +- `uint256 depositValue`: The ETH value to mint on L2. +- `uint256 sendValue`: The ETH value to send to the recipient account. +- `bytes data`: The input data. +- `uint256 gasLimit`: The gasLimit for the L2 transaction. In contrast to [EIP-155] transactions, this transaction type does not include signature information, and makes the `from` address explicit. @@ -69,7 +70,7 @@ using the correct derivation algorithm, the resulting state transition would be In order to execute a deposit transaction: -First, the balance of the `from` account MUST be increased by the amount of `value`. +First, the balance of the `from` account MUST be increased by the amount of `depositValue`. Then, the execution environment for a deposit transaction is initialized based on the transaction's values, in exactly the same manner as it would be for an EIP-155 transaction. @@ -82,7 +83,7 @@ follows: [aliased][address-aliasing] by the deposit feed contract). - `context.calldata` set to `data` - `context.gas` set to `gasLimit` -- `context.value` set to `value` +- `context.value` set to `sendValue` #### Nonce handling @@ -106,11 +107,14 @@ This transaction MUST have the following values: [L1 Attributes depositor account][depositor-account]) 2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 attributes predeploy contract). -3. `value` is `0` -4. `gasLimit` is set to the maximum available. -5. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's `setL1BlockValues()` +3. `depositValue` is `0` +4. `sendValue` is `0` +5. `gasLimit` is set to the maximum available. +6. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's `setL1BlockValues()` function with correct values associated with the corresponding L1 block. + + ## Special Accounts on L2 The L1 attributes deposit transaction involves two special purpose accounts: @@ -167,9 +171,10 @@ contract][deposit-feed-contract] on L1. 2. `to` may be either: 1. any 20-byte address (including the zero-address) 2. `null` in which case a contract is created. -3. `value` is unchanged from the emitted value. -4. `gaslimit` is unchanged from the emitted value. -5. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as +3. `depositValue` is set to the emitted value. +4. `sendValue` is set to the emitted value. +5. `gaslimit` is unchanged from the emitted value. +6. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as either calldata or initialization code depending on the value of `to`. ### Deposit Feed Contract From 879cc0cc178120087e85aff417b4f0a11a05ee7d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 23 Dec 2021 12:29:59 -0500 Subject: [PATCH 109/585] Rename sendValue -> value, depositValue -> mint --- .../contracts/contracts/L1/DepositFeed.sol | 10 +++--- .../contracts/test/L1/DepositFeed.spec.ts | 32 +++++++++---------- specs/deposits.md | 14 ++++---- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index 132cf83ddd23..c4d92546ef71 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -14,8 +14,8 @@ contract DepositFeed { event TransactionDeposited( address indexed from, address indexed to, - uint256 depositValue, - uint256 sendValue, + uint256 mint, + uint256 value, uint256 gasLimit, bool isCreation, bytes data @@ -25,14 +25,14 @@ contract DepositFeed { * Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving * deposit transactions. * @param _to The L2 destination address. - * @param _sendValue The ETH value to send in the deposit transaction. + * @param _value The ETH value to send in the deposit transaction. * @param _gasLimit The L2 gasLimit. * @param _isCreation Whether or not the transaction should be contract creation. * @param _data The input data. */ function depositTransaction( address _to, - uint256 _sendValue, + uint256 _value, uint256 _gasLimit, bool _isCreation, bytes memory _data @@ -49,6 +49,6 @@ contract DepositFeed { } } - emit TransactionDeposited(from, _to, msg.value, _sendValue, _gasLimit, _isCreation, _data); + emit TransactionDeposited(from, _to, msg.value, _value, _gasLimit, _isCreation, _data); } } diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index b6578f9d9d27..a1c4a8be3222 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -17,8 +17,8 @@ const decodeDepositEvent = async ( ): Promise<{ from: string to: string - depositValue: BigNumber - sendValue: BigNumber + mint: BigNumber + value: BigNumber gasLimit: BigNumber isCreation: boolean data: string @@ -31,8 +31,8 @@ const decodeDepositEvent = async ( return { from: eventArgs.from, to: eventArgs.to, - depositValue: eventArgs.depositValue, - sendValue: eventArgs.sendValue, + mint: eventArgs.mint, + value: eventArgs.value, gasLimit: eventArgs.gasLimit, isCreation: eventArgs.isCreation, data: eventArgs.data, @@ -78,8 +78,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: ZERO_ADDRESS, - depositValue: ZERO_BIGNUMBER, - sendValue: ZERO_BIGNUMBER, + mint: ZERO_BIGNUMBER, + value: ZERO_BIGNUMBER, gasLimit: NON_ZERO_GASLIMIT, isCreation: false, data: NON_ZERO_DATA, @@ -100,8 +100,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: ZERO_ADDRESS, - sendValue: ZERO_BIGNUMBER, - depositValue: ZERO_BIGNUMBER, + value: ZERO_BIGNUMBER, + mint: ZERO_BIGNUMBER, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: NON_ZERO_DATA, @@ -129,8 +129,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: applyL1ToL2Alias(dummy.address), to: ZERO_ADDRESS, - sendValue: ZERO_BIGNUMBER, - depositValue: ZERO_BIGNUMBER, + value: ZERO_BIGNUMBER, + mint: ZERO_BIGNUMBER, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: NON_ZERO_DATA, @@ -158,8 +158,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: NON_ZERO_ADDRESS, - sendValue: ZERO_BIGNUMBER, - depositValue: NON_ZERO_VALUE, + value: ZERO_BIGNUMBER, + mint: NON_ZERO_VALUE, gasLimit: NON_ZERO_GASLIMIT, isCreation: false, data: '0x', @@ -186,8 +186,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, to: ZERO_ADDRESS, - sendValue: ZERO_BIGNUMBER, - depositValue: NON_ZERO_VALUE, + value: ZERO_BIGNUMBER, + mint: NON_ZERO_VALUE, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: '0x', @@ -221,8 +221,8 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: applyL1ToL2Alias(dummy.address), to: ZERO_ADDRESS, - sendValue: ZERO_BIGNUMBER, - depositValue: NON_ZERO_VALUE, + value: ZERO_BIGNUMBER, + mint: NON_ZERO_VALUE, gasLimit: NON_ZERO_GASLIMIT, isCreation: true, data: NON_ZERO_DATA, diff --git a/specs/deposits.md b/specs/deposits.md index d21f13bb9576..029d1fe38406 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -25,8 +25,8 @@ fields (rlp encoded in the order they appear here): - `address from`: The address of the sender account. - `address to`: The address of the recipient account. -- `uint256 depositValue`: The ETH value to mint on L2. -- `uint256 sendValue`: The ETH value to send to the recipient account. +- `uint256 mint`: The ETH value to mint on L2. +- `uint256 value`: The ETH value to send to the recipient account. - `bytes data`: The input data. - `uint256 gasLimit`: The gasLimit for the L2 transaction. @@ -70,7 +70,7 @@ using the correct derivation algorithm, the resulting state transition would be In order to execute a deposit transaction: -First, the balance of the `from` account MUST be increased by the amount of `depositValue`. +First, the balance of the `from` account MUST be increased by the amount of `mint`. Then, the execution environment for a deposit transaction is initialized based on the transaction's values, in exactly the same manner as it would be for an EIP-155 transaction. @@ -107,8 +107,8 @@ This transaction MUST have the following values: [L1 Attributes depositor account][depositor-account]) 2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 attributes predeploy contract). -3. `depositValue` is `0` -4. `sendValue` is `0` +3. `mint` is `0` +4. `value` is `0` 5. `gasLimit` is set to the maximum available. 6. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's `setL1BlockValues()` function with correct values associated with the corresponding L1 block. @@ -171,8 +171,8 @@ contract][deposit-feed-contract] on L1. 2. `to` may be either: 1. any 20-byte address (including the zero-address) 2. `null` in which case a contract is created. -3. `depositValue` is set to the emitted value. -4. `sendValue` is set to the emitted value. +3. `mint` is set to the emitted value. +4. `value` is set to the emitted value. 5. `gaslimit` is unchanged from the emitted value. 6. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as either calldata or initialization code depending on the value of `to`. From f34ec4909a8415ab9f9d108d34182de1c65afd21 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 23 Dec 2021 20:29:47 -0500 Subject: [PATCH 110/585] Add a build script --- packages/contracts/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 7b8be6263000..1b2174c6d207 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -9,6 +9,7 @@ }, "scripts": { "test": "hardhat test", + "build": "hardhat compile", "lint:ts:check": "eslint .", "lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol'", "lint:check": "yarn lint:contracts:check && yarn lint:ts:check", From 22c2a177f2f828848279da4d57498431200f6997 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 3 Jan 2022 15:46:32 -0500 Subject: [PATCH 111/585] Add missing auth test to L1Block spec --- packages/contracts/test/L2/L1Block.spec.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/contracts/test/L2/L1Block.spec.ts b/packages/contracts/test/L2/L1Block.spec.ts index edd7fffa23e5..8b68a8a71cbe 100644 --- a/packages/contracts/test/L2/L1Block.spec.ts +++ b/packages/contracts/test/L2/L1Block.spec.ts @@ -23,7 +23,11 @@ describe('L1Block contract', () => { }) it('setL1BlockValues: Should revert if not called by L1 Attributes Depositor Account', async () => { - + await expect( + l1Block.connect(signer).setL1BlockValues(1, 2, 3, NON_ZERO_HASH) + ).to.be.revertedWith( + 'Only callable by L1 Attributes Depositor Account' + ) }) describe('Should return the correct block values for:', async () => { From 271ee82589c0f614e65d9911eede94454797edef Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 3 Jan 2022 15:53:57 -0500 Subject: [PATCH 112/585] fix formatting --- packages/contracts/contracts/L2/L1Block.sol | 42 ++++++++++----------- packages/contracts/test/L2/L1Block.spec.ts | 12 +++--- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/packages/contracts/contracts/L2/L1Block.sol b/packages/contracts/contracts/L2/L1Block.sol index 6a5dcd6c4c61..6f898d871936 100644 --- a/packages/contracts/contracts/L2/L1Block.sol +++ b/packages/contracts/contracts/L2/L1Block.sol @@ -5,27 +5,27 @@ pragma solidity 0.8.10; * @title L1Block */ contract L1Block { - address constant depositorAccount = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; + address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; - uint256 public number; - uint256 public timestamp; - uint256 public basefee; - bytes32 public hash; + uint256 public number; + uint256 public timestamp; + uint256 public basefee; + bytes32 public hash; - function setL1BlockValues( - uint256 _number, - uint256 _timestamp, - uint256 _basefee, - bytes32 _hash - ) external { - require( - msg.sender == depositorAccount, - "Only callable by L1 Attributes Depositor Account" - ); + function setL1BlockValues( + uint256 _number, + uint256 _timestamp, + uint256 _basefee, + bytes32 _hash + ) external { + require( + msg.sender == DEPOSITOR_ACCOUNT, + "Only callable by L1 Attributes Depositor Account" + ); - number = _number; - timestamp = _timestamp; - basefee = _basefee; - hash = _hash; - } -} \ No newline at end of file + number = _number; + timestamp = _timestamp; + basefee = _basefee; + hash = _hash; + } +} diff --git a/packages/contracts/test/L2/L1Block.spec.ts b/packages/contracts/test/L2/L1Block.spec.ts index 8b68a8a71cbe..7d5814644ba6 100644 --- a/packages/contracts/test/L2/L1Block.spec.ts +++ b/packages/contracts/test/L2/L1Block.spec.ts @@ -19,28 +19,26 @@ describe('L1Block contract', () => { await l1Block.deployed() depositor = await ethers.getSigner(DEPOSITOR_ACCOUNT) - }) it('setL1BlockValues: Should revert if not called by L1 Attributes Depositor Account', async () => { await expect( l1Block.connect(signer).setL1BlockValues(1, 2, 3, NON_ZERO_HASH) - ).to.be.revertedWith( - 'Only callable by L1 Attributes Depositor Account' - ) + ).to.be.revertedWith('Only callable by L1 Attributes Depositor Account') }) describe('Should return the correct block values for:', async () => { before(async () => { await ethers.provider.send('hardhat_impersonateAccount', [ - DEPOSITOR_ACCOUNT + DEPOSITOR_ACCOUNT, ]) await ethers.provider.send('hardhat_setBalance', [ - DEPOSITOR_ACCOUNT, '0xFFFFFFFFFFFF' + DEPOSITOR_ACCOUNT, + '0xFFFFFFFFFFFF', ]) await l1Block.connect(depositor).setL1BlockValues(1, 2, 3, NON_ZERO_HASH) await ethers.provider.send('hardhat_stopImpersonatingAccount', [ - DEPOSITOR_ACCOUNT + DEPOSITOR_ACCOUNT, ]) l1Block.connect(signer) }) From aa85c4768c385ea350febfda4ca0c9791462eaea Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 3 Jan 2022 16:01:43 -0500 Subject: [PATCH 113/585] Use custom errors in L1Block contract --- packages/contracts/contracts/L2/L1Block.sol | 12 ++++++++---- packages/contracts/test/L2/L1Block.spec.ts | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/contracts/contracts/L2/L1Block.sol b/packages/contracts/contracts/L2/L1Block.sol index 6f898d871936..0b593463af30 100644 --- a/packages/contracts/contracts/L2/L1Block.sol +++ b/packages/contracts/contracts/L2/L1Block.sol @@ -5,6 +5,11 @@ pragma solidity 0.8.10; * @title L1Block */ contract L1Block { + /** + * Only the Depositor account may call setL1BlockValues(). + */ + error OnlyDepositor(); + address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; uint256 public number; @@ -18,10 +23,9 @@ contract L1Block { uint256 _basefee, bytes32 _hash ) external { - require( - msg.sender == DEPOSITOR_ACCOUNT, - "Only callable by L1 Attributes Depositor Account" - ); + if (msg.sender != DEPOSITOR_ACCOUNT) { + revert OnlyDepositor(); + } number = _number; timestamp = _timestamp; diff --git a/packages/contracts/test/L2/L1Block.spec.ts b/packages/contracts/test/L2/L1Block.spec.ts index 7d5814644ba6..4e029c186645 100644 --- a/packages/contracts/test/L2/L1Block.spec.ts +++ b/packages/contracts/test/L2/L1Block.spec.ts @@ -24,7 +24,7 @@ describe('L1Block contract', () => { it('setL1BlockValues: Should revert if not called by L1 Attributes Depositor Account', async () => { await expect( l1Block.connect(signer).setL1BlockValues(1, 2, 3, NON_ZERO_HASH) - ).to.be.revertedWith('Only callable by L1 Attributes Depositor Account') + ).to.be.revertedWith('OnlyDepositor()') }) describe('Should return the correct block values for:', async () => { From f54d0824d61080767d1762970ebed69bc53a5114 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 3 Jan 2022 16:05:40 -0500 Subject: [PATCH 114/585] User custom errors in DepositFeed contract --- packages/contracts/contracts/L1/DepositFeed.sol | 7 ++++++- packages/contracts/test/L1/DepositFeed.spec.ts | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index c4d92546ef71..023c5cffcd77 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -5,6 +5,11 @@ pragma solidity 0.8.10; * @title DepositFeed */ contract DepositFeed { + /** + * Deposits which create a new contract must set the recipient to address(0). + */ + error NonZeroCreationTarget(); + // Constant for address aliasing uint160 private constant OFFSET = uint160(0x1111000000000000000000000000000000001111); @@ -38,7 +43,7 @@ contract DepositFeed { bytes memory _data ) external payable { if (_isCreation && _to != address(0)) { - revert("Contract creation deposits must not specify a recipient address."); + revert NonZeroCreationTarget(); } address from = msg.sender; diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index a1c4a8be3222..665fce2d4e93 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -58,9 +58,7 @@ describe('DepositFeed', () => { true, '0x' ) - ).to.be.revertedWith( - 'Contract creation deposits must not specify a recipient address.' - ) + ).to.be.revertedWith('NonZeroCreationTarget()') }) describe('Should emit the correct log values...', async () => { From 3fba61b48ab434b694007b6dec73ef500a2a41b8 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 6 Jan 2022 16:01:44 +0100 Subject: [PATCH 115/585] s/Optimistic Ethereum/Optimism --- README.md | 8 ++++---- specs/glossary.md | 8 ++++---- specs/rollup-node.md | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 78cc7ec6b321..d0a2e56fb553 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# The Optimistic Ethereum Spec +# The Optimism Spec This repository holds the work-in-progress specification for the next version of -Optimistic Ethereum. +Optimism. This spec is developped iteratively, specifying a rollup of increasing complexity. The current stage specifies a "rollup" whose only transactions are @@ -18,7 +18,7 @@ Please note that this specification is currently under heavy construction. ### Basic Contributions -Contributing to the Optimistic Ethereum specification is easy. +Contributing to the Optimism specification is easy. You'll find a list of open questions and active research topics over on the [Discussions] page for this repo. Specific tasks and TODOs can be found on the @@ -32,7 +32,7 @@ request]. ### R&D Calls We hold bi-weekly R&D calls that are open to anyone interested in contributing -to the Optimistic Ethereum spec. +to the Optimism spec. Contact [@karlfloersch], [@protolambda], [@kelvinfichter] or [@norswap] if you'd like to join these calls. Please note that these calls may be recorded and diff --git a/specs/glossary.md b/specs/glossary.md index 3abbd5e06ae0..05795ed35d5e 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -34,13 +34,13 @@ [L1]: /glossary.md#layer-1-L1 -Refers the Ethereum blockchain, used in contrast to [layer 2][L2], which refers to Optimistic Ethereum. +Refers the Ethereum blockchain, used in contrast to [layer 2][L2], which refers to Optimism. ## Layer 2 (L2) [L2]: /glossary.md#layer-2-L2 -Refers to the Optimistic Ethereum blockchain (specified in this repository), used in contrast to [layer 1][L1], which +Refers to the Optimism blockchain (specified in this repository), used in contrast to [layer 1][L1], which refers to the Ethereum blockchain. ## Block @@ -88,7 +88,7 @@ L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a A contract placed in the L2 genesis state (i.e. at the start of the chain). -Optimistic Ethereum has the following predeploys: +Optimism has the following predeploys: - [L1 Attributes Predeployed Contract][l1-attr-predeploy] @@ -190,7 +190,7 @@ this term. [l1-attributes-tx]: /glossary.md#l1-attributes-transaction -A transaction with an Optimistic-Ethereum-specific transaction type, that is used to register the L1 block attributes +A transaction with an Optimism-specific transaction type, that is used to register the L1 block attributes (number, timestamp, ...) on L2. The L1 attributes for a given L1 block can be read on L2 from the [L1 Attributes Predeployed diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 4ddd91424999..90361cb8f207 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -123,7 +123,7 @@ are simply copied byte-for-byte — it is the role of the [execution engine] to > **TODO** must offer some precisions on the format of deposits: sender, > receivers both in-tx-as-encoded, and on-L2-tx. What about the fees? -The Optimistic Ethereum specific *[L1 attributes transaction]* has the following [EIP-2718]-compatible format: `0x7E || +The Optimism-specific *[L1 attributes transaction]* has the following [EIP-2718]-compatible format: `0x7E || [block_number, timestamp, basefee]` where: - `0x7E` is the transaction type identifier. @@ -154,7 +154,7 @@ deposit: [calling-exec-engine]: #building-the-L2-block-with-the-execution-engine -The Optimistic Ethereum [execution engine] is specified in the [Execution Engine Specification]. +The Optimism [execution engine] is specified in the [Execution Engine Specification]. [Execution Engine Specification]: exec-engine.md @@ -164,7 +164,7 @@ attributes] into L2 blocks. > **TODO** This section probably includes too much redundant details that will > need to be removed once the execution engine spec is up. -Optimistic Ethereum's execution engine API is built upon [Ethereum's Engine API specification][eth-engine-api], with a +Optimism's execution engine API is built upon [Ethereum's Engine API specification][eth-engine-api], with a couple of modifications. That specification builds upon [Ethereum's JSON-RPC API specification][JSON-RPC-API], which itself builds upon the [JSON-RPC specification][JSON-RPC]. From 1bf31162c8ef53736d09985bc38f2704d8a85017 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 6 Jan 2022 18:34:17 +0100 Subject: [PATCH 116/585] make rollup node spec consistent with deposit spec --- specs/deposits.md | 48 +++++++++++++++----------- specs/glossary.md | 72 +++++++++++++++++++++++++-------------- specs/rollup-node.md | 81 ++++++++++++++++++++++---------------------- 3 files changed, 117 insertions(+), 84 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 029d1fe38406..a70f7c200170 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -4,10 +4,13 @@ [transaction-type]: /glossary.md#transaction-type [derivation]: /glossary.md#L2-chain-derivation [execution-engine]: /glossary.md#execution-engine +[deposits]: /glossary.md#deposits +[L1 attributes deposit]: /glossary.md#l1-attributes-deposit +[transaction deposits]: /glossary.md#transaction-deposits -Deposits are transactions which are initiated on L1, and executed on L2. This document outlines a new -[transaction type][transaction-type] for deposits. It also describes how deposits are initiated on -L1, along with the authorization and validation conditions on L2. +[Deposits] are transactions which are initiated on L1, and executed on L2. This document outlines a +new [transaction type][transaction-type] for deposits. It also describes how deposits are initiated +on L1, along with the authorization and validation conditions on L2. ## The Deposit Transaction Type @@ -16,7 +19,8 @@ L1, along with the authorization and validation conditions on L2. Deposit transactions have the following notable distinctions from existing transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. -2. They do not include signature validation (see [L1 transaction deposits][l1-transaction-deposits] for the rationale). +2. They do not include signature validation (see [L1 transaction deposits][l1-transaction-deposits] + for the rationale). We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following fields (rlp encoded in the order they appear here): @@ -59,12 +63,13 @@ modifications to L1 client software and complexity in general. [authorization]: #validation-and-authorization-of-deposit-transaction-types As noted above, the deposit transaction type does not include a signature for validation. Rather, -authorization is handled by the [L2 chain Derivation][derivation] process, which when -correctly processed will only derive transactions with a `from` address attested to -by the logs of the [L1 deposit feed contract][deposit-feed-contract]. +authorization is handled by the [L2 chain Derivation][derivation] process, which when correctly +processed will only derive transactions with a `from` address attested to by the logs of the [L1 +deposit feed contract][deposit-feed-contract]. -In the event a deposit transaction is included which is not derived by the [execution engine][execution-engine] -using the correct derivation algorithm, the resulting state transition would be invalid. +In the event a deposit transaction is included which is not derived by the [execution +engine][execution-engine] using the correct derivation algorithm, the resulting state transition +would be invalid. ### Execution @@ -99,7 +104,8 @@ tooling (such as wallets and block explorers). [l1-attributes-deposit]: #l1-attributes-deposit -This is a deposit transaction sent to the [L1 attributes predeploy][predeploy] contract. +An [L1 attributes deposit] is a deposit transaction sent to the [L1 attributes predeploy][predeploy] +contract. This transaction MUST have the following values: @@ -110,8 +116,9 @@ This transaction MUST have the following values: 3. `mint` is `0` 4. `value` is `0` 5. `gasLimit` is set to the maximum available. -6. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's `setL1BlockValues()` - function with correct values associated with the corresponding L1 block. +6. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's + `setL1BlockValues()` function with correct values associated with the corresponding L1 block (cf. + [reference implementation][l1-attrib-ref-implem]). @@ -148,6 +155,8 @@ The contract has the following solidity interface, and can be interacted with ac #### L1 Attributes: Reference Implementation +[l1-attrib-ref-implem]: #l1-attributes--reference-implementation + A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. [L1Block.sol]: /packages/contracts/contracts/L1Block.sol @@ -161,8 +170,8 @@ The bytecode to add to the genesis file will be located in the `deployedBytecode [l1-transaction-deposits]: #l1-transaction-deposits -L1 transaction deposits are [deposit transactions][deposit-transaction-type] generated by the -[L2 Chain Derivation][derivation] process. The values of each transaction are determined by the +L1 [transaction deposits] are [deposit transactions][deposit-transaction-type] generated by the [L2 +Chain Derivation][derivation] process. The values of each transaction are determined by the corresponding `TransactionDeposited` event emitted by the [deposit feed contract][deposit-feed-contract] on L1. @@ -188,7 +197,8 @@ The deposit feed handles two special cases: 1. A contract creation deposit, which is indicated by setting the `isCreation` flag to `true`. In the event that the `to` address is non-zero, the contract will revert. -2. A call from a contract account, in which case the `from` value is transformed to its L2 [alias][address-aliasing]. +2. A call from a contract account, in which case the `from` value is transformed to its L2 + [alias][address-aliasing]. > **TODO** Define if/how ETH withdrawals occur. @@ -197,10 +207,10 @@ The deposit feed handles two special cases: [address-aliasing]: #address-aliasing If the caller is not a contract, the address will be ed by adding -`0x1111000000000000000000000000000000001111`. This prevents attacks in which a contract on L1 -has the same address as a contract on L2 but doesn't have the same code. We can safely ignore -this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also -makes it possible for users to interact with contracts on L2 even when the Sequencer is down. +`0x1111000000000000000000000000000000001111`. This prevents attacks in which a contract on L1 has +the same address as a contract on L2 but doesn't have the same code. We can safely ignore this for +EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes it +possible for users to interact with contracts on L2 even when the Sequencer is down. #### Deposit Feed: Reference Implementation diff --git a/specs/glossary.md b/specs/glossary.md index 05795ed35d5e..444b1c1e1930 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -20,9 +20,10 @@ - [L2 Chain Derivation](#l2-chain-derivation) - [L2 Derivation Inputs](#l2-derivation-inputs) - [Payload Attributes](#payload-attributes) - - [L1 Attributes Transaction](#l1-attributes-transaction) - - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - [Deposits](#deposits) + - [L1 Attributes Deposit](#l1-attributes-deposit) + - [Transaction Deposit](#transaction-deposit) + - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - [Deposit Transaction Type](#deposit-transaction-type) - [Deposit Feed Contract](#deposit-feed-contract) - [Execution Engine Concepts](#execution-engine-concepts) @@ -186,46 +187,67 @@ cf. [Execution Engine Specification](exec-engine.md) Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using this term. -## L1 Attributes Transaction +## Deposits -[l1-attributes-tx]: /glossary.md#l1-attributes-transaction +[deposits]: /glossary.md#deposits -A transaction with an Optimism-specific transaction type, that is used to register the L1 block attributes -(number, timestamp, ...) on L2. +A deposit is an L2 transaction derived from an L1 block. -The L1 attributes for a given L1 block can be read on L2 from the [L1 Attributes Predeployed -Contract][l1-attr-predeploy]. +There are two kinds of deposits: -cf. [L1 attributes transaction format](/rollup-node.md#payload-transaction-format) (in the section on [payload -attributes]) +- [L1 Attributes Deposit][l1-attribute-tx], which submit the L1 block's attributes to the [L1 Attributes Predeployed + Contract][l1-attr-predeploy]. +- [Transaction Deposits][tx-deposits], which are transaction that have been submitted on L1, via a transaction sent to +the [deposit feed contract][deposit-feed]. -> **TODO** We might want to move this the format spec to the execution engine. +While transaction deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word +*deposit* should be understood as "a transaction *deposited* to L2 from L1". -> **TODO** We might wish to make this a "normal transaction" if deposits end up -> not carrying a signature. +The term *deposit* performs the double duty of referring to both: -## L1 Attributes Predeployed Contract +1. The transaction information submitted on L1 to the [deposit feed contract][deposit-feed]. This is a kind of [L2 + derivation input][deriv-input]. +2. The actual L2 transaction derived from this L1 input. -[l1-attr-predeploy]: /glossary.md#l1-attributes-predeployed-contract +Deposits are specified in the [deposits specification][deposits-spec]. -A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given -block number or a given block hash. +[deposits-spec]: deposits.md -cf. [L1 Attributes Predeployed Contract Specification](TODO) +## L1 Attributes Deposit -> **TODO LINK** L1 attributes predeployed contract spec +[l1-attributes-deposit]: /glossary.md#l1-attributes-deposit -## Deposits +A [deposit][deposits] that is used to register the L1 block attributes (number, timestamp, ...) on L2 via a call to the +[L1 Attributes Predeployed Contract][l1-attr-predeploy]. That contract can then be used to read the the attributes of +the L1 block corresponding to the current L2 block. -[deposits]: /glossary.md#deposits +L1 attributes deposits are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the deposits +specification. + +[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposit -A deposit is an L2 transaction that has been submitted on L1, via a transaction sent to the [deposit feed +## Transaction Deposits + +[tx-deposits]: #transaction-deposits + +These [deposits] are transaction that have been submitted on L1, via a transaction sent to the [deposit feed contract][deposit-feed]. -While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be -understood as "a transaction *deposited* to L2". +Transaction deposits are specified in the [Transaction Deposits][tx-deposits-spec] section of the deposits +specification. + +[tx-deposits-spec]: deposits.md#l1-transaction-deposits + +## L1 Attributes Predeployed Contract + +[l1-attr-predeploy]: /glossary.md#l1-attributes-predeployed-contract -Deposits are one kind of [L2 derivation input][deriv-input]. +A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given +block number or a given block hash. + +cf. [L1 Attributes Predeployed Contract Specification](TODO) + +> **TODO LINK** L1 attributes predeployed contract spec ## Deposit Transaction Type diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 90361cb8f207..f886ca4b82e2 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -13,6 +13,8 @@ [deposit-feed]: /glossary.md#L2-deposit-feed-contract [L2 chain inception]: /glossary.md#L2-chain-inception [receipts]: /glossary.md#receipt +[L1 attributes deposit]: /glossary.md#l1-attributes-deposit +[transaction deposits]: /glossary.md#transaction-deposits The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their associated [receipts]). This process happens in two steps: @@ -41,11 +43,11 @@ concerned with the specification of the rollup driver. [l2-chain-derivation]: #l2-chain-derivation -This section specifies how the [rollup driver] derives one L2 block per every L1 block. The L2 block will carry the L1 -block attributes (as a *[L1 attributes transaction]*) well as all L2 transactions deposited by users in the L1 block -(*[deposits]*). +This section specifies how the [rollup driver] derives one L2 block per every L1 block. The L2 block will carry +*[deposits]*, including a single *[L1 attributes deposit]* (which carries L1 block attributes) and zero or more +*[transaction deposits]* submitted by user on L1. -[L1 attributes transaction]: /glossary.md#l1-attributes-transaction +---- ### From L1 blocks to payload attributes @@ -59,11 +61,12 @@ The rollup reads the following data from each L1 block: - timestamp - basefee - *random* (the output of the [`RANDOM` opcode][random]) -- [deposits] +- L1 log entries emitted for [transaction deposits] [random]: https://eips.ethereum.org/EIPS/eip-4399 -A deposit is an L2 transaction that has been submitted on L1, via a call to the [deposit feed contract][deposit-feed]. +A [transaction deposit][transaction deposits] is an L2 transaction that has been submitted on L1, via a call to the +[deposit feed contract][deposit-feed]. While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be understood as "a transaction *deposited* to L2". @@ -99,44 +102,38 @@ The object properties must be set as follows: rounded to the closest multiple of 2 seconds. No two blocks may have the same timestamp. - `random` is set to the *random* L1 block attribute - `suggestedFeeRecipient` is set to an address where the sequencer would like to direct the fees -- `transactions` is an array of transactions, encoded in the [EIP-2718] format (i.e. as a single byte defining the - transaction type, concatenated with an opaque byte array whose meaning depends on the type). +- `transactions` is an array containing the [L1 attributes deposit] as well as [transaction deposits], whose format is + specified in the [next section][payload-format]. -> **TODO** we need to handle non-EIP-2718 transactions too - -[unix type]: https://en.wikipedia.org/wiki/Unix_time -[merge]: https://ethereum.org/en/eth2/merge/ +[unix time]: https://en.wikipedia.org/wiki/Unix_time +[yellow paper]: https://github.com/ethereum/yellowpaper +[EIP-155]: https://eips.ethereum.org/EIPS/eip-155 +[EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 +[EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 -[encode-tx]: https://github.com/norswap/nanoeth/blob/cc5d94a349c90627024f3cd629a2d830008fec72/src/com/norswap/nanoeth/transactions/Transaction.java#L84-L130 +---- -The [EIP-2718] transactions must have a transaction type that is valid on L1, or be an *[L1 attributes transaction]* -(see below). - -#### Payload Transaction Format +### Payload Transaction Format [payload-format]: #payload-transaction-format -The `transactions` array is filled with the deposits, prefixed by the (single) [L1 attributes transaction]. The deposits -are simply copied byte-for-byte — it is the role of the [execution engine] to reject invalidly-formatted transactions. - -> **TODO** must offer some precisions on the format of deposits: sender, -> receivers both in-tx-as-encoded, and on-L2-tx. What about the fees? +The `transactions` array is filled with user-submitted deposits, prefixed by the (single) [L1 attributes deposit]. The +format for deposits is described at [the top of the deposit specification][deposit-transaction-type]. -The Optimism-specific *[L1 attributes transaction]* has the following [EIP-2718]-compatible format: `0x7E || -[block_number, timestamp, basefee]` where: +[deposit-transaction-type]: deposits.md#the-deposit-transaction-type -- `0x7E` is the transaction type identifier. -- `block_number` is the L1 block number as a 64-bit integer (4 bytes) -- `timestamp` is the L1 block timestamp as a 64-bit integer (4 bytes) -- `basefee` is the L1 block basefee as a 64-bit integer (4 bytes) +The rollup node is responsible for encoding the L1 attributes deposit based on the attributes (block number, timestamp +and basefee) of the L1 block, as specified in the [L1 Attributes Deposit][l1-attributes-deposit-spec] section of the +deposit specification. It must also encode the transaction deposits based on the `TransactionDeposited` event +emitted by the deposit contract, as specified by the [L1 Transaction Deposits][l1-transaction-deposits] section of the +same document. -When included in the `transactions` array, this transaction should be RLP-encoded in the same way as other transactions. +[l1-attributes-deposit-spec]: deposits.md#l1-attributes-deposit +[l1-transaction-deposits]: deposits.md#l1-transaction-deposits -> **TODO** move this section into a doc specific to the execution-engine - -Here is an example valid `PayloadAttributesOPV1` object, which contains an L1 attributes transaction as well as a single -deposit: +Here is an example valid `PayloadAttributesOPV1` object, which contains an L1 attributes deposit as well as a single +transaction deposit: ```js { @@ -144,12 +141,14 @@ deposit: random: "0xde5dff2b0982ecbbd38081eb8f4aed0525140dc1c1d56f995b4fa801a3f2649e", suggestedFeeRecipient: "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B", transactions: [ - "TODO specify L1 attribute transaction", + "TODO generate abi-encoded L1 attribute deposit", "0x02f87101058459682f0085199c82cc0082520894ab5801a7d398351b8be11c439e05c5b3259aec9b8609184e72a00080c080a0a6d217a91ea344fc09f740f104f764d71bb1ca9a8e159117d2d27091ea5fce91a04cf5add5f5b7d791a2c4663ab488cb581df800fe0910aa755099ba466b49fd69" ] } ``` +---- + ### Building the L2 block with the execution engine [calling-exec-engine]: #building-the-L2-block-with-the-execution-engine @@ -189,15 +188,15 @@ route. This has the same signature, except that: - `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. - `safeBlockHash`: same as `headBlockHash`. - `finalizedBlockHash`: the hash of the block whose number is `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if - the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS == 50400` - (approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the + the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS` = 50400, + approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the first L1 block for which an L2 block was produced). See the [Finalization Guarantees][finalization] section for more details. [`ForkchoiceStateV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#ForkchoiceStateV1 -> **Note:** the properties of this `ForkchoiceStateV1` can be used to anchor queries to the regular (non-engine-API) -> JSON-RPC endpoint of the execution engine. [See here for more information.][L2-JSON-RPC-API] +> **Note:** the properties of `ForkchoiceStateV1` can be used to anchor queries to the regular (non-engine-API) JSON-RPC +> endpoint of the execution engine. [See here for more information.][L2-JSON-RPC-API] [L2-JSON-RPC-API]: TODO @@ -216,9 +215,9 @@ requiring manual user intervention). The following scenarios are assimilated to errors: -- [`engine_forkchoiceUpdateOPV1`] returning a `status` of "`SYNCING`" instead of "`SUCCESS`" whenever passed a +- [`engine_forkchoiceUpdatedOPV1`] returning a `status` of `"SYNCING"` instead of `"SUCCESS"` whenever passed a `headBlockHash` that it retrieved from a previous call to [`engine_executePayloadV1`]. -- [`engine_executePayloadV1`] returning a `status` of "`SYNCING`" or `"INVALID"` whenever passed an execution payload +- [`engine_executePayloadV1`] returning a `status` of `"SYNCING"` or `"INVALID"` whenever passed an execution payload that was obtained by a previous call to [`engine_getPayloadV1`]. [`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 @@ -260,6 +259,8 @@ the descendant of an ancestor of the previous head). In those case, the rollup d > Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more > than `FINALIZATION_DELAY_BLOCKS == 50400` in the past, hence preserving our finalization guarantees. +[merge]: https://ethereum.org/en/eth2/merge/ + Just like before, the meaning of errors returned by RPC calls is unspecified and must be handled at the implementer's discretion, while remaining compatible with the specification. From d0fe4acc14ff94afe7b920877a625c82089f09a3 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 10 Jan 2022 22:49:31 +0100 Subject: [PATCH 117/585] ref impl: Go linting + tests in CI --- .github/workflows/go-ci.yml | 29 +++++++++++++++++++++++++++++ .github/workflows/lint.yml | 1 + meta/linting.md | 27 +++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 .github/workflows/go-ci.yml diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml new file mode 100644 index 000000000000..1856a3bb3b1f --- /dev/null +++ b/.github/workflows/go-ci.yml @@ -0,0 +1,29 @@ +name: Go lint and test + +on: + push: + branches: + - 'main' + - 'staging' + pull_request: + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: v1.43.0 # version of golangci-lint, not the action + skip-go-installation: true + # rules: https://golangci-lint.run/usage/quick-start/ + args: -E asciicheck,goimports + - name: Test + run: go test ./... diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 760c97d26246..a7c83b5b7062 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,6 +4,7 @@ on: push: branches: - 'main' + - 'staging' pull_request: workflow_dispatch: diff --git a/meta/linting.md b/meta/linting.md index 2796ea33686d..d68b1dbd5ea4 100644 --- a/meta/linting.md +++ b/meta/linting.md @@ -1,5 +1,7 @@ # Linting +## Markdown + See - [markdownlint rule reference](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md) @@ -11,3 +13,28 @@ Justification for linting rules in [.markdownlint.json](/.markdownlint.json): - *no-blanks-blockquote*: enable multiple consecutive blockquotes separated by white lines - *single-title*: enable reusing `

` for content - *no-emphasis-as-heading*: enable emphasized paragraphs + +```shell +yarn # Install dependencies +yarn lint # Run linter +``` + +## Go + +See + +- [golangci-lint docs](https://golangci-lint.run/usage/install/#local-installation) +- [golangci-lint github](https://github.com/golangci/golangci-lint) +- [github action github](https://github.com/golangci/golangci-lint-action) + +Justification for linting rules: + +- *asciicheck*: no symbol names with invisible unicode and such +- *goimports*: group local and external import + +```shell +# Install linter globally (should not affect go.mod) +go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.43.0 +# run linter, add --fix option to fix problems (where supported) +golangci-lint run -E asciicheck,goimports +``` From 36257d66e66f964f5b37dad7a95285e72270ea39 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 10 Jan 2022 22:50:41 +0100 Subject: [PATCH 118/585] ref impl: opnode base --- go.mod | 18 ++ go.sum | 564 ++++++++++++++++++++++++++++++++++++++++++++ opnode/cmd/main.go | 99 ++++++++ opnode/node/log.go | 92 ++++++++ opnode/node/node.go | 18 ++ 5 files changed, 791 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 opnode/cmd/main.go create mode 100644 opnode/node/log.go create mode 100644 opnode/node/node.go diff --git a/go.mod b/go.mod new file mode 100644 index 000000000000..f825bc822f6f --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module github.com/ethereum-optimism/optimistic-specs + +go 1.17 + +require ( + github.com/ethereum/go-ethereum v1.10.13 + github.com/protolambda/ask v0.1.2 + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 +) + +require ( + github.com/go-stack/stack v1.8.0 // indirect + golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect +) + +replace github.com/ethereum/go-ethereum v1.10.13 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a + +//replace github.com/ethereum/go-ethereum v1.10.13 => ../reference-optimistic-geth diff --git a/go.sum b/go.sum new file mode 100644 index 000000000000..ff36ada6b786 --- /dev/null +++ b/go.sum @@ -0,0 +1,564 @@ +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/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/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/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/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +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-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +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/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +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/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/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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +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/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/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 v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +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/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a h1:ifL2rtsPv8plDlAucTQdLecBgLWph9HeXA0CHDKpxIE= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= +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/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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +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-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +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/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= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +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= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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/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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.5/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/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 v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +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/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-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +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/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/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/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.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +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/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.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +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-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +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 v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.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/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +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/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/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_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_model v0.0.0-20190812154241-14fe0d1b01d4/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/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/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/protolambda/ask v0.1.2 h1:BSQP7VDmh+L0lLFjEYUMrTnb2SwdT64UY3vXqDuIIok= +github.com/protolambda/ask v0.1.2/go.mod h1:7WB3T4BXZhKUaDcEjF7Ksgi7HCrBDxM37gyM1EhwkmM= +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/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/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/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 v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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/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.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/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.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-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +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-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-20201221181555-eec23a3978ad/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= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +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-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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +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/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-20201020160332-67f06af15bc9/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-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-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-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/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-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-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/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 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +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/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-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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-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.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= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +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/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= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +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/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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +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= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/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.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/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +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.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go new file mode 100644 index 000000000000..a8d83d9c3b46 --- /dev/null +++ b/opnode/cmd/main.go @@ -0,0 +1,99 @@ +package main + +import ( + "context" + "fmt" + "io" + "os" + "os/signal" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/protolambda/ask" +) + +type MainCmd struct { +} + +func (c *MainCmd) Help() string { + return "Run Optimism rollup node." +} + +func (c *MainCmd) Cmd(route string) (cmd interface{}, err error) { + switch route { + case "run": + return &node.OpNodeCmd{}, nil + default: + return nil, ask.UnrecognizedErr + } +} + +// TODO: we can support additional utils etc. +func (c *MainCmd) Routes() []string { + return []string{"run"} +} + +type start struct { + cmd *ask.CommandDescription + err error +} + +func main() { + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, os.Interrupt) + ctx, cancel := context.WithCancel(context.Background()) + + cmd := &MainCmd{} + descr, err := ask.Load(cmd) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "failed to load main command: %v", err.Error()) + os.Exit(1) + } + onDeprecated := func(fl ask.PrefixedFlag) error { + fmt.Fprintf(os.Stderr, "warning: flag %q is deprecated: %s", fl.Path, fl.Deprecated) + return nil + } + + starter := make(chan start) + + // run command in the background, so we can stop it at any time + go func() { + cmd, err := descr.Execute(ctx, &ask.ExecutionOptions{OnDeprecated: onDeprecated}, os.Args[1:]...) + starter <- start{cmd, err} + }() + + for { + select { + case start := <-starter: + if cmd, err := start.cmd, start.err; err == nil { + // if the command is long-running and closeable later on, then have the interrupt close it. + if cl, ok := cmd.Command.(io.Closer); ok { + <-interrupt + err := cl.Close() + cancel() + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "failed to close node gracefully. Exiting in 5 seconds. %v", err.Error()) + <-time.After(time.Second * 5) + os.Exit(1) + } + os.Exit(0) + } else { + os.Exit(0) + } + } else if err == ask.UnrecognizedErr { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } else if err == ask.HelpErr { + _, _ = fmt.Fprintln(os.Stderr, cmd.Usage(false)) + os.Exit(0) + } else { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + case <-interrupt: // if interrupted during start, then we try to cancel + cancel() + // TODO: multiple interrupts to force quick exit? + } + } + +} diff --git a/opnode/node/log.go b/opnode/node/log.go new file mode 100644 index 000000000000..52a976fddccf --- /dev/null +++ b/opnode/node/log.go @@ -0,0 +1,92 @@ +package node + +import ( + "fmt" + "os" + "strings" + + "github.com/ethereum/go-ethereum/log" + "golang.org/x/term" +) + +type LogLvl string + +func (lvl LogLvl) String() string { + return string(lvl) +} + +func (lvl *LogLvl) Set(v string) error { + v = strings.ToLower(v) // ignore case + _, err := log.LvlFromString(v) + if err != nil { + return err + } + *lvl = LogLvl(v) + return nil +} + +func (lvl *LogLvl) Type() string { + return "log-level" +} + +func (lvl LogLvl) Lvl() log.Lvl { + out, err := log.LvlFromString(string(lvl)) + if err != nil { + panic("lvl.Set failed") + } + return out +} + +type LogFormat string + +func (lf LogFormat) String() string { + return string(lf) +} + +func (lf *LogFormat) Set(v string) error { + switch v { + case "json", "json-pretty", "terminal", "text": + *lf = LogFormat(v) + return nil + default: + return fmt.Errorf("unrecognized log format: %s", v) + } +} + +func (lf *LogFormat) Type() string { + return "log-format" +} + +func (lf LogFormat) Format(color bool) log.Format { + switch lf { + case "json": + return log.JSONFormat() + case "json-pretty": + return log.JSONFormatEx(true, true) + case "text", "terminal": + return log.TerminalFormat(color) + default: + panic("lf.Set failed") + } +} + +type LogCmd struct { + LogLvl LogLvl `ask:"--level" help:"Log level: trace, debug, info, warn, error, crit. Capitals are accepted too."` + Color bool `ask:"--color" help:"Color the log output. Defaults to true if terminal is detected."` + Format LogFormat `ask:"--format" help:"Format the log output. Supported formats: 'text', 'json'"` +} + +func (c *LogCmd) Default() { + c.LogLvl = "info" + c.Color = term.IsTerminal(int(os.Stdout.Fd())) + c.Format = "text" +} + +func (c *LogCmd) Create() log.Logger { + handler := log.StreamHandler(os.Stdout, c.Format.Format(c.Color)) + handler = log.SyncHandler(handler) + log.LvlFilterHandler(c.LogLvl.Lvl(), handler) + logger := log.New() + logger.SetHandler(handler) + return logger +} diff --git a/opnode/node/node.go b/opnode/node/node.go new file mode 100644 index 000000000000..6d8d7858152e --- /dev/null +++ b/opnode/node/node.go @@ -0,0 +1,18 @@ +package node + +import "context" + +type OpNodeCmd struct { +} + +func (c *OpNodeCmd) Help() string { + return "Run optimism node" +} + +func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { + return nil +} + +func (c *OpNodeCmd) Close() error { + return nil +} From 488ed1a09eb6d221524a824ae97f42a5ffd3ec36 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 10 Jan 2022 23:04:23 +0100 Subject: [PATCH 119/585] ref impl: eth utils - watch head, hash/height id type, RPC source interfaces --- go.mod | 2 + go.sum | 17 ++++++ opnode/eth/canonical.go | 36 ++++++++++++ opnode/eth/heads.go | 48 +++++++++++++++ opnode/eth/id.go | 22 +++++++ opnode/eth/source.go | 127 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 252 insertions(+) create mode 100644 opnode/eth/canonical.go create mode 100644 opnode/eth/heads.go create mode 100644 opnode/eth/id.go create mode 100644 opnode/eth/source.go diff --git a/go.mod b/go.mod index f825bc822f6f..74bdad440959 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,9 @@ require ( ) require ( + github.com/btcsuite/btcd v0.20.1-beta // indirect github.com/go-stack/stack v1.8.0 // indirect + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect ) diff --git a/go.sum b/go.sum index ff36ada6b786..52fb4d7f2de1 100644 --- a/go.sum +++ b/go.sum @@ -35,7 +35,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= @@ -57,6 +59,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 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 v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -68,7 +71,9 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f 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 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/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= @@ -83,6 +88,7 @@ github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= @@ -117,6 +123,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 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-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= @@ -147,6 +154,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= 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= @@ -241,6 +249,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd 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 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= 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= @@ -255,6 +264,7 @@ github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -273,6 +283,7 @@ github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -286,6 +297,7 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 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/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/protolambda/ask v0.1.2 h1:BSQP7VDmh+L0lLFjEYUMrTnb2SwdT64UY3vXqDuIIok= github.com/protolambda/ask v0.1.2/go.mod h1:7WB3T4BXZhKUaDcEjF7Ksgi7HCrBDxM37gyM1EhwkmM= @@ -297,6 +309,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= 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= @@ -315,9 +328,12 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV 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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= 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= @@ -343,6 +359,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= 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= diff --git a/opnode/eth/canonical.go b/opnode/eth/canonical.go new file mode 100644 index 000000000000..89a482032771 --- /dev/null +++ b/opnode/eth/canonical.go @@ -0,0 +1,36 @@ +package eth + +import ( + "context" + "fmt" + "math/big" +) + +// BlockLinkByNumber Retrieves the *currently* canonical block-hash at the given block-height, and the parent before it. +// The results of this should not be cached, or the cache needs to be reorg-aware. +type BlockLinkByNumber interface { + BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) +} + +type BlockLinkByNumberFn func(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) + +func (fn BlockLinkByNumberFn) BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) { + return fn(ctx, num) +} + +// CanonicalChain presents the block-hashes by height by wrapping a header-source +// (useful due to lack of a direct JSON RPC endpoint) +func CanonicalChain(l1Src HeaderByNumberSource) BlockLinkByNumber { + return BlockLinkByNumberFn(func(ctx context.Context, num uint64) (BlockID, BlockID, error) { + header, err := l1Src.HeaderByNumber(ctx, big.NewInt(int64(num))) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return BlockID{}, BlockID{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", num, err) + } + parentNum := num + if parentNum > 0 { + parentNum -= 1 + } + return BlockID{Hash: header.Hash(), Number: num}, BlockID{Hash: header.ParentHash, Number: parentNum}, nil + }) +} diff --git a/opnode/eth/heads.go b/opnode/eth/heads.go new file mode 100644 index 000000000000..1b729571ead7 --- /dev/null +++ b/opnode/eth/heads.go @@ -0,0 +1,48 @@ +package eth + +import ( + "context" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +type HeadSignal struct { + Parent BlockID + Self BlockID +} + +// HeadSignalFn is called to inform a chain with a new head +type HeadSignalFn func(sig HeadSignal) + +// WatchHeadChanges wraps a new-head subscription from ChainReader to feed the given Tracker +func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) (ethereum.Subscription, error) { + headChanges := make(chan *types.Header, 10) + sub, err := src.SubscribeNewHead(ctx, headChanges) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case header := <-headChanges: + hash := header.Hash() + height := header.Number.Uint64() + self := BlockID{Hash: hash, Number: height} + parent := BlockID{} + if height > 0 { + parent = BlockID{Hash: header.ParentHash, Number: height - 1} + } + fn(HeadSignal{Parent: parent, Self: self}) + case err := <-sub.Err(): + return err + case <-ctx.Done(): + return ctx.Err() + case <-quit: + return nil + } + } + }), nil +} diff --git a/opnode/eth/id.go b/opnode/eth/id.go new file mode 100644 index 000000000000..aa33558efafa --- /dev/null +++ b/opnode/eth/id.go @@ -0,0 +1,22 @@ +package eth + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" +) + +type BlockID struct { + Hash common.Hash + Number uint64 +} + +func (id BlockID) String() string { + return fmt.Sprintf("%s:%d", id.Hash.String(), id.Number) +} + +// TerminalString implements log.TerminalStringer, formatting a string for console +// output during logging. +func (id BlockID) TerminalString() string { + return fmt.Sprintf("%s:%d", id.Hash.TerminalString(), id.Number) +} diff --git a/opnode/eth/source.go b/opnode/eth/source.go new file mode 100644 index 000000000000..95cadd68d1a6 --- /dev/null +++ b/opnode/eth/source.go @@ -0,0 +1,127 @@ +package eth + +import ( + "context" + "math/big" + "sync/atomic" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +type NewHeadSource interface { + SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) +} + +type HeaderByHashSource interface { + HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) +} + +type HeaderByNumberSource interface { + HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) +} + +type ReceiptSource interface { + TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) +} + +type BlockByHashSource interface { + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) +} + +type BlockByNumberSource interface { + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) +} + +type L1Source interface { + NewHeadSource + HeaderByHashSource + HeaderByNumberSource + ReceiptSource + BlockByHashSource + Close() +} + +type BlockSource interface { + BlockByHashSource + BlockByNumberSource +} + +// For test instances, composition etc. we implement the interfaces with equivalent function types + +type NewHeadFn func(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) + +func (fn NewHeadFn) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { + return fn(ctx, ch) +} + +type HeaderByHashFn func(ctx context.Context, hash common.Hash) (*types.Header, error) + +func (fn HeaderByHashFn) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + return fn(ctx, hash) +} + +type HeaderByNumberFn func(ctx context.Context, number *big.Int) (*types.Header, error) + +func (fn HeaderByNumberFn) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + return fn(ctx, number) +} + +type ReceiptFn func(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + +func (fn ReceiptFn) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + return fn(ctx, txHash) +} + +type BlockByHashFn func(ctx context.Context, hash common.Hash) (*types.Block, error) + +func (fn BlockByHashFn) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return fn(ctx, hash) +} + +type BlockByNumFn func(ctx context.Context, number *big.Int) (*types.Block, error) + +func (fn BlockByNumFn) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return fn(ctx, number) +} + +// CombinedL1Source balances multiple L1 sources, to shred concurrent requests to multiple endpoints +type CombinedL1Source struct { + i uint64 + sources []L1Source +} + +func NewCombinedL1Source(sources []L1Source) L1Source { + if len(sources) == 0 { + panic("need at least 1 source") + } + return &CombinedL1Source{i: 0, sources: sources} +} + +func (cs *CombinedL1Source) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].HeaderByHash(ctx, hash) +} + +func (cs *CombinedL1Source) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].HeaderByNumber(ctx, number) +} + +func (cs *CombinedL1Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { + // TODO: can't use multiple sources as consensus, or head may be conflicting too much + return cs.sources[0].SubscribeNewHead(ctx, ch) +} + +func (cs *CombinedL1Source) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].TransactionReceipt(ctx, txHash) +} + +func (cs *CombinedL1Source) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].BlockByHash(ctx, hash) +} + +func (cs *CombinedL1Source) Close() { + for _, src := range cs.sources { + src.Close() + } +} From 12f94124d898882b777f1ff276a9808ed2b3c47a Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 10 Jan 2022 23:15:28 +0100 Subject: [PATCH 120/585] ref impl: parallelized downloader for L1 block + receipts --- go.mod | 18 +++ go.sum | 20 ++++ opnode/l1/downloader.go | 220 +++++++++++++++++++++++++++++++++++ opnode/l1/downloader_test.go | 206 ++++++++++++++++++++++++++++++++ 4 files changed, 464 insertions(+) create mode 100644 opnode/l1/downloader.go create mode 100644 opnode/l1/downloader_test.go diff --git a/go.mod b/go.mod index 74bdad440959..2f267216ff7e 100644 --- a/go.mod +++ b/go.mod @@ -4,15 +4,33 @@ go 1.17 require ( github.com/ethereum/go-ethereum v1.10.13 + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/protolambda/ask v0.1.2 + github.com/stretchr/testify v1.7.0 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 ) require ( + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/btcsuite/btcd v0.20.1-beta // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-stack/stack v1.8.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/tsdb v0.7.1 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) replace github.com/ethereum/go-ethereum v1.10.13 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a diff --git a/go.sum b/go.sum index 52fb4d7f2de1..31bb54ffe7b7 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,7 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA 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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= 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= @@ -110,6 +111,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv 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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 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= @@ -120,8 +122,10 @@ github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1T 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-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= @@ -182,6 +186,7 @@ github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= 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= @@ -224,11 +229,14 @@ github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM52 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/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= 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.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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= @@ -262,6 +270,7 @@ github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 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/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -269,9 +278,11 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.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 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 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= @@ -286,6 +297,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 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= @@ -327,6 +339,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf 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.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 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= @@ -411,6 +424,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -473,6 +487,7 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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= @@ -508,6 +523,7 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -555,11 +571,13 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/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 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 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= @@ -568,7 +586,9 @@ 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.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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go new file mode 100644 index 000000000000..c66f61687959 --- /dev/null +++ b/opnode/l1/downloader.go @@ -0,0 +1,220 @@ +package l1 + +import ( + "context" + "errors" + "fmt" + "sync" + "sync/atomic" + "time" + + lru "github.com/hashicorp/golang-lru" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +type blockAndReceipts struct { + // Track if we finished (with error or not). May increment >1 when other sub-tasks fail. + // First field, aligned atomic changes. + finished uint32 + + // Count receipts to track status + // First field of struct for memory aligned atomic access + DownloadedReceipts uint32 + + Block *types.Block + // allocated in advance, one for each transaction, nil until downloaded + Receipts []*types.Receipt + + // stop fetching if this context is dead + ctx context.Context + + // for other duplicate requests to get the result + feed event.Feed +} + +// wrappedErr wraps an error, since event.Feed cannot handle nil errors otherwise (reflection on nil) +type wrappedErr struct { + error +} + +func (bl *blockAndReceipts) Finish(err wrappedErr) { + if atomic.AddUint32(&bl.finished, 1) == 1 { + bl.feed.Send(err) + } +} + +type receiptTask struct { + BlockHash common.Hash + TxHash common.Hash + TxIndex uint64 + // Count the attempts we made to fetch this receipt. Block as a whole fails if we tried to many times. + Retry uint64 + // Avoid concurrent Downloader cache access and pruning edge cases with receipts + // Keep a pointer to insert the receipt at + Dest *blockAndReceipts +} + +type Downloader interface { + Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) + AddReceiptWorkers(n int) int +} + +type DownloadSource interface { + eth.BlockByHashSource + eth.ReceiptSource +} + +type downloader struct { + // cache of ongoing/completed block tasks: block hash -> block + cacheEvict *lru.Cache + cacheLock sync.Mutex + + receiptTasks chan *receiptTask + receiptWorkers []ethereum.Subscription + receiptWorkersLock sync.Mutex + + chr DownloadSource +} + +var downloadEvictedErr = errors.New("evicted") + +func NewDownloader(chr DownloadSource) Downloader { + dl := &downloader{ + receiptTasks: make(chan *receiptTask, 100), + chr: chr, + } + evict := func(k, v interface{}) { + // stop downloading things if they were evicted (already finished items are unaffected) + v.(*blockAndReceipts).Finish(wrappedErr{downloadEvictedErr}) + } + // 500 at 100 KB each would be 50 MB of memory for the L1 block inputs cache + dl.cacheEvict, _ = lru.NewWithEvict(500, evict) + return dl +} + +func (l1t *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { + // check if we are already working on it + l1t.cacheLock.Lock() + + var bnr *blockAndReceipts + if bnrIfc, ok := l1t.cacheEvict.Get(id.Hash); ok { + bnr = bnrIfc.(*blockAndReceipts) + l1t.cacheEvict.Add(id.Hash, bnr) // add it again, so it moves to the front and avoid eviction + } else { + bnr = &blockAndReceipts{ctx: ctx} + l1t.cacheEvict.Add(id.Hash, bnr) + + // pull the block in the background + go func() { + ctx, cancel := context.WithTimeout(ctx, time.Second*10) + defer cancel() + bl, err := l1t.chr.BlockByHash(ctx, id.Hash) + if err != nil { + bnr.Finish(wrappedErr{fmt.Errorf("failed to download block %s: %v", id.Hash, err)}) + return + } + + txs := bl.Transactions() + bnr.Block = bl + bnr.Receipts = make([]*types.Receipt, len(txs)) + + for i, tx := range txs { + l1t.receiptTasks <- &receiptTask{BlockHash: id.Hash, TxHash: tx.Hash(), TxIndex: uint64(i), Dest: bnr} + } + + // no receipts to fetch? Then we are done! + if len(txs) == 0 { + bnr.Finish(wrappedErr{nil}) + } + }() + } + l1t.cacheLock.Unlock() + + ch := make(chan wrappedErr) + sub := bnr.feed.Subscribe(ch) + select { + case wErr := <-ch: + if wErr.error != nil { + return nil, nil, wErr.error + } + return bnr.Block, bnr.Receipts, nil + case err := <-sub.Err(): + return nil, nil, err + case <-ctx.Done(): + return nil, nil, ctx.Err() + } +} + +const maxReceiptRetry = 5 + +func (l1t *downloader) newReceiptWorker() ethereum.Subscription { + return event.NewSubscription(func(quit <-chan struct{}) error { + for { + select { + case task := <-l1t.receiptTasks: + // scheduled tasks may be stale if other receipts of the block failed too many times + if task.Dest.finished > 0 { // no need for locks, a very rare stale download does not hurt + continue + } + // limit fetching to the task as a whole, and constrain to 10 seconds for receipt itself + ctx, cancel := context.WithTimeout(task.Dest.ctx, time.Second*10) + defer cancel() + receipt, err := l1t.chr.TransactionReceipt(ctx, task.TxHash) + if err != nil { + // if a single receipt fails out of the whole block, we can retry a few times. + if task.Retry >= maxReceiptRetry { + // Failed to get the receipt too many times, block fails! + task.Dest.Finish(wrappedErr{fmt.Errorf("failed to download receipt again, and reached max %d retries: %v", maxReceiptRetry, err)}) + continue + } else { + task.Retry += 1 + select { + case l1t.receiptTasks <- task: + // all good, retry scheduled successfully + default: + // failed to schedule, too much receipt work, stop block to relieve pressure. + task.Dest.Finish(wrappedErr{fmt.Errorf("receipt downloader too busy, not downloading receipt again (%d retries): %v", task.Retry, err)}) + continue + } + continue + } + } + task.Dest.Receipts[task.TxIndex] = receipt + // We count the receipts we have so far (atomic, avoid parallel counting race condition) + total := atomic.AddUint32(&task.Dest.DownloadedReceipts, 1) + if total == uint32(len(task.Dest.Receipts)) { + // block completed without error! + task.Dest.Finish(wrappedErr{nil}) + continue + } + // task completed, but block is not complete without other receipt tasks finishing first + case <-quit: + return nil + } + } + }) +} + +// AddReceiptWorkers can add or remove (negative value) worker routines to parallelize receipt downloads with. +// It returns the number of active workers. +func (l1t *downloader) AddReceiptWorkers(n int) int { + l1t.receiptWorkersLock.Lock() + defer l1t.receiptWorkersLock.Unlock() + if n < 0 { + for i := 0; i < -n && len(l1t.receiptWorkers) > 0; i++ { + last := len(l1t.receiptWorkers) - 1 + l1t.receiptWorkers[last].Unsubscribe() + l1t.receiptWorkers = l1t.receiptWorkers[:last] + } + } + for i := 0; i < n; i++ { + l1t.receiptWorkers = append(l1t.receiptWorkers, l1t.newReceiptWorker()) + } + return len(l1t.receiptWorkers) +} diff --git a/opnode/l1/downloader_test.go b/opnode/l1/downloader_test.go new file mode 100644 index 000000000000..8bb9628d49f2 --- /dev/null +++ b/opnode/l1/downloader_test.go @@ -0,0 +1,206 @@ +package l1 + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/trie" + "github.com/stretchr/testify/assert" +) + +type retryReceipt struct { + tries int + receipt *types.Receipt +} +type mockDownloaderSource struct { + block *types.Block + receipts map[common.Hash]*retryReceipt +} + +func (m *mockDownloaderSource) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + if m.block == nil { + return nil, errors.New("no block here") + } + return m.block, nil +} + +func (m *mockDownloaderSource) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + ret, ok := m.receipts[txHash] + if !ok { + return nil, errors.New("no receipt here") + } + ret.tries -= 1 + if ret.tries < 0 { + return ret.receipt, nil + } + return nil, fmt.Errorf("receipt takes %d more tries to download", ret.tries) +} + +func RandomL1Block(txCount int) (*types.Block, []*types.Receipt) { + // insecure but reproducible secret key RNG for test txs + rng := rand.New(rand.NewSource(123)) + key, _ := ecdsa.GenerateKey(crypto.S256(), rng) + signer := types.NewLondonSigner(big.NewInt(1234)) + + var txs []*types.Transaction + for i := 0; i < txCount; i++ { + tx, err := types.SignNewTx(key, signer, &types.LegacyTx{ + Nonce: uint64(i), + GasPrice: big.NewInt(7), + Gas: 21000, + To: &common.Address{}, // burn, send to zero address + Value: big.NewInt(1337), + Data: nil, + }) + if err != nil { + panic(fmt.Errorf("failed to sign tx %d: %v", i, err)) + } + txs = append(txs, tx) + } + + receipts := make([]*types.Receipt, 0, len(txs)) + for i, tx := range txs { + h := tx.Hash() + receipts = append(receipts, &types.Receipt{ + Type: tx.Type(), + Status: types.ReceiptStatusSuccessful, + // not part of the receipt, but extra optional info, which we use for testing + TxHash: h, + TransactionIndex: uint(i), + }) + } + hasher := trie.NewStackTrie(nil) + + var parent common.Hash + rng.Read(parent[:]) + var state common.Hash + rng.Read(state[:]) + block := types.NewBlock(&types.Header{ + ParentHash: parent, + UncleHash: types.EmptyUncleHash, + Coinbase: common.Address{}, + Root: state, + TxHash: types.DeriveSha(types.Transactions(txs), hasher), + ReceiptHash: types.DeriveSha(types.Receipts(receipts), hasher), + Bloom: types.Bloom{}, + Difficulty: nil, + Number: big.NewInt(123), + }, txs, nil, receipts, trie.NewStackTrie(nil)) + return block, receipts +} + +func TestDownloader_Fetch(t *testing.T) { + checks := func(t *testing.T, bl *types.Block, rs []*types.Receipt, workers int, change func(src *mockDownloaderSource) bool) { + receiptRetries := make(map[common.Hash]*retryReceipt) + for _, r := range rs { + receiptRetries[r.TxHash] = &retryReceipt{tries: 0, receipt: r} + } + src := &mockDownloaderSource{block: bl, receipts: receiptRetries} + expectOK := true + if change != nil { + expectOK = change(src) + } + dl := NewDownloader(src) + dl.AddReceiptWorkers(workers) + block, receipts, err := dl.Fetch(context.Background(), eth.BlockID{Hash: bl.Hash(), Number: bl.NumberU64()}) + if expectOK { + if err != nil { + t.Fatal(err) + } + assert.Equal(t, bl, block, "block retrieved") + assert.Equal(t, rs, receipts, "receipts received") + } else { + if err == nil { + t.Fatal("expected error, but got none") + } + } + } + + testWithWorkers := func(workers int) { + t.Run(fmt.Sprintf("%d workers", workers), func(t *testing.T) { + + t.Run("empty block", func(t *testing.T) { + bl, rs := RandomL1Block(0) + checks(t, bl, rs, 2, nil) + }) + + t.Run("missing block", func(t *testing.T) { + bl, rs := RandomL1Block(0) + checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { + src.block = nil + return false + }) + }) + + t.Run("single tx block", func(t *testing.T) { + bl, rs := RandomL1Block(1) + checks(t, bl, rs, 2, nil) + }) + + t.Run("single tx single retry block", func(t *testing.T) { + bl, rs := RandomL1Block(1) + checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { + for _, r := range src.receipts { + r.tries = 1 + } + return true + }) + }) + + t.Run("single tx too many retries block", func(t *testing.T) { + bl, rs := RandomL1Block(1) + checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { + for _, r := range src.receipts { + r.tries = 9999 + } + return false + }) + }) + + t.Run("two tx retry block", func(t *testing.T) { + bl, rs := RandomL1Block(2) + checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { + for _, r := range src.receipts { + r.tries = 1 + } + return true + }) + }) + + t.Run("few tx no retry block", func(t *testing.T) { + bl, rs := RandomL1Block(10) + checks(t, bl, rs, 2, nil) + }) + + t.Run("many tx no retry block", func(t *testing.T) { + bl, rs := RandomL1Block(100) + checks(t, bl, rs, 2, nil) + }) + + t.Run("many tx random retries block", func(t *testing.T) { + bl, rs := RandomL1Block(100) + rng := rand.New(rand.NewSource(123)) + checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { + for _, r := range src.receipts { + r.tries = rng.Intn(4) + } + return true + }) + }) + }) + } + + testWithWorkers(1) + testWithWorkers(2) + testWithWorkers(5) +} From 8509aecaee83221ef2e2f30934580087597a8d4a Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 5 Jan 2022 16:22:10 -0500 Subject: [PATCH 121/585] specs: Add README with design goals --- specs/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 specs/README.md diff --git a/specs/README.md b/specs/README.md new file mode 100644 index 000000000000..3805fcc4fccf --- /dev/null +++ b/specs/README.md @@ -0,0 +1,31 @@ +# Optimism specs + +This directory contains the plain english specs for Optimism, an minimal optimistic rollup protocol +that maintains 1:1 compatibility with Ethereum. + +## Design Goals + +Our aim is to design a protocol specification that is: + +- **Fast:** When users send transactions, they get reliable confirmations with low-latency. + For example when swapping on Uniswap you should see that your transaction succeed in less than 2 + seconds. +- **Scalable:** It should be possible to handle an enormous number of transactions per second which + will enable us to charge low fees. V1.0 will enable us to scale up to and even past the gas limit + on L1. Later iterations will scale much further. +- **Modular:** Our designs will use modularity to reduce complexity and enable parallel + contributions. Coming up with good conceptual frameworks & composable atoms of software enables us + to build extremely complex software even when any one person cannot hold that much in their brain. +- **Minimal:** Rollups should be minimal to best take advantage of the battle-tested infrastructure + (like Geth) that already runs Ethereum. An ideal optimistic rollup design should be representable + as a *diff* against Ethereum client software. +- **Developer Driven:** Our designs will be developer driven to ensure we are actually building + something that people want to use. We must constantly engage with the developers who will be using our + software to avoid creating a system no one wants to use. +- **Clear and Readable:** The specs we write are written to be read. So tight feedback loop with the + systems team consuming the spec is also key! +- **Secure:** This is self-evident. We cannot lose money and in a system where even a bit of downtime can + result in loss of funds this means everything we build must be incredibly secure. +- **Decentralizable:** Everything we build must have a clear path towards decentralization. Today + Optimism relies on OptimismPBC to function, but eventually it will be managed by a DAO and even in + that decentralized future our system must thrive. From 1f9730b5876a56d2f664f088cc04d0f1ddc0d60b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 7 Jan 2022 11:22:12 -0500 Subject: [PATCH 122/585] specs: Add ToC to README --- specs/README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/specs/README.md b/specs/README.md index 3805fcc4fccf..a7f9b96fc08e 100644 --- a/specs/README.md +++ b/specs/README.md @@ -3,6 +3,13 @@ This directory contains the plain english specs for Optimism, an minimal optimistic rollup protocol that maintains 1:1 compatibility with Ethereum. +## Specification Contents + +- [Glossary](glossary.md) +- [Deposits](deposits.md) +- [Execution Engine](exec-engine.md) +- [Rollup Node](rollup-node.md) + ## Design Goals Our aim is to design a protocol specification that is: @@ -20,12 +27,12 @@ Our aim is to design a protocol specification that is: (like Geth) that already runs Ethereum. An ideal optimistic rollup design should be representable as a *diff* against Ethereum client software. - **Developer Driven:** Our designs will be developer driven to ensure we are actually building - something that people want to use. We must constantly engage with the developers who will be using our - software to avoid creating a system no one wants to use. + something that people want to use. We must constantly engage with the developers who will be using + our software to avoid creating a system no one wants to use. - **Clear and Readable:** The specs we write are written to be read. So tight feedback loop with the systems team consuming the spec is also key! -- **Secure:** This is self-evident. We cannot lose money and in a system where even a bit of downtime can - result in loss of funds this means everything we build must be incredibly secure. +- **Secure:** This is self-evident. We cannot lose money and in a system where even a bit of + downtime can result in loss of funds this means everything we build must be incredibly secure. - **Decentralizable:** Everything we build must have a clear path towards decentralization. Today Optimism relies on OptimismPBC to function, but eventually it will be managed by a DAO and even in that decentralized future our system must thrive. From e738589dac1160ea1daa8f0d081677647d1135cb Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 18:09:57 +0100 Subject: [PATCH 123/585] ref impl: downloader - implement review suggestions from @norswap --- opnode/l1/downloader.go | 198 ++++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 91 deletions(-) diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go index c66f61687959..0cb4caca7206 100644 --- a/opnode/l1/downloader.go +++ b/opnode/l1/downloader.go @@ -18,23 +18,38 @@ import ( "github.com/ethereum/go-ethereum/event" ) -type blockAndReceipts struct { - // Track if we finished (with error or not). May increment >1 when other sub-tasks fail. +const ( + fetchBlockTimeout = 10 * time.Second + fetchReceiptTimeout = 10 * time.Second + maxReceiptRetry = 5 + + // 500 at 100 KB each would be 50 MB of memory for the L1 block inputs cache + cacheSize = 500 + + // Amount of receipt tasks to buffer before applying back-pressure (blocking new block-requests) + receiptQueueSize = 100 +) + +type downloadTask struct { + // Incremented when Finish is called, to check whether the task already completed (with or without error). + // May increment >1 when other sub-tasks fail. + // // First field, aligned atomic changes. finished uint32 - // Count receipts to track status - // First field of struct for memory aligned atomic access - DownloadedReceipts uint32 + // Count already downloaded receipts to track status + // + // Aligned after above field, atomic changes. + downloadedReceipts uint32 - Block *types.Block - // allocated in advance, one for each transaction, nil until downloaded - Receipts []*types.Receipt + block *types.Block + // receipts slice is allocated in advance, one slot for each transaction, nil until downloaded + receipts []*types.Receipt // stop fetching if this context is dead ctx context.Context - // for other duplicate requests to get the result + // feed to subscribe the requests to (de-duplicate work) feed event.Feed } @@ -43,21 +58,21 @@ type wrappedErr struct { error } -func (bl *blockAndReceipts) Finish(err wrappedErr) { +func (bl *downloadTask) Finish(err wrappedErr) { if atomic.AddUint32(&bl.finished, 1) == 1 { bl.feed.Send(err) } } type receiptTask struct { - BlockHash common.Hash - TxHash common.Hash - TxIndex uint64 - // Count the attempts we made to fetch this receipt. Block as a whole fails if we tried to many times. - Retry uint64 - // Avoid concurrent Downloader cache access and pruning edge cases with receipts - // Keep a pointer to insert the receipt at - Dest *blockAndReceipts + blockHash common.Hash + txHash common.Hash + txIndex uint64 + // Count the attempts we made to fetch this receipt. Block as a whole fails if we tried too many times. + retry uint64 + // Avoid concurrent Downloader cache access and pruning edge cases with receipts. + // Keep a pointer to the parent task to insert the receipt into. + dest *downloadTask } type Downloader interface { @@ -79,71 +94,70 @@ type downloader struct { receiptWorkers []ethereum.Subscription receiptWorkersLock sync.Mutex - chr DownloadSource + src DownloadSource } var downloadEvictedErr = errors.New("evicted") -func NewDownloader(chr DownloadSource) Downloader { +func NewDownloader(dlSource DownloadSource) Downloader { dl := &downloader{ - receiptTasks: make(chan *receiptTask, 100), - chr: chr, + receiptTasks: make(chan *receiptTask, receiptQueueSize), + src: dlSource, } evict := func(k, v interface{}) { // stop downloading things if they were evicted (already finished items are unaffected) - v.(*blockAndReceipts).Finish(wrappedErr{downloadEvictedErr}) + v.(*downloadTask).Finish(wrappedErr{downloadEvictedErr}) } - // 500 at 100 KB each would be 50 MB of memory for the L1 block inputs cache - dl.cacheEvict, _ = lru.NewWithEvict(500, evict) + dl.cacheEvict, _ = lru.NewWithEvict(cacheSize, evict) return dl } -func (l1t *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { +func (dl *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { // check if we are already working on it - l1t.cacheLock.Lock() + dl.cacheLock.Lock() - var bnr *blockAndReceipts - if bnrIfc, ok := l1t.cacheEvict.Get(id.Hash); ok { - bnr = bnrIfc.(*blockAndReceipts) - l1t.cacheEvict.Add(id.Hash, bnr) // add it again, so it moves to the front and avoid eviction + var dlTask *downloadTask + if dlTaskIfc, ok := dl.cacheEvict.Get(id.Hash); ok { + dlTask = dlTaskIfc.(*downloadTask) + dl.cacheEvict.Add(id.Hash, dlTask) // add it again, so it moves to the front and avoid eviction } else { - bnr = &blockAndReceipts{ctx: ctx} - l1t.cacheEvict.Add(id.Hash, bnr) + dlTask = &downloadTask{ctx: ctx} + dl.cacheEvict.Add(id.Hash, dlTask) // pull the block in the background go func() { - ctx, cancel := context.WithTimeout(ctx, time.Second*10) + ctx, cancel := context.WithTimeout(ctx, fetchBlockTimeout) defer cancel() - bl, err := l1t.chr.BlockByHash(ctx, id.Hash) + bl, err := dl.src.BlockByHash(ctx, id.Hash) if err != nil { - bnr.Finish(wrappedErr{fmt.Errorf("failed to download block %s: %v", id.Hash, err)}) + dlTask.Finish(wrappedErr{fmt.Errorf("failed to download block %s: %v", id.Hash, err)}) return } txs := bl.Transactions() - bnr.Block = bl - bnr.Receipts = make([]*types.Receipt, len(txs)) + dlTask.block = bl + dlTask.receipts = make([]*types.Receipt, len(txs)) for i, tx := range txs { - l1t.receiptTasks <- &receiptTask{BlockHash: id.Hash, TxHash: tx.Hash(), TxIndex: uint64(i), Dest: bnr} + dl.receiptTasks <- &receiptTask{blockHash: id.Hash, txHash: tx.Hash(), txIndex: uint64(i), dest: dlTask} } // no receipts to fetch? Then we are done! if len(txs) == 0 { - bnr.Finish(wrappedErr{nil}) + dlTask.Finish(wrappedErr{nil}) } }() } - l1t.cacheLock.Unlock() + dl.cacheLock.Unlock() ch := make(chan wrappedErr) - sub := bnr.feed.Subscribe(ch) + sub := dlTask.feed.Subscribe(ch) select { case wErr := <-ch: if wErr.error != nil { return nil, nil, wErr.error } - return bnr.Block, bnr.Receipts, nil + return dlTask.block, dlTask.receipts, nil case err := <-sub.Err(): return nil, nil, err case <-ctx.Done(): @@ -151,49 +165,51 @@ func (l1t *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, } } -const maxReceiptRetry = 5 +func (dl *downloader) processTask(task *receiptTask) { + // scheduled tasks may be stale if other receipts of the block failed too many times + if task.dest.finished > 0 { // no need for locks, a very rare stale download does not hurt + return + } + // stop fetching when the task is cancelled or when the individual receipt times out + ctx, cancel := context.WithTimeout(task.dest.ctx, fetchReceiptTimeout) + defer cancel() + receipt, err := dl.src.TransactionReceipt(ctx, task.txHash) + if err != nil { + // if a single receipt fails out of the whole block, we can retry a few times. + if task.retry >= maxReceiptRetry { + // Failed to get the receipt too many times, block fails! + task.dest.Finish(wrappedErr{fmt.Errorf("failed to download receipt again, and reached max %d retries: %v", maxReceiptRetry, err)}) + return + } else { + task.retry += 1 + select { + case dl.receiptTasks <- task: + // all good, retry scheduled successfully + return + default: + // failed to schedule, too much receipt work, stop block to relieve pressure. + task.dest.Finish(wrappedErr{fmt.Errorf("receipt downloader too busy, not downloading receipt again (%d retries): %v", task.retry, err)}) + return + } + } + } + task.dest.receipts[task.txIndex] = receipt + // We count the receipts we have so far (atomic, avoid parallel counting race condition) + total := atomic.AddUint32(&task.dest.downloadedReceipts, 1) + if total == uint32(len(task.dest.receipts)) { + // block completed without error! + task.dest.Finish(wrappedErr{nil}) + return + } + // task completed, but no Finish call without other receipt tasks finishing first +} -func (l1t *downloader) newReceiptWorker() ethereum.Subscription { +func (dl *downloader) newReceiptWorker() ethereum.Subscription { return event.NewSubscription(func(quit <-chan struct{}) error { for { select { - case task := <-l1t.receiptTasks: - // scheduled tasks may be stale if other receipts of the block failed too many times - if task.Dest.finished > 0 { // no need for locks, a very rare stale download does not hurt - continue - } - // limit fetching to the task as a whole, and constrain to 10 seconds for receipt itself - ctx, cancel := context.WithTimeout(task.Dest.ctx, time.Second*10) - defer cancel() - receipt, err := l1t.chr.TransactionReceipt(ctx, task.TxHash) - if err != nil { - // if a single receipt fails out of the whole block, we can retry a few times. - if task.Retry >= maxReceiptRetry { - // Failed to get the receipt too many times, block fails! - task.Dest.Finish(wrappedErr{fmt.Errorf("failed to download receipt again, and reached max %d retries: %v", maxReceiptRetry, err)}) - continue - } else { - task.Retry += 1 - select { - case l1t.receiptTasks <- task: - // all good, retry scheduled successfully - default: - // failed to schedule, too much receipt work, stop block to relieve pressure. - task.Dest.Finish(wrappedErr{fmt.Errorf("receipt downloader too busy, not downloading receipt again (%d retries): %v", task.Retry, err)}) - continue - } - continue - } - } - task.Dest.Receipts[task.TxIndex] = receipt - // We count the receipts we have so far (atomic, avoid parallel counting race condition) - total := atomic.AddUint32(&task.Dest.DownloadedReceipts, 1) - if total == uint32(len(task.Dest.Receipts)) { - // block completed without error! - task.Dest.Finish(wrappedErr{nil}) - continue - } - // task completed, but block is not complete without other receipt tasks finishing first + case task := <-dl.receiptTasks: + dl.processTask(task) case <-quit: return nil } @@ -203,18 +219,18 @@ func (l1t *downloader) newReceiptWorker() ethereum.Subscription { // AddReceiptWorkers can add or remove (negative value) worker routines to parallelize receipt downloads with. // It returns the number of active workers. -func (l1t *downloader) AddReceiptWorkers(n int) int { - l1t.receiptWorkersLock.Lock() - defer l1t.receiptWorkersLock.Unlock() +func (dl *downloader) AddReceiptWorkers(n int) int { + dl.receiptWorkersLock.Lock() + defer dl.receiptWorkersLock.Unlock() if n < 0 { - for i := 0; i < -n && len(l1t.receiptWorkers) > 0; i++ { - last := len(l1t.receiptWorkers) - 1 - l1t.receiptWorkers[last].Unsubscribe() - l1t.receiptWorkers = l1t.receiptWorkers[:last] + for i := 0; i < -n && len(dl.receiptWorkers) > 0; i++ { + last := len(dl.receiptWorkers) - 1 + dl.receiptWorkers[last].Unsubscribe() + dl.receiptWorkers = dl.receiptWorkers[:last] } } for i := 0; i < n; i++ { - l1t.receiptWorkers = append(l1t.receiptWorkers, l1t.newReceiptWorker()) + dl.receiptWorkers = append(dl.receiptWorkers, dl.newReceiptWorker()) } - return len(l1t.receiptWorkers) + return len(dl.receiptWorkers) } From 31440fb8cbbd9eaed96bfa7fb57566e0d9f29844 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 18:35:44 +0100 Subject: [PATCH 124/585] ref impl: downloader Close func --- opnode/l1/downloader.go | 37 +++++++++++++++++++++++++++++++++--- opnode/l1/downloader_test.go | 4 ++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go index 0cb4caca7206..9b2eb0f3332b 100644 --- a/opnode/l1/downloader.go +++ b/opnode/l1/downloader.go @@ -30,6 +30,11 @@ const ( receiptQueueSize = 100 ) +var ( + DownloadEvictedErr = errors.New("evicted") + DownloadClosedErr = errors.New("closed") +) + type downloadTask struct { // Incremented when Finish is called, to check whether the task already completed (with or without error). // May increment >1 when other sub-tasks fail. @@ -78,6 +83,7 @@ type receiptTask struct { type Downloader interface { Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) AddReceiptWorkers(n int) int + Close() } type DownloadSource interface { @@ -94,11 +100,10 @@ type downloader struct { receiptWorkers []ethereum.Subscription receiptWorkersLock sync.Mutex + // source to pull data from. Nil when downloader is closed src DownloadSource } -var downloadEvictedErr = errors.New("evicted") - func NewDownloader(dlSource DownloadSource) Downloader { dl := &downloader{ receiptTasks: make(chan *receiptTask, receiptQueueSize), @@ -106,7 +111,7 @@ func NewDownloader(dlSource DownloadSource) Downloader { } evict := func(k, v interface{}) { // stop downloading things if they were evicted (already finished items are unaffected) - v.(*downloadTask).Finish(wrappedErr{downloadEvictedErr}) + v.(*downloadTask).Finish(wrappedErr{DownloadEvictedErr}) } dl.cacheEvict, _ = lru.NewWithEvict(cacheSize, evict) return dl @@ -115,6 +120,10 @@ func NewDownloader(dlSource DownloadSource) Downloader { func (dl *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { // check if we are already working on it dl.cacheLock.Lock() + if dl.src == nil { + dl.cacheLock.Unlock() + return nil, nil, DownloadClosedErr + } var dlTask *downloadTask if dlTaskIfc, ok := dl.cacheEvict.Get(id.Hash); ok { @@ -234,3 +243,25 @@ func (dl *downloader) AddReceiptWorkers(n int) int { } return len(dl.receiptWorkers) } + +// Close unsubscribes and removes the receipt workers, then drains all remaining tasks +func (dl *downloader) Close() { + // nil the src to stop accepting new download tasks + dl.cacheLock.Lock() + if dl.src == nil { + return // already closed + } + dl.src = nil + dl.cacheLock.Unlock() + + dl.receiptWorkersLock.Lock() + defer dl.receiptWorkersLock.Unlock() + for _, w := range dl.receiptWorkers { + w.Unsubscribe() + } + dl.receiptWorkers = dl.receiptWorkers[:0] + close(dl.receiptTasks) + for task := range dl.receiptTasks { + task.dest.Finish(wrappedErr{DownloadClosedErr}) + } +} diff --git a/opnode/l1/downloader_test.go b/opnode/l1/downloader_test.go index 8bb9628d49f2..7529c695ca62 100644 --- a/opnode/l1/downloader_test.go +++ b/opnode/l1/downloader_test.go @@ -124,6 +124,10 @@ func TestDownloader_Fetch(t *testing.T) { t.Fatal("expected error, but got none") } } + dl.Close() + _, _, err = dl.Fetch(context.Background(), eth.BlockID{Hash: common.Hash{0xff}, Number: 42}) + assert.Error(t, err) + assert.ErrorIs(t, err, DownloadClosedErr) } testWithWorkers := func(workers int) { From 1c46c628c5761eef46f04540c64890e3a705ae55 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 18:52:01 +0100 Subject: [PATCH 125/585] ref impl: implement eth utils review suggestions by @norswap --- opnode/eth/canonical.go | 1 + opnode/eth/heads.go | 4 ++-- opnode/eth/source.go | 20 ++++++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/opnode/eth/canonical.go b/opnode/eth/canonical.go index 89a482032771..2a2e88d2e67e 100644 --- a/opnode/eth/canonical.go +++ b/opnode/eth/canonical.go @@ -12,6 +12,7 @@ type BlockLinkByNumber interface { BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) } +// BlockLinkByNumberFn implements BlockLinkByNumber to implement the interface as anonymous function type BlockLinkByNumberFn func(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) func (fn BlockLinkByNumberFn) BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) { diff --git a/opnode/eth/heads.go b/opnode/eth/heads.go index 1b729571ead7..1d1d1b595ad3 100644 --- a/opnode/eth/heads.go +++ b/opnode/eth/heads.go @@ -13,10 +13,10 @@ type HeadSignal struct { Self BlockID } -// HeadSignalFn is called to inform a chain with a new head +// HeadSignalFn is used as callback function to accept head-signals type HeadSignalFn func(sig HeadSignal) -// WatchHeadChanges wraps a new-head subscription from ChainReader to feed the given Tracker +// WatchHeadChanges wraps a new-head subscription from NewHeadSource to feed the given Tracker func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) (ethereum.Subscription, error) { headChanges := make(chan *types.Header, 10) sub, err := src.SubscribeNewHead(ctx, headChanges) diff --git a/opnode/eth/source.go b/opnode/eth/source.go index 95cadd68d1a6..368b2d5020af 100644 --- a/opnode/eth/source.go +++ b/opnode/eth/source.go @@ -10,6 +10,9 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// Source interfaces isolate individual ethereum.ChainReader methods, +// and enable anonymous functions to implement them. + type NewHeadSource interface { SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) } @@ -86,9 +89,10 @@ func (fn BlockByNumFn) BlockByNumber(ctx context.Context, number *big.Int) (*typ return fn(ctx, number) } -// CombinedL1Source balances multiple L1 sources, to shred concurrent requests to multiple endpoints +// CombinedL1Source implements round-robin between multiple L1 sources, +// to divide concurrent requests to multiple endpoints type CombinedL1Source struct { - i uint64 + i uint32 // track the last used source sources []L1Source } @@ -99,12 +103,16 @@ func NewCombinedL1Source(sources []L1Source) L1Source { return &CombinedL1Source{i: 0, sources: sources} } +func (cs *CombinedL1Source) nextSource() L1Source { + return cs.sources[atomic.AddUint32(&cs.i, 1)%uint32(len(cs.sources))] +} + func (cs *CombinedL1Source) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].HeaderByHash(ctx, hash) + return cs.nextSource().HeaderByHash(ctx, hash) } func (cs *CombinedL1Source) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].HeaderByNumber(ctx, number) + return cs.nextSource().HeaderByNumber(ctx, number) } func (cs *CombinedL1Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { @@ -113,11 +121,11 @@ func (cs *CombinedL1Source) SubscribeNewHead(ctx context.Context, ch chan<- *typ } func (cs *CombinedL1Source) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].TransactionReceipt(ctx, txHash) + return cs.nextSource().TransactionReceipt(ctx, txHash) } func (cs *CombinedL1Source) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return cs.sources[atomic.AddUint64(&cs.i, 1)%uint64(len(cs.sources))].BlockByHash(ctx, hash) + return cs.nextSource().BlockByHash(ctx, hash) } func (cs *CombinedL1Source) Close() { From 1a6bce9080705b5e165654ce397e20fbf30c4fa9 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 21:15:03 +0100 Subject: [PATCH 126/585] Reference implementation license --- README.md | 4 +++- opnode/LICENSE | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 opnode/LICENSE diff --git a/README.md b/README.md index d0a2e56fb553..fe19856cb6d4 100644 --- a/README.md +++ b/README.md @@ -45,4 +45,6 @@ shared publicly (we will ask for consent before recording). ## License -CC0 1.0 Universal, see [`LICENSE`](./LICENSE) file. +Specification: CC0 1.0 Universal, see [`LICENSE`](./LICENSE) file. + +Reference implementation: MIT, see [`opnode/LICENSE`](./opnode/LICENSE) file. diff --git a/opnode/LICENSE b/opnode/LICENSE new file mode 100644 index 000000000000..86541fdc788e --- /dev/null +++ b/opnode/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Optimism + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 059720a30fb4ae52919628b03af7489af442b8d3 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 14 Jan 2022 00:08:23 +0100 Subject: [PATCH 127/585] Move specs license to specs, clarify MIT applies to all reference software sources --- LICENSE | 137 ++++++------------------------------- README.md | 4 +- packages/contracts/LICENSE | 21 ++++++ specs/LICENSE | 116 +++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 118 deletions(-) create mode 100644 packages/contracts/LICENSE create mode 100644 specs/LICENSE diff --git a/LICENSE b/LICENSE index 670154e35388..86541fdc788e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,116 +1,21 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - +MIT License + +Copyright (c) 2022 Optimism + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index fe19856cb6d4..209c52137947 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,6 @@ shared publicly (we will ask for consent before recording). ## License -Specification: CC0 1.0 Universal, see [`LICENSE`](./LICENSE) file. +Specification: CC0 1.0 Universal, see [`specs/LICENSE`](./specs/LICENSE) file. -Reference implementation: MIT, see [`opnode/LICENSE`](./opnode/LICENSE) file. +Reference software: MIT, see [`LICENSE`](./LICENSE) file. diff --git a/packages/contracts/LICENSE b/packages/contracts/LICENSE new file mode 100644 index 000000000000..86541fdc788e --- /dev/null +++ b/packages/contracts/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Optimism + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/specs/LICENSE b/specs/LICENSE new file mode 100644 index 000000000000..670154e35388 --- /dev/null +++ b/specs/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + From 88ecc167d49def83ef39f26c9ee8d0df4044a918 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 14 Jan 2022 16:37:53 +0100 Subject: [PATCH 128/585] ref impl: cancel download task on eviction --- opnode/l1/downloader.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go index 9b2eb0f3332b..b18fccfadf68 100644 --- a/opnode/l1/downloader.go +++ b/opnode/l1/downloader.go @@ -53,6 +53,8 @@ type downloadTask struct { // stop fetching if this context is dead ctx context.Context + // to free up resources (e.g. ongoing receipt tasks) if a downloadTask finishes prematurely + cancel context.CancelFunc // feed to subscribe the requests to (de-duplicate work) feed event.Feed @@ -112,6 +114,7 @@ func NewDownloader(dlSource DownloadSource) Downloader { evict := func(k, v interface{}) { // stop downloading things if they were evicted (already finished items are unaffected) v.(*downloadTask).Finish(wrappedErr{DownloadEvictedErr}) + v.(*downloadTask).cancel() } dl.cacheEvict, _ = lru.NewWithEvict(cacheSize, evict) return dl @@ -130,7 +133,8 @@ func (dl *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, dlTask = dlTaskIfc.(*downloadTask) dl.cacheEvict.Add(id.Hash, dlTask) // add it again, so it moves to the front and avoid eviction } else { - dlTask = &downloadTask{ctx: ctx} + ctx, cancel := context.WithCancel(ctx) + dlTask = &downloadTask{ctx: ctx, cancel: cancel} dl.cacheEvict.Add(id.Hash, dlTask) // pull the block in the background From 7a1c7a570c6fd32626d7287ace4ffb7a79cef9b0 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 14 Jan 2022 13:45:55 -0500 Subject: [PATCH 129/585] add code coverage reporting for go in CI --- .github/workflows/go-ci.yml | 6 ++++-- .gitignore | 2 ++ README.md | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 1856a3bb3b1f..8a855b14c098 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -25,5 +25,7 @@ jobs: skip-go-installation: true # rules: https://golangci-lint.run/usage/quick-start/ args: -E asciicheck,goimports - - name: Test - run: go test ./... + - name: Test and generate coverage + run: go test -coverprofile=coverage.out -covermode=atomic ./... + - name: Upload coverage output + uses: codecov/codecov-action@v2 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 93cab344de41..8bba35cddc0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules yarn-error.log +coverage.out + diff --git a/README.md b/README.md index 209c52137947..4d723cfda863 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![codecov](https://codecov.io/gh/ethereum-optimism/optimistic-specs/branch/main/graph/badge.svg?token=19JPIN9XPB)](https://codecov.io/gh/ethereum-optimism/optimistic-specs) + # The Optimism Spec This repository holds the work-in-progress specification for the next version of From 47935ea97667bc1a1598c8b9df6234e4a5dfdca6 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 16:33:08 +0100 Subject: [PATCH 130/585] ref impl: more doc comments in downloader --- opnode/l1/downloader.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go index b18fccfadf68..75dfcdbb6f52 100644 --- a/opnode/l1/downloader.go +++ b/opnode/l1/downloader.go @@ -83,7 +83,20 @@ type receiptTask struct { } type Downloader interface { + // Fetch downloads a block and all the corresponding transaction receipts. + // Past and ongoing download jobs are cached in an LRU to de-duplicate work. + // + // If the Downloader is closed, then a DownloadClosedErr is returned. + // + // If the Downloader is stressed with too many new requests, + // a long call may be evicted and return a DownloadEvictedErr. + // + // If the provided ctx is done the download may also finish with the context error. + // + // Internal timeouts are maintained to ensure nothing halts the downloader indefinitely. Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) + // AddReceiptWorkers can add n parallel workers, or remove if n < 0, or no-op if n == 0. + // It then returns the new number of workers. AddReceiptWorkers(n int) int Close() } @@ -93,10 +106,19 @@ type DownloadSource interface { eth.ReceiptSource } +// downloader implements Downloader with parallel jobs, +// to work around the limited standard JSON-RPC that can only fetch receipts individually. +// +// The downloader maintains a LRU of past and ongoing requests, to de-duplicate work. +// After the first task of downloading the block completes, the transactions are mapped to receipt download tasks. +// Receipt tasks are queued up, split between parallel workers, and re-scheduled on failure up to 5 times. +// +// Receipt-downloading workers can be added/removed through AddReceiptWorkers at any time. type downloader struct { // cache of ongoing/completed block tasks: block hash -> block cacheEvict *lru.Cache - cacheLock sync.Mutex + // Get/Add calls need to be atomic to avoid duplicate jobs being created and added + cacheLock sync.Mutex receiptTasks chan *receiptTask receiptWorkers []ethereum.Subscription @@ -131,7 +153,6 @@ func (dl *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, var dlTask *downloadTask if dlTaskIfc, ok := dl.cacheEvict.Get(id.Hash); ok { dlTask = dlTaskIfc.(*downloadTask) - dl.cacheEvict.Add(id.Hash, dlTask) // add it again, so it moves to the front and avoid eviction } else { ctx, cancel := context.WithCancel(ctx) dlTask = &downloadTask{ctx: ctx, cancel: cancel} From 84211e350826b8c9d6514fe1a2de269c6b87f80a Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Sun, 9 Jan 2022 17:40:40 +0100 Subject: [PATCH 131/585] fix broken links --- specs/deposits.md | 16 ++++++------- specs/exec-engine.md | 6 ++--- specs/glossary.md | 56 +++++++++++++++++++++----------------------- specs/rollup-node.md | 32 ++++++++++++------------- 4 files changed, 54 insertions(+), 56 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index a70f7c200170..dddb69894d1d 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -1,12 +1,12 @@ # Deposits -[transaction-type]: /glossary.md#transaction-type -[derivation]: /glossary.md#L2-chain-derivation -[execution-engine]: /glossary.md#execution-engine -[deposits]: /glossary.md#deposits -[L1 attributes deposit]: /glossary.md#l1-attributes-deposit -[transaction deposits]: /glossary.md#transaction-deposits +[transaction-type]: glossary.md#transaction-type +[derivation]: glossary.md#L2-chain-derivation +[execution-engine]: glossary.md#execution-engine +[deposits]: glossary.md#deposits +[L1 attributes deposit]: glossary.md#l1-attributes-deposit +[transaction deposits]: glossary.md#transaction-deposits [Deposits] are transactions which are initiated on L1, and executed on L2. This document outlines a new [transaction type][transaction-type] for deposits. It also describes how deposits are initiated @@ -159,7 +159,7 @@ The contract has the following solidity interface, and can be interacted with ac A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. -[L1Block.sol]: /packages/contracts/contracts/L1Block.sol +[L1Block.sol]: /packages/contracts/contracts/L2/L1Block.sol The bytecode to add to the genesis file will be located in the `deployedBytecode` of the [JSON artifact file][l1-block-artifacts] corresponding to L1Block.sol. @@ -216,4 +216,4 @@ possible for users to interact with contracts on L2 even when the Sequencer is d A reference implementation of the Deposit Feed contract can be found in [DepositFeed.sol]. -[DepositFeed.sol]: /packages/contracts/contracts/DepositFeed.sol +[DepositFeed.sol]: /packages/contracts/contracts/L1/DepositFeed.sol diff --git a/specs/exec-engine.md b/specs/exec-engine.md index f3259c2e2e9e..36d2e1e85b79 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -7,12 +7,12 @@ This document outlines the modifications, configuration and usage of a L1 execut The Engine interfaces abstract away transaction types with [EIP-2718][eip-2718]. To support rollup functionality, processing of a new Deposit [`TransactionType`][eip-2718-transactions] -is implemented by the engine, see the [deposit specification][deposit-spec]. +is implemented by the engine, see the [deposits specification][deposit-spec]. This type of transaction can mint L2 ETH, run EVM, and introduce L1 information to enshrined contracts in the execution state. -[deposit-spec]: ./deposits#deposit-transaction-type +[deposit-spec]: deposits.md ### Deposit boundaries @@ -62,7 +62,7 @@ This `transactions` field is an optional JSON field: > **TODO**: derivation function spec in rollup node doc or separate driver doc -[rollup-driver]: ./rollup-driver.md +[rollup-driver]: rollup-node.md ### `engine_executePayloadV1` diff --git a/specs/glossary.md b/specs/glossary.md index 444b1c1e1930..58567ab194c3 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -33,20 +33,20 @@ ## Layer 1 (L1) -[L1]: /glossary.md#layer-1-L1 +[L1]: glossary.md#layer-1-L1 Refers the Ethereum blockchain, used in contrast to [layer 2][L2], which refers to Optimism. ## Layer 2 (L2) -[L2]: /glossary.md#layer-2-L2 +[L2]: glossary.md#layer-2-L2 Refers to the Optimism blockchain (specified in this repository), used in contrast to [layer 1][L1], which refers to the Ethereum blockchain. ## Block -[block]: /glossary.md#block +[block]: glossary.md#block Can refer to an [L1] block, or to an [L2] block, which are structured similarly. @@ -60,13 +60,13 @@ block, and output block properties, which are derived after executing the block' ## EOA -[EOA]: /glossary.md#EOA +[EOA]: glossary.md#EOA "Externally Owned Account", an Ethereum term to designate addresses operated by users, as opposed to contract addresses. ## Merkle Root -[Merkle root]: /glossary.md#merkle-roots +[Merkle root]: glossary.md#merkle-roots The Merkle root is the root hash of a [Merkle Patricia tree] (MPT). A MPT is a sparse [trie], which is a tree-like structure that maps keys to values. The root hash of a MPT is a commitment to the contents of the tree, which allows a @@ -75,7 +75,7 @@ verified against the Merkle root. ## Chain Re-Organization -[reorg]: /glossary.md#chain-re-organization +[reorg]: glossary.md#chain-re-organization A re-organization, or re-org for short, is whenever the head of a blockchain (its last block) changes (as dictated by the [fork choice rule]) to a block that is not a child of the previous head. @@ -85,7 +85,7 @@ L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a ## Predeployed Contract ("Predeploy") -[predeploy]: /glossary.md#predeployed-contract-predeploy +[predeploy]: glossary.md#predeployed-contract-predeploy A contract placed in the L2 genesis state (i.e. at the start of the chain). @@ -95,7 +95,7 @@ Optimism has the following predeploys: ## Receipt -[receipt]: /glossary.md#receipt +[receipt]: glossary.md#receipt A receipt is an output generated by a transaction, comprising a status code, the amount of gas used, a list of log entries, and a [bloom filter] indexing these entries. Log entries are most notably used to encode [Solidity events]. @@ -107,7 +107,7 @@ Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. ## Transaction Type -[transaction-type]: /glossary.md#transaction-type +[transaction-type]: glossary.md#transaction-type Ethereum provides a mechanism (as described in [EIP-2718]) for defining different transaction types. Different transaction types can contain different payloads, and be handled differently by the protocol. @@ -120,47 +120,47 @@ Different transaction types can contain different payloads, and be handled diffe ## Address Aliasing -[address-aliasing]: /glossary.md#address-aliasing +[address-aliasing]: glossary.md#address-aliasing When a contract submits a [deposit] from L1 to L2, it's address (as returned by `ORIGIN` and `CALLER`) will be aliased with a modified representation of the address of a contract. -- cf. [Deposit Specification](/deposits.md#address-aliasing) +- cf. [Deposit Specification](deposits.md#address-aliasing) ## L2 Chain Inception -[L2 chain inception]: /glossary.md#L2-chain-inception +[L2 chain inception]: glossary.md#L2-chain-inception The L1 block number for which the first block of the L2 chain was generated. ## Rollup Node -[rollup node]: /glossary.md#rollup-node +[rollup node]: glossary.md#rollup-node The rollup node is responsible for [deriving the L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their associated [receipts][receipt]). This is done by its [rollup driver] component. -- cf. [Rollup Node Specification](/rollup-node.md) +- cf. [Rollup Node Specification](rollup-node.md) ## Rollup Driver -[rollup driver]: /glossary.md#rollup-driver +[rollup driver]: glossary.md#rollup-driver The rollup driver is the [rollup node] component responsible for [deriving the L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their associated [receipts][receipt]). ## L2 Chain Derivation -[derivation]: /glossary.md#L2-chain-derivation +[derivation]: glossary.md#L2-chain-derivation A process that reads [L2 derivation inputs][deriv-inputs] from L1 in order to derive the L2 chain. cf. [L2 Chain Derivation (in Rollup Node -Specification)](/rollup-node.md#l2-chain-derivation) +Specification)](rollup-node.md#l2-chain-derivation) ## L2 Derivation Inputs -[deriv-inputs]: /glossary.md#l2-chain-derivation-inputs +[deriv-inputs]: glossary.md#l2-chain-derivation-inputs This term refers to data that is found in L1 blocks and is read by the [rollup node] to construct [payload attributes]. @@ -174,7 +174,7 @@ Chain derivation attributes include: ## Payload Attributes -[payload attributes]: /glossary.md#payload-attributes +[payload attributes]: glossary.md#payload-attributes This term refers to data that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are then passed to the [execution engine] to construct L2 blocks. @@ -189,7 +189,7 @@ this term. ## Deposits -[deposits]: /glossary.md#deposits +[deposits]: glossary.md#deposits A deposit is an L2 transaction derived from an L1 block. @@ -215,7 +215,7 @@ Deposits are specified in the [deposits specification][deposits-spec]. ## L1 Attributes Deposit -[l1-attributes-deposit]: /glossary.md#l1-attributes-deposit +[l1-attributes-deposit]: glossary.md#l1-attributes-deposit A [deposit][deposits] that is used to register the L1 block attributes (number, timestamp, ...) on L2 via a call to the [L1 Attributes Predeployed Contract][l1-attr-predeploy]. That contract can then be used to read the the attributes of @@ -240,25 +240,23 @@ specification. ## L1 Attributes Predeployed Contract -[l1-attr-predeploy]: /glossary.md#l1-attributes-predeployed-contract +[l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given block number or a given block hash. -cf. [L1 Attributes Predeployed Contract Specification](TODO) - -> **TODO LINK** L1 attributes predeployed contract spec +cf. [L1 Attributes Predeployed Contract Specification](#l1-attributes--reference-implementation) ## Deposit Transaction Type -[deposit-tx-type]: /glossary.md#deposit-transaction-type +[deposit-tx-type]: glossary.md#deposit-transaction-type The deposit transaction type is an [EIP-2718] [transaction type][transaction-type], which specifies the input fields and correct handling of a [deposit][deposits]. ## Deposit Feed Contract -[deposit-feed]: /glossary.md#deposit-feed-contract +[deposit-feed]: glossary.md#deposit-feed-contract An [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. @@ -275,7 +273,7 @@ cf. [Deposits Specification](deposits.md) ## Execution Engine -[execution-engine]: /glossary.md#execution-engine +[execution-engine]: glossary.md#execution-engine The execution engine is responsible for executing transactions in blocks and computing the resulting state roots, receipts roots and block hash. @@ -290,7 +288,7 @@ transactions [derived from L1 blocks][derivations]. In these specifications, "execution engine" always refer to the L2 execution engine, unless otherwise specified. -- cf. [Execution Engine Specification](/exec-engine.md) +- cf. [Execution Engine Specification](exec-engine.md) [Merkle Patricia tree]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md diff --git a/specs/rollup-node.md b/specs/rollup-node.md index f886ca4b82e2..3d7787b748c6 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -1,20 +1,20 @@ # Rollup Node Specification -[rollup node]: /glossary.md#rollup-node -[derivation]: /glossary.md#L2-chain-derivation -[payload attributes]: /glossary.md#payload-attributes -[block]: /glossary.md#block -[execution engine]: /glossary.md#execution-engine -[reorg]: /glossary.md#re-organization -[block gossip]: /glossary.md#block-gossip -[rollup driver]: /glossary.md#rollup-driver -[deposits]: /glossary.md#deposits -[deposit-feed]: /glossary.md#L2-deposit-feed-contract -[L2 chain inception]: /glossary.md#L2-chain-inception -[receipts]: /glossary.md#receipt -[L1 attributes deposit]: /glossary.md#l1-attributes-deposit -[transaction deposits]: /glossary.md#transaction-deposits +[rollup node]: glossary.md#rollup-node +[derivation]: glossary.md#L2-chain-derivation +[payload attributes]: glossary.md#payload-attributes +[block]: glossary.md#block +[execution engine]: glossary.md#execution-engine +[reorg]: glossary.md#re-organization +[block gossip]: glossary.md#block-gossip +[rollup driver]: glossary.md#rollup-driver +[deposits]: glossary.md#deposits +[deposit-feed]: glossary.md#L2-deposit-feed-contract +[L2 chain inception]: glossary.md#L2-chain-inception +[receipts]: glossary.md#receipt +[L1 attributes deposit]: glossary.md#l1-attributes-deposit +[transaction deposits]: glossary.md#transaction-deposits The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their associated [receipts]). This process happens in two steps: @@ -198,7 +198,7 @@ route. This has the same signature, except that: > **Note:** the properties of `ForkchoiceStateV1` can be used to anchor queries to the regular (non-engine-API) JSON-RPC > endpoint of the execution engine. [See here for more information.][L2-JSON-RPC-API] -[L2-JSON-RPC-API]: TODO +[L2-JSON-RPC-API]: exec-engine.md#engine-api > **TODO LINK** L2 JSON RPC API (might be the same as [L1's][JSON-RPC-API]) @@ -254,7 +254,7 @@ the descendant of an ancestor of the previous head). In those case, the rollup d set `headBlockHash` to the hash of the last processed L2 block (use the hash of the common ancestor initially) instead of the last L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated accordingly. -[block sync]: https://github.com/ethereum-optimism/optimistic-specs/blob/main/exec-engine.md#sync +[block sync]: exec-engine.md#sync > Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more > than `FINALIZATION_DELAY_BLOCKS == 50400` in the past, hence preserving our finalization guarantees. From f1ce827c1d28e423b2e0354cd857a10012e7210f Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Sun, 9 Jan 2022 17:41:00 +0100 Subject: [PATCH 132/585] automate link checking with lychee --- .github/workflows/lint.yml | 10 ++++++++++ package.json | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a7c83b5b7062..4c86eb1fe45e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -39,3 +39,13 @@ jobs: - name: Lint run: yarn lint:check + + linkChecker: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Link Checker + uses: lycheeverse/lychee-action@v1.2.0 + with: + fail: true diff --git a/package.json b/package.json index 976789013dd6..ccc488465ea4 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,10 @@ "markdownlint-cli2": "^0.3.2" }, "scripts": { + "setup": "yarn install && cargo install lychee", "lint": "yarn lint:fix && yarn lint:check", "lint:fix": "markdownlint-cli2-fix \"./specs/**/*.md\" \"#node_modules\"", - "lint:check": "markdownlint-cli2 \"./specs/**/*.md\" \"#node_modules\"" + "lint:check": "markdownlint-cli2 \"./specs/**/*.md\" \"#node_modules\"", + "lint:links": "lychee \"./specs/**/*.md\" --base ." } } From 4d68dd3585184f56fd890e1759c0eb7b6b36e385 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 10 Jan 2022 16:39:37 +0100 Subject: [PATCH 133/585] make lychee work with absolute links --- package.json | 2 +- specs/deposits.md | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ccc488465ea4..c7b09321ebbc 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,6 @@ "lint": "yarn lint:fix && yarn lint:check", "lint:fix": "markdownlint-cli2-fix \"./specs/**/*.md\" \"#node_modules\"", "lint:check": "markdownlint-cli2 \"./specs/**/*.md\" \"#node_modules\"", - "lint:links": "lychee \"./specs/**/*.md\" --base ." + "lint:links": "lychee \"./specs/**/*.md\"" } } diff --git a/specs/deposits.md b/specs/deposits.md index dddb69894d1d..05d1112bcfd9 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -159,10 +159,12 @@ The contract has the following solidity interface, and can be interacted with ac A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. -[L1Block.sol]: /packages/contracts/contracts/L2/L1Block.sol +[L1Block.sol]: ../packages/contracts/contracts/L2/L1Block.sol -The bytecode to add to the genesis file will be located in the `deployedBytecode` of the -[JSON artifact file][l1-block-artifacts] corresponding to L1Block.sol. +The bytecode to add to the genesis file will be located in the +`deployedBytecode` of the [JSON artifact file][l1-block-artifacts] corresponding +to L1Block.sol (this link will be broken unless you've built the contracts with +`yarn build` in the `packages/contracts` directory). [l1-block-artifacts]: /packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json @@ -216,4 +218,4 @@ possible for users to interact with contracts on L2 even when the Sequencer is d A reference implementation of the Deposit Feed contract can be found in [DepositFeed.sol]. -[DepositFeed.sol]: /packages/contracts/contracts/L1/DepositFeed.sol +[DepositFeed.sol]: ../packages/contracts/contracts/L1/DepositFeed.sol From 381688372c52c7957a380e7a66f2382abbdf6d7e Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 11 Jan 2022 16:55:30 +0100 Subject: [PATCH 134/585] fixes from review --- specs/deposits.md | 10 +++++----- specs/glossary.md | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 05d1112bcfd9..ea748005d9fa 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -208,11 +208,11 @@ The deposit feed handles two special cases: [address-aliasing]: #address-aliasing -If the caller is not a contract, the address will be ed by adding -`0x1111000000000000000000000000000000001111`. This prevents attacks in which a contract on L1 has -the same address as a contract on L2 but doesn't have the same code. We can safely ignore this for -EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes it -possible for users to interact with contracts on L2 even when the Sequencer is down. +If the caller is not a contract, the address will be transformed by adding +`0x1111000000000000000000000000000000001111` to it. This prevents attacks in which a contract on L1 +has the same address as a contract on L2 but doesn't have the same code. We can safely ignore this +for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes +it possible for users to interact with contracts on L2 even when the Sequencer is down. #### Deposit Feed: Reference Implementation diff --git a/specs/glossary.md b/specs/glossary.md index 58567ab194c3..619a7a1d97be 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -195,8 +195,8 @@ A deposit is an L2 transaction derived from an L1 block. There are two kinds of deposits: -- [L1 Attributes Deposit][l1-attribute-tx], which submit the L1 block's attributes to the [L1 Attributes Predeployed - Contract][l1-attr-predeploy]. +- [L1 Attributes Deposit][l1-attributes-deposit], which submits the L1 block's attributes to the [L1 Attributes + Predeployed Contract][l1-attr-predeploy]. - [Transaction Deposits][tx-deposits], which are transaction that have been submitted on L1, via a transaction sent to the [deposit feed contract][deposit-feed]. @@ -206,7 +206,7 @@ While transaction deposits are notably (but not only) used to "deposit" (bridge) The term *deposit* performs the double duty of referring to both: 1. The transaction information submitted on L1 to the [deposit feed contract][deposit-feed]. This is a kind of [L2 - derivation input][deriv-input]. + derivation input][deriv-inputs]. 2. The actual L2 transaction derived from this L1 input. Deposits are specified in the [deposits specification][deposits-spec]. From 8d6b9a82e6af7226a63a98408bce22cef7be7344 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 11 Jan 2022 17:05:59 +0100 Subject: [PATCH 135/585] fix more broken link refs, add fork choice rule definition --- specs/deposits.md | 2 +- specs/glossary.md | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index ea748005d9fa..7e2630ac4362 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -146,7 +146,7 @@ certain block variables from the corresponding L1 block in storage, so that they during the execution of the subsequent deposited transactions. The contract implements an authorization scheme, such that it only accepts state-changing calls from -the [depositor account]. +the [depositor account][depositor-account]. The contract has the following solidity interface, and can be interacted with according to the [contract ABI specification][ABI]. diff --git a/specs/glossary.md b/specs/glossary.md index 619a7a1d97be..98ea789e3aca 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -12,6 +12,7 @@ - [Predeployed Contract ("Predeploy")](#predeployed-contract-predeploy) - [Receipt](#receipt) - [Transaction Type](#transaction-type) + - [Fork Choice Rule](#fork-choice-rule) - [L2 Chain Concepts](#l2-chain-concepts) - [Address Aliasing](#address-aliasing) - [L2 Chain Inception](#l2-chain-inception) @@ -78,7 +79,7 @@ verified against the Merkle root. [reorg]: glossary.md#chain-re-organization A re-organization, or re-org for short, is whenever the head of a blockchain (its last block) changes (as dictated by -the [fork choice rule]) to a block that is not a child of the previous head. +the [fork choice rule][fork-choice-rule]) to a block that is not a child of the previous head. L1 re-orgs can happen because of network conditions or attacks. L2 re-orgs are a consequence of L1 re-orgs, mediated via [L2 chain derivation][derivation]. @@ -114,6 +115,18 @@ Different transaction types can contain different payloads, and be handled diffe [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 +## Fork Choice Rule + +[fork-choice-rule]: glossary.md#fork-choice-rule + +The fork choice rule is the rule used to determined which block is to be considered as the head of a blockchain. On L1, +this is determined by the proof of stake rules. + +L2 also has a fork choice rule, although the rules vary depending on wether we want the sequencer-confirmed head, the +on-chain-confirmed head, or the on-chain-finalized head. + +> TODO: define and link to those concepts + ------------------------------------------------------------------------------------------------------------------------ # L2 Chain Concepts @@ -122,8 +135,8 @@ Different transaction types can contain different payloads, and be handled diffe [address-aliasing]: glossary.md#address-aliasing -When a contract submits a [deposit] from L1 to L2, it's address (as returned by `ORIGIN` and `CALLER`) - will be aliased with a modified representation of the address of a contract. +When a contract submits a [deposit][deposits] from L1 to L2, it's address (as returned by `ORIGIN` and `CALLER`) will be +aliased with a modified representation of the address of a contract. - cf. [Deposit Specification](deposits.md#address-aliasing) @@ -177,7 +190,7 @@ Chain derivation attributes include: [payload attributes]: glossary.md#payload-attributes This term refers to data that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are then -passed to the [execution engine] to construct L2 blocks. +passed to the [execution engine][execution-engine] to construct L2 blocks. "Payload attributes" is a term that originates and is specified in the [Ethereum Engine API specification][engine-api], which we extend in this specification. @@ -284,7 +297,7 @@ On L1, the executed blocks can come from L1 block synchronization; or from a blo engine (using transactions from the L1 [mempool]), at the request of the L1 consensus layer. On L2, the executed blocks are freshly minted by the execution engine at the request of the [rollup node], using -transactions [derived from L1 blocks][derivations]. +transactions [derived from L1 blocks][derivation]. In these specifications, "execution engine" always refer to the L2 execution engine, unless otherwise specified. From 75c7023eb8c26a86ec95f530b06432cbd6443639 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Wed, 19 Jan 2022 16:43:27 +0100 Subject: [PATCH 136/585] remove link to generated file --- specs/deposits.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 7e2630ac4362..175ba5bd8af2 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -161,12 +161,9 @@ A reference implementation of the L1 Attributes predeploy contract can be found [L1Block.sol]: ../packages/contracts/contracts/L2/L1Block.sol -The bytecode to add to the genesis file will be located in the -`deployedBytecode` of the [JSON artifact file][l1-block-artifacts] corresponding -to L1Block.sol (this link will be broken unless you've built the contracts with -`yarn build` in the `packages/contracts` directory). - -[l1-block-artifacts]: /packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json +After running `yarn build` in the `packages/contracts` directory, the bytecode to add to the genesis +file will be located in the `deployedBytecode` field of the build artifacts file at +`/packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json`. ## L1 Transaction Deposits From a3ffa9a8c825d155a0469659b3101db5f41eecc4 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Wed, 19 Jan 2022 17:30:42 +0100 Subject: [PATCH 137/585] expand lychee linting and make CI similar to local --- .github/workflows/lint.yml | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4c86eb1fe45e..05107451c23e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -48,4 +48,5 @@ jobs: - name: Link Checker uses: lycheeverse/lychee-action@v1.2.0 with: + args: --verbose --no-progress --exclude twitter.com --exclude-mail README.md "./specs/**/*.md" "./meta/**/*.md" "./opnode/**/*.md" fail: true diff --git a/package.json b/package.json index c7b09321ebbc..f1302f9a1dfb 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,6 @@ "lint": "yarn lint:fix && yarn lint:check", "lint:fix": "markdownlint-cli2-fix \"./specs/**/*.md\" \"#node_modules\"", "lint:check": "markdownlint-cli2 \"./specs/**/*.md\" \"#node_modules\"", - "lint:links": "lychee \"./specs/**/*.md\"" + "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"" } } From 89a27f719c716a2226a3d23de2c5bf51ee6d6721 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 10 Jan 2022 23:31:00 +0100 Subject: [PATCH 138/585] ref impl: execution engine API client-bindings --- go.mod | 5 + go.sum | 4 + opnode/l2/api.go | 297 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 opnode/l2/api.go diff --git a/go.mod b/go.mod index 2f267216ff7e..2f0f38262db7 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.17 require ( github.com/ethereum/go-ethereum v1.10.13 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d + github.com/holiman/uint256 v1.2.0 github.com/protolambda/ask v0.1.2 github.com/stretchr/testify v1.7.0 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 @@ -16,9 +17,11 @@ require ( github.com/btcsuite/btcd v0.20.1-beta // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -30,7 +33,9 @@ require ( github.com/tklauser/numcpus v0.2.2 // indirect golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + ) replace github.com/ethereum/go-ethereum v1.10.13 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a diff --git a/go.sum b/go.sum index 31bb54ffe7b7..f2cb64c940d4 100644 --- a/go.sum +++ b/go.sum @@ -91,6 +91,7 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 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 v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= 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= @@ -181,6 +182,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 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 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= @@ -189,6 +191,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= 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 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= @@ -575,6 +578,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN 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/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/opnode/l2/api.go b/opnode/l2/api.go new file mode 100644 index 000000000000..9f5a827de1d4 --- /dev/null +++ b/opnode/l2/api.go @@ -0,0 +1,297 @@ +package l2 + +import ( + "context" + "fmt" + "reflect" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/holiman/uint256" + + "github.com/ethereum/go-ethereum/rpc" +) + +type ErrorCode int + +const ( + UnavailablePayload ErrorCode = -32001 +) + +type Bytes32 [32]byte + +func (b *Bytes32) UnmarshalJSON(text []byte) error { + return hexutil.UnmarshalFixedJSON(reflect.TypeOf(b), text, b[:]) +} + +func (b *Bytes32) UnmarshalText(text []byte) error { + return hexutil.UnmarshalFixedText("Bytes32", text, b[:]) +} + +func (b Bytes32) MarshalText() ([]byte, error) { + return hexutil.Bytes(b[:]).MarshalText() +} + +func (b Bytes32) String() string { + return hexutil.Encode(b[:]) +} + +type Bytes256 [256]byte + +func (b *Bytes256) UnmarshalJSON(text []byte) error { + return hexutil.UnmarshalFixedJSON(reflect.TypeOf(b), text, b[:]) +} + +func (b *Bytes256) UnmarshalText(text []byte) error { + return hexutil.UnmarshalFixedText("Bytes32", text, b[:]) +} + +func (b Bytes256) MarshalText() ([]byte, error) { + return hexutil.Bytes(b[:]).MarshalText() +} + +func (b Bytes256) String() string { + return hexutil.Encode(b[:]) +} + +type Uint64Quantity = hexutil.Uint64 + +type BytesMax32 []byte + +func (b *BytesMax32) UnmarshalJSON(text []byte) error { + if len(text) > 64+2+2 { // account for delimiter "", and 0x prefix + return fmt.Errorf("input too long, expected at most 32 hex-encoded, 0x-prefixed, bytes: %x", text) + } + return (*hexutil.Bytes)(b).UnmarshalJSON(text) +} + +func (b *BytesMax32) UnmarshalText(text []byte) error { + if len(text) > 64+2 { // account for 0x prefix + return fmt.Errorf("input too long, expected at most 32 hex-encoded, 0x-prefixed, bytes: %x", text) + } + return (*hexutil.Bytes)(b).UnmarshalText(text) +} + +func (b BytesMax32) MarshalText() ([]byte, error) { + return (hexutil.Bytes)(b).MarshalText() +} + +func (b BytesMax32) String() string { + return hexutil.Encode(b) +} + +type Uint256Quantity = uint256.Int + +type Data = hexutil.Bytes + +// TODO: implement neat 8 byte typed payload ID and upstream it to geth api definitions +type PayloadID = hexutil.Bytes + +type ExecutionPayload struct { + ParentHash common.Hash `json:"parentHash"` + FeeRecipient common.Address `json:"feeRecipient"` + StateRoot Bytes32 `json:"stateRoot"` + ReceiptsRoot Bytes32 `json:"receiptsRoot"` + LogsBloom Bytes256 `json:"logsBloom"` + Random Bytes32 `json:"random"` + BlockNumber Uint64Quantity `json:"blockNumber"` + GasLimit Uint64Quantity `json:"gasLimit"` + GasUsed Uint64Quantity `json:"gasUsed"` + Timestamp Uint64Quantity `json:"timestamp"` + ExtraData BytesMax32 `json:"extraData"` + BaseFeePerGas Uint256Quantity `json:"baseFeePerGas"` + BlockHash common.Hash `json:"blockHash"` + // Array of transaction objects, each object is a byte list (DATA) representing + // TransactionType || TransactionPayload or LegacyTransaction as defined in EIP-2718 + Transactions []Data `json:"transactions"` +} + +func (payload *ExecutionPayload) ID() eth.BlockID { + return eth.BlockID{Hash: payload.BlockHash, Number: uint64(payload.BlockNumber)} +} + +type PayloadAttributes struct { + // value for the timestamp field of the new payload + Timestamp Uint64Quantity `json:"timestamp"` + // value for the random field of the new payload + Random Bytes32 `json:"random"` + // suggested value for the coinbase field of the new payload + SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient"` + // Transactions to build the block with, omitted if the local tx pool of the engine should be used instead + Transactions []Data `json:"transactions,omitempty"` +} + +type ExecutePayloadStatus string + +const ( + // given payload is valid + ExecutionValid ExecutePayloadStatus = "VALID" + // given payload is invalid + ExecutionInvalid ExecutePayloadStatus = "INVALID" + // sync process is in progress + ExecutionSyncing ExecutePayloadStatus = "SYNCING" +) + +type ExecutePayloadResult struct { + // the result of the payload execution + Status ExecutePayloadStatus `json:"status"` + // the hash of the most recent valid block in the branch defined by payload and its ancestors + LatestValidHash common.Hash `json:"latestValidHash"` + // additional details on the result + ValidationError string `json:"validationError"` +} + +type ForkchoiceState struct { + // block hash of the head of the canonical chain + HeadBlockHash common.Hash `json:"headBlockHash"` + // safe block hash in the canonical chain + SafeBlockHash common.Hash `json:"safeBlockHash"` + // block hash of the most recent finalized block + FinalizedBlockHash common.Hash `json:"finalizedBlockHash"` +} + +type ForkchoiceUpdatedStatus string + +const ( + // given payload is valid + UpdateSuccess ForkchoiceUpdatedStatus = "SUCCESS" + // sync process is in progress + UpdateSyncing ForkchoiceUpdatedStatus = "SYNCING" +) + +type ForkchoiceUpdatedResult struct { + // the result of the payload execution + Status ForkchoiceUpdatedStatus `json:"status"` + // the payload id if requested + PayloadID *PayloadID `json:"payloadId"` +} + +type EngineAPI interface { + GetPayload(ctx context.Context, payloadId PayloadID) (*ExecutionPayload, error) + ExecutePayload(ctx context.Context, payload *ExecutionPayload) (*ExecutePayloadResult, error) + ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) + Close() +} + +type RPCBackend interface { + CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error + Close() +} + +type EthBackend interface { + eth.BlockByHashSource + eth.BlockByNumberSource + eth.NewHeadSource +} + +type EngineClient struct { + RPCBackend + EthBackend + Log log.Logger +} + +func (el *EngineClient) GetPayload(ctx context.Context, payloadId PayloadID) (*ExecutionPayload, error) { + e := el.Log.New("payload_id", payloadId) + e.Debug("getting payload") + var result ExecutionPayload + err := el.CallContext(ctx, &result, "engine_getPayloadV1", payloadId) + if err != nil { + e = log.New("payload_id", "err", err) + if rpcErr, ok := err.(rpc.Error); ok { + code := ErrorCode(rpcErr.ErrorCode()) + if code != UnavailablePayload { + e.Warn("unexpected error code in get-payload response", "code", code) + } else { + e.Warn("unavailable payload in get-payload request") + } + } else { + e.Error("failed to get payload") + } + return nil, err + } + e.Debug("Received payload") + return &result, nil +} + +func (el *EngineClient) ExecutePayload(ctx context.Context, payload *ExecutionPayload) (*ExecutePayloadResult, error) { + e := el.Log.New("block_hash", payload.BlockHash) + e.Debug("sending payload for execution") + var result ExecutePayloadResult + err := el.CallContext(ctx, &result, "engine_executePayloadV1", payload) + if err != nil { + e.Error("Payload execution failed", "err", err) + return nil, err + } + e.Debug("Received payload execution result", "status", result.Status, "latestValidHash", result.LatestValidHash, "message", result.ValidationError) + return &result, nil +} + +func (el *EngineClient) ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) { + e := el.Log.New("state", state, "attr", attr) + e.Debug("Sharing forkchoice-updated signal") + + var result ForkchoiceUpdatedResult + err := el.CallContext(ctx, &result, "engine_forkchoiceUpdatedV1", state, attr) + if err == nil { + e.Debug("Shared forkchoice-updated signal") + if attr != nil { + e.Debug("Received payload id", "payloadId", result.PayloadID) + } + return result, nil + } else { + e = e.New("err", err) + if rpcErr, ok := err.(rpc.Error); ok { + code := ErrorCode(rpcErr.ErrorCode()) + e.Warn("Unexpected error code in forkchoice-updated response", "code", code) + } else { + e.Error("Failed to share forkchoice-updated signal") + } + return result, err + } +} + +func (el *EngineClient) Close() { + el.RPCBackend.Close() +} + +func BlockToPayload(bl *types.Block, random Bytes32) (*ExecutionPayload, error) { + extra := bl.Extra() + if len(extra) > 32 { + return nil, fmt.Errorf("eth2 merge spec limits extra data to 32 bytes in payload, got %d", len(extra)) + } + baseFee, overflow := uint256.FromBig(bl.BaseFee()) + if overflow { + return nil, fmt.Errorf("overflowing base fee") + } + txs := bl.Transactions() + txsEncoded := make([]Data, 0, len(txs)) + for i, tx := range txs { + txOpaque, err := tx.MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to encode tx %d", i) + } + txsEncoded = append(txsEncoded, txOpaque) + } + return &ExecutionPayload{ + ParentHash: bl.ParentHash(), + FeeRecipient: bl.Coinbase(), + StateRoot: Bytes32(bl.Root()), + ReceiptsRoot: Bytes32(bl.ReceiptHash()), + LogsBloom: Bytes256(bl.Bloom()), + Random: random, + BlockNumber: Uint64Quantity(bl.NumberU64()), + GasLimit: Uint64Quantity(bl.GasLimit()), + GasUsed: Uint64Quantity(bl.GasUsed()), + Timestamp: Uint64Quantity(bl.Time()), + ExtraData: BytesMax32(extra), + BaseFeePerGas: Uint256Quantity(*baseFee), + BlockHash: bl.Hash(), + Transactions: txsEncoded, + }, nil +} From a5d35dad5ea12cc121f6f5ed4c6b3b6b901e1e51 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 10 Jan 2022 23:31:00 +0100 Subject: [PATCH 139/585] ref impl: execution engine API client-bindings --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index 2f0f38262db7..fe6901c885bc 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,6 @@ require ( golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect - ) replace github.com/ethereum/go-ethereum v1.10.13 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a From d43370019f7a0875919782965b3fefdf2ba8003c Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 10 Jan 2022 23:57:17 +0100 Subject: [PATCH 140/585] ref impl: input derivation and reading l1-info Co-authored-by: Nicolas "Norswap" Laurent --- opnode/l2/input_derivation.go | 209 +++++++++++++++++++++++++++++ opnode/l2/input_derivation_test.go | 195 +++++++++++++++++++++++++++ opnode/l2/reading.go | 69 ++++++++++ opnode/l2/reading_test.go | 108 +++++++++++++++ 4 files changed, 581 insertions(+) create mode 100644 opnode/l2/input_derivation.go create mode 100644 opnode/l2/input_derivation_test.go create mode 100644 opnode/l2/reading.go create mode 100644 opnode/l2/reading_test.go diff --git a/opnode/l2/input_derivation.go b/opnode/l2/input_derivation.go new file mode 100644 index 000000000000..74febfd46b63 --- /dev/null +++ b/opnode/l2/input_derivation.go @@ -0,0 +1,209 @@ +package l2 + +import ( + "encoding/binary" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/trie" + "github.com/holiman/uint256" +) + +var ( + DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint256,bool,bytes)" + DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) + DepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") + L1InfoFuncSignature = "setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash)" + L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] + L1InfoPredeployAddr = common.HexToAddress("0x4242424242424242424242424242424242424242") +) + +// UnmarshalLogEvent decodes an EVM log entry emitted by the deposit contract into typed deposit data. +// +// parse log data for: +// event TransactionDeposited( +// address indexed from, +// address indexed to, +// uint256 mint, +// uint256 value, +// uint256 gasLimit, +// bool isCreation, +// data data +// ); +// +// Deposits additionally get: +// - blockNum matching the L1 block height +// - txIndex: matching the deposit index, not L1 transaction index, since there can be multiple deposits per L1 tx +func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.DepositTx, error) { + if len(ev.Topics) != 3 { + return nil, fmt.Errorf("expected 3 event topics (event identity, indexed from, indexed to)") + } + if ev.Topics[0] != DepositEventABIHash { + return nil, fmt.Errorf("invalid deposit event selector: %s, expected %s", ev.Topics[0], DepositEventABIHash) + } + if len(ev.Data) < 7*32 { + return nil, fmt.Errorf("deposit event data too small (%d bytes): %x", len(ev.Data), ev.Data) + } + + var dep types.DepositTx + + dep.BlockHeight = blockNum + dep.TransactionIndex = txIndex + + // indexed 0 + dep.From = common.BytesToAddress(ev.Topics[1][12:]) + // indexed 1 + to := common.BytesToAddress(ev.Topics[2][12:]) + + // unindexed data + offset := uint64(0) + dep.Value = new(big.Int).SetBytes(ev.Data[offset : offset+32]) + offset += 32 + + dep.Mint = new(big.Int).SetBytes(ev.Data[offset : offset+32]) + // 0 mint is represented as nil to skip minting code + if dep.Mint.Cmp(new(big.Int)) == 0 { + dep.Mint = nil + } + offset += 32 + + gas := new(big.Int).SetBytes(ev.Data[offset : offset+32]) + if !gas.IsUint64() { + return nil, fmt.Errorf("bad gas value: %x", ev.Data[offset:offset+32]) + } + offset += 32 + dep.Gas = gas.Uint64() + // isCreation: If the boolean byte is 1 then dep.To will stay nil, + // and it will create a contract using L2 account nonce to determine the created address. + if ev.Data[offset+31] == 0 { + dep.To = &to + } + offset += 32 + var dataOffset uint256.Int + dataOffset.SetBytes(ev.Data[offset : offset+32]) + offset += 32 + if dataOffset.Eq(uint256.NewInt(128)) { + return nil, fmt.Errorf("incorrect data offset: %v", dataOffset[0]) + } + + var dataLen uint256.Int + dataLen.SetBytes(ev.Data[offset : offset+32]) + offset += 32 + if !dataLen.IsUint64() || dataLen.Uint64() != uint64(len(ev.Data))-offset { + return nil, fmt.Errorf("inconsistent data length: %s, expected %d", dataLen.String(), uint64(len(ev.Data))-offset) + } + + // remaining bytes fill the data + dep.Data = ev.Data[offset:] + + return &dep, nil +} + +type L1Info interface { + NumberU64() uint64 + Time() uint64 + Hash() common.Hash + BaseFee() *big.Int +} + +func DeriveL1InfoDeposit(block L1Info) *types.DepositTx { + data := make([]byte, 4+8+8+32+32) + offset := 0 + copy(data[offset:4], L1InfoFuncBytes4) + offset += 4 + binary.BigEndian.PutUint64(data[offset:offset+8], block.NumberU64()) + offset += 8 + binary.BigEndian.PutUint64(data[offset:offset+8], block.Time()) + offset += 8 + block.BaseFee().FillBytes(data[offset : offset+32]) + offset += 32 + copy(data[offset:offset+32], block.Hash().Bytes()) + + return &types.DepositTx{ + BlockHeight: block.NumberU64(), + TransactionIndex: 0, // always the first transaction + From: DepositContractAddr, + To: &L1InfoPredeployAddr, + Mint: nil, + Value: big.NewInt(0), + Gas: 99_999_999, + Data: data, + } +} + +type ReceiptHash interface { + ReceiptHash() common.Hash +} + +// CheckReceipts sanity checks that the receipts are consistent with the block data. +func CheckReceipts(block ReceiptHash, receipts []*types.Receipt) bool { + hasher := trie.NewStackTrie(nil) + computed := types.DeriveSha(types.Receipts(receipts), hasher) + return block.ReceiptHash() == computed +} + +// DeriveL2Transactions transforms a L1 block and corresponding receipts into the transaction inputs for a full L2 block +func DeriveUserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, error) { + var out []*types.DepositTx + + for _, rec := range receipts { + if rec.Status != types.ReceiptStatusSuccessful { + continue + } + for _, log := range rec.Logs { + if log.Address == DepositContractAddr { + // offset transaction index by 1, the first is the l1-info tx + dep, err := UnmarshalLogEvent(height, uint64(len(out))+1, log) + if err != nil { + return nil, fmt.Errorf("malformatted L1 deposit log: %v", err) + } + out = append(out, dep) + } + } + } + return out, nil +} + +type BlockInput interface { + ReceiptHash + L1Info + MixDigest() common.Hash +} + +func DeriveBlockInputs(block BlockInput, receipts []*types.Receipt) (*PayloadAttributes, error) { + if !CheckReceipts(block, receipts) { + return nil, fmt.Errorf("receipts are not consistent with the block's receipts root: %s", block.ReceiptHash()) + } + + l1Tx := types.NewTx(DeriveL1InfoDeposit(block)) + opaqueL1Tx, err := l1Tx.MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to encode L1 info tx") + } + + userDeposits, err := DeriveUserDeposits(block.NumberU64(), receipts) + if err != nil { + return nil, fmt.Errorf("failed to derive user deposits: %v", err) + } + + encodedTxs := make([]Data, 0, len(userDeposits)+1) + encodedTxs = append(encodedTxs, opaqueL1Tx) + + for i, tx := range userDeposits { + opaqueTx, err := types.NewTx(tx).MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to encode user tx %d", i) + } + encodedTxs = append(encodedTxs, opaqueTx) + } + + return &PayloadAttributes{ + Timestamp: Uint64Quantity(block.Time()), + Random: Bytes32(block.MixDigest()), + SuggestedFeeRecipient: common.Address{}, // nobody gets tx fees for deposits + Transactions: encodedTxs, + }, nil +} diff --git a/opnode/l2/input_derivation_test.go b/opnode/l2/input_derivation_test.go new file mode 100644 index 000000000000..29ffae388a54 --- /dev/null +++ b/opnode/l2/input_derivation_test.go @@ -0,0 +1,195 @@ +package l2 + +import ( + "encoding/binary" + "fmt" + "math/big" + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +func GenerateAddress(rng *rand.Rand) (out common.Address) { + rng.Read(out[:]) + return +} + +func RandETH(rng *rand.Rand, max int64) *big.Int { + x := big.NewInt(rng.Int63n(max)) + x = new(big.Int).Mul(x, big.NewInt(1e18)) + return x +} + +// Returns a DepositEvent customized on the basis of the id parameter. +func GenerateDeposit(blockNum uint64, txIndex uint64, rng *rand.Rand) *types.DepositTx { + dataLen := rng.Int63n(10_000) + data := make([]byte, dataLen) + rng.Read(data) + + var to *common.Address + if rng.Intn(2) == 0 { + x := GenerateAddress(rng) + to = &x + } + var mint *big.Int + if rng.Intn(2) == 0 { + mint = RandETH(rng, 200) + } + + dep := &types.DepositTx{ + BlockHeight: blockNum, + TransactionIndex: txIndex, + From: GenerateAddress(rng), + To: to, + Value: RandETH(rng, 200), + Gas: uint64(rng.Int63n(10 * 1e6)), // 10 M gas max + Data: data, + Mint: mint, + } + return dep +} + +// Generates an EVM log entry that encodes a TransactionDeposited event from the deposit contract. +// Calls GenerateDeposit with random number generator to generate the deposit. +func GenerateDepositLog(deposit *types.DepositTx) *types.Log { + + toBytes := common.Hash{} + if deposit.To != nil { + toBytes = deposit.To.Hash() + } + topics := []common.Hash{ + DepositEventABIHash, + deposit.From.Hash(), + toBytes, + } + + data := make([]byte, 6*32) + offset := 0 + deposit.Value.FillBytes(data[offset : offset+32]) + offset += 32 + + if deposit.Mint != nil { + deposit.Mint.FillBytes(data[offset : offset+32]) + } + offset += 32 + + binary.BigEndian.PutUint64(data[offset+24:offset+32], deposit.Gas) + offset += 32 + if deposit.To == nil { // isCreation + data[offset+31] = 1 + } + offset += 32 + binary.BigEndian.PutUint64(data[offset+24:offset+32], 5*32) + offset += 32 + binary.BigEndian.PutUint64(data[offset+24:offset+32], uint64(len(deposit.Data))) + data = append(data, deposit.Data...) + + return GenerateLog(DepositContractAddr, topics, data) +} + +// Generates an EVM log entry with the given topics and data. +func GenerateLog(addr common.Address, topics []common.Hash, data []byte) *types.Log { + return &types.Log{ + Address: addr, + Topics: topics, + Data: data, + Removed: false, + + // ignored (zeroed): + BlockNumber: 0, + TxHash: common.Hash{}, + TxIndex: 0, + BlockHash: common.Hash{}, + Index: 0, + } +} + +func TestUnmarshalLogEvent(t *testing.T) { + for i := int64(0); i < 100; i++ { + t.Run(fmt.Sprintf("random_deposit_%d", i), func(t *testing.T) { + rng := rand.New(rand.NewSource(1234 + i)) + blockNum := rng.Uint64() + txIndex := uint64(rng.Intn(10000)) + depInput := GenerateDeposit(blockNum, txIndex, rng) + log := GenerateDepositLog(depInput) + depOutput, err := UnmarshalLogEvent(blockNum, txIndex, log) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, depInput, depOutput) + }) + } +} + +// DeriveL1InfoDeposit is tested in reading_test.go, combined with the inverse ParseL1InfoDepositTxData + +// receiptData defines what a test receipt looks like +type receiptData struct { + // false = failed tx + goodReceipt bool + // false = not a deposit log + DepositLogs []bool +} + +type DeriveUserDepositsTestCase struct { + name string + height uint64 + // generate len(receipts) receipts + receipts []receiptData +} + +func TestDeriveUserDeposits(t *testing.T) { + testCases := []DeriveUserDepositsTestCase{ + {"no deposits", 100, []receiptData{}}, + {"other log", 100, []receiptData{{true, []bool{false}}}}, + {"success deposit", 100, []receiptData{{true, []bool{true}}}}, + {"failed deposit", 100, []receiptData{{false, []bool{true}}}}, + {"mixed deposits", 100, []receiptData{{true, []bool{true}}, {false, []bool{true}}}}, + {"success multiple logs", 100, []receiptData{{true, []bool{true, true}}}}, + {"failed multiple logs", 100, []receiptData{{false, []bool{true, true}}}}, + {"not all deposit logs", 100, []receiptData{{true, []bool{true, false, true}}}}, + {"random", 100, []receiptData{{true, []bool{false, false, true}}, {false, []bool{}}, {true, []bool{true}}}}, + } + for i, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + rng := rand.New(rand.NewSource(1234 + int64(i))) + var receipts []*types.Receipt + var expectedDeposits []*types.DepositTx + for _, rData := range testCase.receipts { + var logs []*types.Log + status := types.ReceiptStatusSuccessful + if !rData.goodReceipt { + status = types.ReceiptStatusFailed + } + for _, isDeposit := range rData.DepositLogs { + if isDeposit { + dep := GenerateDeposit(testCase.height, uint64(1+len(expectedDeposits)), rng) + if status == types.ReceiptStatusSuccessful { + expectedDeposits = append(expectedDeposits, dep) + } + logs = append(logs, GenerateDepositLog(dep)) + } else { + logs = append(logs, GenerateLog(GenerateAddress(rng), nil, nil)) + } + } + + receipts = append(receipts, &types.Receipt{ + Type: types.DynamicFeeTxType, + Status: status, + Logs: logs, + }) + } + got, err := DeriveUserDeposits(testCase.height, receipts) + assert.NoError(t, err) + assert.Equal(t, len(got), len(expectedDeposits)) + for d, depTx := range got { + expected := expectedDeposits[d] + assert.Equal(t, expected, depTx) + } + }) + } +} diff --git a/opnode/l2/reading.go b/opnode/l2/reading.go new file mode 100644 index 000000000000..bcb55b83bab1 --- /dev/null +++ b/opnode/l2/reading.go @@ -0,0 +1,69 @@ +package l2 + +import ( + "encoding/binary" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// ParseL1InfoDepositTxData is the inverse of DeriveL1InfoDeposit, to see where the L2 chain is derived from +func ParseL1InfoDepositTxData(data []byte) (nr uint64, time uint64, baseFee *big.Int, blockHash common.Hash, err error) { + if len(data) != 4+8+8+32+32 { + err = fmt.Errorf("data is unexpected length: %d", len(data)) + return + } + offset := 4 + nr = binary.BigEndian.Uint64(data[offset : offset+8]) + offset += 8 + time = binary.BigEndian.Uint64(data[offset : offset+8]) + offset += 8 + baseFee = new(big.Int).SetBytes(data[offset : offset+32]) + offset += 32 + blockHash.SetBytes(data[offset : offset+32]) + return +} + +type Block interface { + Hash() common.Hash + NumberU64() uint64 + ParentHash() common.Hash + Transactions() types.Transactions +} + +type Genesis struct { + L1 eth.BlockID + L2 eth.BlockID +} + +// ParseBlockReferences takes a L2 block and determines which L1 block it was derived from, and the L2 self and parent id. +func ParseBlockReferences(refL2Block Block, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { + refL2 = eth.BlockID{Hash: refL2Block.Hash(), Number: refL2Block.NumberU64()} + if refL2.Number <= genesis.L2.Number { + if refL2.Hash != genesis.L2.Hash { + err = fmt.Errorf("unexpected L2 genesis block: %s, expected %s", refL2, genesis.L2) + return + } + refL1 = genesis.L1 + refL2 = genesis.L2 + parentL2 = common.Hash{} + return + } + + parentL2 = refL2Block.ParentHash() + txs := refL2Block.Transactions() + if len(txs) == 0 || txs[0].Type() != types.DepositTxType { + err = fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", refL2Block.Hash()) + return + } + refL1Nr, _, _, refL1Hash, err := ParseL1InfoDepositTxData(txs[0].Data()) + if err != nil { + err = fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) + return + } + refL1 = eth.BlockID{Hash: refL1Hash, Number: refL1Nr} + return +} diff --git a/opnode/l2/reading_test.go b/opnode/l2/reading_test.go new file mode 100644 index 000000000000..857c27a0ccc2 --- /dev/null +++ b/opnode/l2/reading_test.go @@ -0,0 +1,108 @@ +package l2 + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +type l1MockInfo struct { + num uint64 + time uint64 + hash common.Hash + baseFee *big.Int +} + +func (l *l1MockInfo) NumberU64() uint64 { + return l.num +} + +func (l *l1MockInfo) Time() uint64 { + return l.time +} + +func (l *l1MockInfo) Hash() common.Hash { + return l.hash +} + +func (l *l1MockInfo) BaseFee() *big.Int { + return l.baseFee +} + +func randomHash(rng *rand.Rand) (out common.Hash) { + rng.Read(out[:]) + return +} + +func randomL1Info(rng *rand.Rand) *l1MockInfo { + return &l1MockInfo{ + num: rng.Uint64(), + time: rng.Uint64(), + hash: randomHash(rng), + baseFee: big.NewInt(rng.Int63n(1000_0000 * 1e9)), // a million GWEI + } +} + +func makeInfo(fn func(l *l1MockInfo)) func(rng *rand.Rand) *l1MockInfo { + return func(rng *rand.Rand) *l1MockInfo { + l := randomL1Info(rng) + if fn != nil { + fn(l) + } + return l + } +} + +var _ L1Info = (*l1MockInfo)(nil) + +type infoTest struct { + name string + mkInfo func(rng *rand.Rand) *l1MockInfo +} + +func TestParseL1InfoDepositTxData(t *testing.T) { + // Go 1.18 will have native fuzzing for us to use, until then, we cover just the below cases + cases := []infoTest{ + {"random", makeInfo(nil)}, + {"zero basefee", makeInfo(func(l *l1MockInfo) { + l.baseFee = new(big.Int) + })}, + {"zero time", makeInfo(func(l *l1MockInfo) { + l.time = 0 + })}, + {"zero num", makeInfo(func(l *l1MockInfo) { + l.num = 0 + })}, + {"all zero", func(rng *rand.Rand) *l1MockInfo { + return &l1MockInfo{baseFee: new(big.Int)} + }}, + } + for i, testCase := range cases { + t.Run(testCase.name, func(t *testing.T) { + info := testCase.mkInfo(rand.New(rand.NewSource(int64(1234 + i)))) + depTx := DeriveL1InfoDeposit(info) + nr, time, baseFee, h, err := ParseL1InfoDepositTxData(depTx.Data) + assert.NoError(t, err, "expected valid deposit info") + assert.Equal(t, nr, info.num) + assert.Equal(t, time, info.time) + assert.True(t, baseFee.Sign() >= 0) + assert.Equal(t, baseFee.Bytes(), info.baseFee.Bytes()) + assert.Equal(t, h, info.hash) + }) + } + t.Run("no data", func(t *testing.T) { + _, _, _, _, err := ParseL1InfoDepositTxData(nil) + assert.Error(t, err) + }) + t.Run("not enough data", func(t *testing.T) { + _, _, _, _, err := ParseL1InfoDepositTxData([]byte{1, 2, 3, 4}) + assert.Error(t, err) + }) + t.Run("too much data", func(t *testing.T) { + _, _, _, _, err := ParseL1InfoDepositTxData(make([]byte, 4+8+8+32+32+1)) + assert.Error(t, err) + }) +} From 09a7098d9ac9c3e49b1fb1565fd51eb1c75989b4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 20:16:28 +0100 Subject: [PATCH 141/585] ref impl: fix data minimum length, bug found by @trianglesphere --- opnode/l2/input_derivation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/l2/input_derivation.go b/opnode/l2/input_derivation.go index 74febfd46b63..fded7b31cd5b 100644 --- a/opnode/l2/input_derivation.go +++ b/opnode/l2/input_derivation.go @@ -44,7 +44,7 @@ func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.D if ev.Topics[0] != DepositEventABIHash { return nil, fmt.Errorf("invalid deposit event selector: %s, expected %s", ev.Topics[0], DepositEventABIHash) } - if len(ev.Data) < 7*32 { + if len(ev.Data) < 6*32 { return nil, fmt.Errorf("deposit event data too small (%d bytes): %x", len(ev.Data), ev.Data) } From d65541ae2fc90ce781b3d173cec665d9419cf6c1 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 21:04:27 +0100 Subject: [PATCH 142/585] ref impl: fix deposit data padding handling --- opnode/l2/input_derivation.go | 13 ++++++++++--- opnode/l2/input_derivation_test.go | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/opnode/l2/input_derivation.go b/opnode/l2/input_derivation.go index fded7b31cd5b..ed4f01e05e97 100644 --- a/opnode/l2/input_derivation.go +++ b/opnode/l2/input_derivation.go @@ -92,12 +92,19 @@ func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.D var dataLen uint256.Int dataLen.SetBytes(ev.Data[offset : offset+32]) offset += 32 - if !dataLen.IsUint64() || dataLen.Uint64() != uint64(len(ev.Data))-offset { - return nil, fmt.Errorf("inconsistent data length: %s, expected %d", dataLen.String(), uint64(len(ev.Data))-offset) + + if !dataLen.IsUint64() { + return nil, fmt.Errorf("data too large: %s", dataLen.String()) + } + // The data may be padded to a multiple of 32 bytes + maxExpectedLen := uint64(len(ev.Data)) - offset + dataLenU64 := dataLen.Uint64() + if dataLenU64 > maxExpectedLen { + return nil, fmt.Errorf("data length too long: %d, expected max %d", dataLenU64, maxExpectedLen) } // remaining bytes fill the data - dep.Data = ev.Data[offset:] + dep.Data = ev.Data[offset : offset+dataLenU64] return &dep, nil } diff --git a/opnode/l2/input_derivation_test.go b/opnode/l2/input_derivation_test.go index 29ffae388a54..325b7d467640 100644 --- a/opnode/l2/input_derivation_test.go +++ b/opnode/l2/input_derivation_test.go @@ -87,6 +87,9 @@ func GenerateDepositLog(deposit *types.DepositTx) *types.Log { offset += 32 binary.BigEndian.PutUint64(data[offset+24:offset+32], uint64(len(deposit.Data))) data = append(data, deposit.Data...) + if len(data)%32 != 0 { // pad to multiple of 32 + data = append(data, make([]byte, 32-(len(data)%32))...) + } return GenerateLog(DepositContractAddr, topics, data) } From b9bd93981f14b35011439999b5a7a4009d7b4239 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 11 Jan 2022 00:07:15 +0100 Subject: [PATCH 143/585] ref impl: derive outputs and run driver step --- opnode/l2/driver_step.go | 106 +++++++++++++++++++++++++++++++++ opnode/l2/output_derivation.go | 35 +++++++++++ 2 files changed, 141 insertions(+) create mode 100644 opnode/l2/driver_step.go create mode 100644 opnode/l2/output_derivation.go diff --git a/opnode/l2/driver_step.go b/opnode/l2/driver_step.go new file mode 100644 index 000000000000..d01db44af9a0 --- /dev/null +++ b/opnode/l2/driver_step.go @@ -0,0 +1,106 @@ +package l2 + +import ( + "context" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/core/types" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +type DriverAPI interface { + EngineAPI + EthBackend +} + +func Execute(ctx context.Context, rpc DriverAPI, payload *ExecutionPayload) error { + execCtx, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() + execRes, err := rpc.ExecutePayload(execCtx, payload) + if err != nil { + return fmt.Errorf("failed to execute payload: %v", err) + } + switch execRes.Status { + case ExecutionValid: + return nil + case ExecutionSyncing: + return fmt.Errorf("failed to execute payload %s, node is syncing, latest valid hash is %s", payload.ID(), execRes.LatestValidHash) + case ExecutionInvalid: + return fmt.Errorf("execution payload %s was INVALID! Latest valid hash is %s, ignoring bad block: %q", payload.ID(), execRes.LatestValidHash, execRes.ValidationError) + default: + return fmt.Errorf("unknown execution status on %s: %q, ", payload.ID(), string(execRes.Status)) + } +} + +func ForkchoiceUpdate(ctx context.Context, rpc DriverAPI, l2BlockHash common.Hash, l2Finalized common.Hash) error { + postState := &ForkchoiceState{ + HeadBlockHash: l2BlockHash, // no difference yet between Head and Safe, no data ahead of L1 yet. + SafeBlockHash: l2BlockHash, + FinalizedBlockHash: l2Finalized, + } + + fcCtx, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() + fcRes, err := rpc.ForkchoiceUpdated(fcCtx, postState, nil) + if err != nil { + return fmt.Errorf("failed to update forkchoice: %v", err) + } + switch fcRes.Status { + case UpdateSyncing: + return fmt.Errorf("updated forkchoice, but node is syncing: %v", err) + case UpdateSuccess: + return nil + default: + return fmt.Errorf("unknown forkchoice status on %s: %q, ", l2BlockHash, string(fcRes.Status)) + } +} + +type Downloader interface { + Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) +} + +func DriverStep(ctx context.Context, log log.Logger, rpc DriverAPI, + dl Downloader, l1Input eth.BlockID, l2Parent eth.BlockID, l2Finalized common.Hash) (out eth.BlockID, err error) { + + logger := log.New("input_l1", l1Input, "input_l2_parent", l2Parent, "finalized_l2", l2Finalized) + + fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) + defer cancel() + bl, receipts, err := dl.Fetch(fetchCtx, l1Input) + if err != nil { + return eth.BlockID{}, fmt.Errorf("failed to fetch block with receipts: %v", err) + } + logger.Debug("fetched L1 data for driver") + + attrs, err := DeriveBlockInputs(bl, receipts) + if err != nil { + return eth.BlockID{}, fmt.Errorf("failed to derive execution payload inputs: %v", err) + } + logger.Debug("derived L2 block inputs") + + payload, err := DeriveBlockOutputs(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) + if err != nil { + return eth.BlockID{}, fmt.Errorf("failed to derive execution payload: %v", err) + } + + logger = logger.New("derived_l2", payload.ID()) + logger.Info("derived full block") + + err = Execute(ctx, rpc, payload) + if err != nil { + return eth.BlockID{}, fmt.Errorf("failed to apply execution payload: %v", err) + } + logger.Info("executed block") + + err = ForkchoiceUpdate(ctx, rpc, payload.BlockHash, l2Finalized) + if err != nil { + return eth.BlockID{}, fmt.Errorf("failed to persist execution payload: %v", err) + } + logger.Info("updated fork-choice with block") + + return payload.ID(), nil +} diff --git a/opnode/l2/output_derivation.go b/opnode/l2/output_derivation.go new file mode 100644 index 000000000000..f36d2c9cdf1e --- /dev/null +++ b/opnode/l2/output_derivation.go @@ -0,0 +1,35 @@ +package l2 + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common" +) + +type BlockPreparer interface { + GetPayload(ctx context.Context, payloadId PayloadID) (*ExecutionPayload, error) + ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) +} + +// DeriveBlockOutputs uses the engine API to derive a full L2 block from the block inputs. +// The fcState does not affect the block production, but may inform the engine of finality and head changes to sync towards before block computation. +func DeriveBlockOutputs(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *PayloadAttributes) (*ExecutionPayload, error) { + fcState := &ForkchoiceState{ + HeadBlockHash: l2Parent, // no difference yet between Head and Safe, no data ahead of L1 yet. + SafeBlockHash: l2Parent, + FinalizedBlockHash: l2Finalized, + } + fcResult, err := engine.ForkchoiceUpdated(ctx, fcState, attributes) + if err != nil { + return nil, fmt.Errorf("engine failed to process forkchoice update for block derivation: %v", err) + } else if fcResult.Status != UpdateSuccess { + return nil, fmt.Errorf("engine not in sync, failed to derive block, status: %s", fcResult.Status) + } + + payload, err := engine.GetPayload(ctx, *fcResult.PayloadID) + if err != nil { + return nil, fmt.Errorf("failed to get payload: %v", err) + } + return payload, nil +} From 8b667dd231bf313afae32562c7b6e097cedec911 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 11 Jan 2022 00:15:04 +0100 Subject: [PATCH 144/585] ref impl: find starting point of sync, given L1 and L2 interfaces --- opnode/l2/sync_reference.go | 56 +++++++++++++++++++++++ opnode/l2/sync_start.go | 89 +++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 opnode/l2/sync_reference.go create mode 100644 opnode/l2/sync_start.go diff --git a/opnode/l2/sync_reference.go b/opnode/l2/sync_reference.go new file mode 100644 index 000000000000..17be18664c53 --- /dev/null +++ b/opnode/l2/sync_reference.go @@ -0,0 +1,56 @@ +package l2 + +import ( + "context" + "fmt" + "math/big" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" +) + +// SyncSource implements SyncReference with a L2 block sources and L1 hash-by-number source +type SyncSource struct { + L1 eth.BlockLinkByNumber + L2 eth.BlockSource +} + +func (src SyncSource) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) { + return src.L1.BlockLinkByNumber(ctx, l1Num) +} + +func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { + ctx, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() + refL2Block, err2 := src.L2.BlockByNumber(ctx, l2Num) // nil for latest block + if err2 != nil { + err = fmt.Errorf("failed to retrieve head L2 block: %v", err2) + return + } + return ParseBlockReferences(refL2Block, genesis) +} + +func (src SyncSource) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { + ctx, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() + refL2Block, err2 := src.L2.BlockByHash(ctx, l2Hash) + if err2 != nil { + err = fmt.Errorf("failed to retrieve head L2 block: %v", err2) + return + } + return ParseBlockReferences(refL2Block, genesis) +} + +// SyncReference helps inform the sync algorithm of the L2 sync-state and L1 canonical chain +type SyncReference interface { + // RefByL1Num fetches the canonical L1 block hash and the parent for the given L1 block height. + RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) + + // RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. + // Use a nil height to fetch the head. + RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) + + // RefByL2Hash fetches the L1 and L2 block IDs from the engine for the given L2 block hash. + RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) +} diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go new file mode 100644 index 000000000000..9be3f8fd26c2 --- /dev/null +++ b/opnode/l2/sync_start.go @@ -0,0 +1,89 @@ +package l2 + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/ethereum/go-ethereum" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" +) + +func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { + // 10 seconds for the whole thing (TODO: or do we want individual timeouts?) + ctx, cancel := context.WithTimeout(ctx, time.Second*10) + defer cancel() + var refL1 eth.BlockID + var parentL2 common.Hash + // Start at L2 head + refL1, refL2, parentL2, err = reference.RefByL2Num(ctx, nil, genesis) + if err != nil { + err = fmt.Errorf("failed to fetch L2 head: %v", err) + return + } + // Check if L1 source has the block + var currentL1 eth.BlockID + currentL1, _, err = reference.RefByL1Num(ctx, refL1.Number) + if err != nil { + err = fmt.Errorf("failed to lookup block %d in L1: %v", refL1.Number, err) + return + } + if currentL1 == refL1 { + // L1 node has head-block of execution-engine, so we should fetch the L1 block that builds on top. + var ontoL1 eth.BlockID + nextRefL1, ontoL1, err = reference.RefByL1Num(ctx, refL1.Number+1) + if err != nil { + // If refL1 is the head block, then we might not have a next block to build on the head + if errors.Is(err, ethereum.NotFound) { + // return the same as the engine head was already built on, no error. + nextRefL1 = refL1 + refL2 = eth.BlockID{Hash: parentL2, Number: refL2.Number} + if refL2.Number > 0 { + refL2.Number -= 1 + } + err = nil + return + } + return + } + // The L1 source might rug us with a reorg between API calls, catch that. + if ontoL1 != currentL1 { + err = fmt.Errorf("the L1 source reorged, the block for N+1 %s doesn't have the previously fetched block N %s as parent, but builds on %s instead", nextRefL1, currentL1, ontoL1) + } + return + } + + // Search back: linear walk back from engine head. Should only be as deep as the reorg. + for refL2.Number > 0 { + // remember the canonical L1 block that builds on top of the L1 source block of the L2 parent block. + nextRefL1 = refL1 + refL1, refL2, parentL2, err = reference.RefByL2Hash(ctx, parentL2, genesis) + if err != nil { + // TODO: re-attempt look-up, now that we already traversed previous history? + err = fmt.Errorf("failed to lookup block %s in L2: %v", refL2, err) // refL2 is previous parentL2 + return + } + // Check if L1 source has the block that derived the L2 block we are planning to build on + currentL1, _, err = reference.RefByL1Num(ctx, refL1.Number) + if err != nil { + err = fmt.Errorf("failed to lookup block %d in L1: %v", refL1.Number, err) + return + } + if currentL1 == refL1 { + return + } + // TODO: after e.g. initial N steps, use binary search instead + // (relies on block numbers, not great for tip of chain, but nice-to-have in deep reorgs) + } + // Enforce that we build on the desired genesis block. + // The engine might be configured for a different chain or older testnet. + if refL2 != genesis.L2 { + err = fmt.Errorf("engine was anchored at unexpected block: %s, expected %s", refL2, genesis.L2) + return + } + // we got the correct genesis, all good, but a lot to sync! + return +} From ab7a7785682a9f106f679bb5287e877e339fbdb4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 12 Jan 2022 21:48:18 +0100 Subject: [PATCH 145/585] ref impl: test FindSyncStart --- opnode/l2/sync_start.go | 2 +- opnode/l2/sync_start_test.go | 171 +++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 opnode/l2/sync_start_test.go diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index 9be3f8fd26c2..89ebcc32508c 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -59,7 +59,7 @@ func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesi // Search back: linear walk back from engine head. Should only be as deep as the reorg. for refL2.Number > 0 { // remember the canonical L1 block that builds on top of the L1 source block of the L2 parent block. - nextRefL1 = refL1 + nextRefL1 = currentL1 refL1, refL2, parentL2, err = reference.RefByL2Hash(ctx, parentL2, genesis) if err != nil { // TODO: re-attempt look-up, now that we already traversed previous history? diff --git a/opnode/l2/sync_start_test.go b/opnode/l2/sync_start_test.go new file mode 100644 index 000000000000..68f5a6aff99a --- /dev/null +++ b/opnode/l2/sync_start_test.go @@ -0,0 +1,171 @@ +package l2 + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +type l2Block struct { + Self eth.BlockID + FromL1 eth.BlockID +} + +type mockSyncReference struct { + L2 []l2Block + L1 []eth.BlockID +} + +func (m *mockSyncReference) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) { + self = m.L1[l1Num] + if l1Num > 0 { + parent = m.L1[l1Num-1] + } + return +} + +func (m *mockSyncReference) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { + if len(m.L2) == 0 { + panic("bad test, no l2 chain") + } + i := uint64(len(m.L2) - 1) + if l2Num != nil { + i = l2Num.Uint64() + } + head := m.L2[i] + refL1 = head.FromL1 + refL2 = head.Self + if i > 0 { + parentL2 = m.L2[i-1].Self.Hash + } + return +} + +func (m *mockSyncReference) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { + for i, bl := range m.L2 { + if bl.Self.Hash == l2Hash { + return m.RefByL2Num(ctx, big.NewInt(int64(i)), genesis) + } + } + err = ethereum.NotFound + return +} + +var _ SyncReference = (*mockSyncReference)(nil) + +func mockID(id rune, num uint64) eth.BlockID { + var h common.Hash + copy(h[:], string(id)) + return eth.BlockID{Hash: h, Number: uint64(num)} +} + +func chainL1(ids string) (out []eth.BlockID) { + for i, id := range ids { + out = append(out, mockID(id, uint64(i))) + } + return +} + +func chainL2(l1 []eth.BlockID, ids string) (out []l2Block) { + for i, id := range ids { + out = append(out, l2Block{ + Self: mockID(id, uint64(i)), + FromL1: l1[i], + }) + } + return +} + +type syncStartTestCase struct { + Name string + + OffsetL2 uint64 + EngineL1 string + EngineL2 string + ActualL1 string + + GenesisL2 rune + + ExpectedNextRefL1 rune + ExpectedRefL2 rune + + ExpectedErr error +} + +func (c *syncStartTestCase) Run(t *testing.T) { + engL1 := chainL1(c.EngineL1) + engL2 := chainL2(engL1[c.OffsetL2:], c.EngineL2) + actL1 := chainL1(c.ActualL1) + + msr := &mockSyncReference{ + L2: engL2, + L1: actL1, + } + + genesis := &Genesis{ + L1: actL1[0], + L2: mockID(c.GenesisL2, 0), + } + + expectedNextRefL1Num := ^uint64(0) + for i, id := range c.ActualL1 { + if id == c.ExpectedNextRefL1 { + expectedNextRefL1Num = uint64(i) + } + } + expectedNextRefL1 := mockID(c.ExpectedNextRefL1, expectedNextRefL1Num) + + expectedNextRefL2Num := ^uint64(0) + for i, id := range c.EngineL2 { + if id == c.ExpectedRefL2 { + expectedNextRefL2Num = uint64(i) + } + } + expectedRefL2 := mockID(c.ExpectedRefL2, expectedNextRefL2Num) + + nextRefL1, refL2, err := FindSyncStart(context.Background(), msr, genesis) + if c.ExpectedErr != nil { + assert.Equal(t, c.ExpectedErr, err) + } else { + assert.NoError(t, err) + assert.Equal(t, expectedNextRefL1, nextRefL1, "expected %s (nr %d) but got %s (nr %d)", expectedNextRefL1.Hash[:1], expectedNextRefL1.Number, nextRefL1.Hash[:1], nextRefL1.Number) + assert.Equal(t, expectedRefL2, refL2, "expected %s (nr %d) but got %s (nr %d)", expectedRefL2.Hash[:1], expectedRefL2.Number, refL2.Hash[:1], refL2.Number) + } +} + +func TestFindSyncStart(t *testing.T) { + testCases := []syncStartTestCase{ + { + Name: "happy extend", + OffsetL2: 0, + EngineL1: "ab", + EngineL2: "AB", + ActualL1: "abc", + GenesisL2: 'A', + ExpectedNextRefL1: 'c', + ExpectedRefL2: 'B', + ExpectedErr: nil, + }, + { + Name: "reorg two steps back", + OffsetL2: 0, + EngineL1: "abc", + EngineL2: "ABC", + ActualL1: "axy", + GenesisL2: 'A', + ExpectedNextRefL1: 'x', + ExpectedRefL2: 'A', + ExpectedErr: nil, + }, + // TODO more test cases + } + + for _, testCase := range testCases { + t.Run(testCase.Name, testCase.Run) + } +} From 92bfa201813ab5dd26c75874892e750364a3aa60 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 12 Jan 2022 23:22:07 +0100 Subject: [PATCH 146/585] ref impl: sync start genesis and diff height edge cases, more tests --- opnode/l2/sync_start.go | 33 +++++++++-- opnode/l2/sync_start_test.go | 107 +++++++++++++++++++++++++++++++++-- 2 files changed, 130 insertions(+), 10 deletions(-) diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index 89ebcc32508c..b7a1ec16b2e7 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -12,6 +12,8 @@ import ( "github.com/ethereum/go-ethereum/common" ) +var WrongChainErr = errors.New("wrong chain") + func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { // 10 seconds for the whole thing (TODO: or do we want individual timeouts?) ctx, cancel := context.WithTimeout(ctx, time.Second*10) @@ -28,8 +30,15 @@ func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesi var currentL1 eth.BlockID currentL1, _, err = reference.RefByL1Num(ctx, refL1.Number) if err != nil { - err = fmt.Errorf("failed to lookup block %d in L1: %v", refL1.Number, err) - return + if !errors.Is(err, ethereum.NotFound) { + err = fmt.Errorf("failed to lookup block %d in L1: %w", refL1.Number, err) + return + } + // if the L1 did not find the block, it might be out of sync. + // We cannot sync from L1 in this case, but must make sure we are not in + // a reorg to a L1 chain with less blocks. + err = nil + currentL1 = eth.BlockID{} // empty = not found } if currentL1 == refL1 { // L1 node has head-block of execution-engine, so we should fetch the L1 block that builds on top. @@ -63,16 +72,25 @@ func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesi refL1, refL2, parentL2, err = reference.RefByL2Hash(ctx, parentL2, genesis) if err != nil { // TODO: re-attempt look-up, now that we already traversed previous history? - err = fmt.Errorf("failed to lookup block %s in L2: %v", refL2, err) // refL2 is previous parentL2 + err = fmt.Errorf("failed to lookup block %s in L2: %w", refL2, err) // refL2 is previous parentL2 return } // Check if L1 source has the block that derived the L2 block we are planning to build on currentL1, _, err = reference.RefByL1Num(ctx, refL1.Number) if err != nil { - err = fmt.Errorf("failed to lookup block %d in L1: %v", refL1.Number, err) - return + if !errors.Is(err, ethereum.NotFound) { + err = fmt.Errorf("failed to lookup block %d in L1: %w", refL1.Number, err) + return + } + // again, if L1 does not have the block, then we just search if we are reorging. + err = nil + currentL1 = eth.BlockID{} // empty = not found } if currentL1 == refL1 { + // check if we had a L1 block to build on top of the common chain with + if nextRefL1 == (eth.BlockID{}) { + err = ethereum.NotFound + } return } // TODO: after e.g. initial N steps, use binary search instead @@ -81,9 +99,12 @@ func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesi // Enforce that we build on the desired genesis block. // The engine might be configured for a different chain or older testnet. if refL2 != genesis.L2 { - err = fmt.Errorf("engine was anchored at unexpected block: %s, expected %s", refL2, genesis.L2) + err = fmt.Errorf("unexpected L2 genesis block: %s, expected %s, %w", refL2, genesis.L2, WrongChainErr) return } + if currentL1 != genesis.L1 { + err = fmt.Errorf("unexpected L1 anchor block: %s, expected %s, %w", currentL1, genesis.L1, WrongChainErr) + } // we got the correct genesis, all good, but a lot to sync! return } diff --git a/opnode/l2/sync_start_test.go b/opnode/l2/sync_start_test.go index 68f5a6aff99a..33f28b97cf0d 100644 --- a/opnode/l2/sync_start_test.go +++ b/opnode/l2/sync_start_test.go @@ -22,6 +22,10 @@ type mockSyncReference struct { } func (m *mockSyncReference) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) { + if l1Num >= uint64(len(m.L1)) { + err = ethereum.NotFound + return + } self = m.L1[l1Num] if l1Num > 0 { parent = m.L1[l1Num-1] @@ -118,19 +122,26 @@ func (c *syncStartTestCase) Run(t *testing.T) { expectedNextRefL1Num = uint64(i) } } + if c.ExpectedNextRefL1 == 0 { + expectedNextRefL1Num = uint64(0) + } expectedNextRefL1 := mockID(c.ExpectedNextRefL1, expectedNextRefL1Num) - expectedNextRefL2Num := ^uint64(0) + expectedRefL2Num := ^uint64(0) for i, id := range c.EngineL2 { if id == c.ExpectedRefL2 { - expectedNextRefL2Num = uint64(i) + expectedRefL2Num = uint64(i) } } - expectedRefL2 := mockID(c.ExpectedRefL2, expectedNextRefL2Num) + if c.ExpectedRefL2 == 0 { + expectedRefL2Num = uint64(0) + } + expectedRefL2 := mockID(c.ExpectedRefL2, expectedRefL2Num) nextRefL1, refL2, err := FindSyncStart(context.Background(), msr, genesis) if c.ExpectedErr != nil { - assert.Equal(t, c.ExpectedErr, err) + assert.Error(t, err, "got next L1 %s (%d), onto L2: %s (%d)", nextRefL1.Hash[:1], nextRefL1.Number, refL2.Hash[:1], refL2.Number) + assert.ErrorIs(t, err, c.ExpectedErr) } else { assert.NoError(t, err) assert.Equal(t, expectedNextRefL1, nextRefL1, "expected %s (nr %d) but got %s (nr %d)", expectedNextRefL1.Hash[:1], expectedNextRefL1.Number, nextRefL1.Hash[:1], nextRefL1.Number) @@ -151,6 +162,39 @@ func TestFindSyncStart(t *testing.T) { ExpectedRefL2: 'B', ExpectedErr: nil, }, + { + Name: "extend one at a time", + OffsetL2: 0, + EngineL1: "ab", + EngineL2: "AB", + ActualL1: "abcdef", + GenesisL2: 'A', + ExpectedNextRefL1: 'c', + ExpectedRefL2: 'B', + ExpectedErr: nil, + }, + { + Name: "already synced", + OffsetL2: 0, + EngineL1: "abcde", + EngineL2: "ABCDE", + ActualL1: "abcde", + GenesisL2: 'A', + ExpectedNextRefL1: 'e', + ExpectedRefL2: 'D', + ExpectedErr: nil, + }, + { + Name: "genesis", + OffsetL2: 0, + EngineL1: "a", + EngineL2: "A", + ActualL1: "a", + GenesisL2: 'A', + ExpectedNextRefL1: 'a', + ExpectedRefL2: 0, // actual zero hash before genesis hash + ExpectedErr: nil, + }, { Name: "reorg two steps back", OffsetL2: 0, @@ -162,6 +206,61 @@ func TestFindSyncStart(t *testing.T) { ExpectedRefL2: 'A', ExpectedErr: nil, }, + { + Name: "Orphan block", + OffsetL2: 0, + EngineL1: "abcd", + EngineL2: "ABCD", + ActualL1: "abcx", + GenesisL2: 'A', + ExpectedNextRefL1: 'x', + ExpectedRefL2: 'C', + ExpectedErr: nil, + }, + { + Name: "L2 chain ahead", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "abc", + GenesisL2: 'A', + ExpectedNextRefL1: 0, + ExpectedRefL2: 0, + ExpectedErr: ethereum.NotFound, + }, + { + Name: "L2 chain ahead reorg", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "abcx", + GenesisL2: 'A', + ExpectedNextRefL1: 'x', + ExpectedRefL2: 'C', + ExpectedErr: nil, + }, + { + Name: "unexpected L1 chain", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "xyz", + GenesisL2: 'A', + ExpectedNextRefL1: 0, + ExpectedRefL2: 0, + ExpectedErr: WrongChainErr, + }, + { + Name: "unexpected L2 chain", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "xyz", + GenesisL2: 'X', + ExpectedNextRefL1: 0, + ExpectedRefL2: 0, + ExpectedErr: WrongChainErr, + }, // TODO more test cases } From 11048aabbd4a905cd3042c2aa19f671a4929d6fd Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 02:32:50 +0100 Subject: [PATCH 147/585] ref impl: sync start genesis L1 check test fixed --- opnode/l2/sync_start.go | 1 + opnode/l2/sync_start_test.go | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index b7a1ec16b2e7..38dd6bd47d16 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -104,6 +104,7 @@ func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesi } if currentL1 != genesis.L1 { err = fmt.Errorf("unexpected L1 anchor block: %s, expected %s, %w", currentL1, genesis.L1, WrongChainErr) + return } // we got the correct genesis, all good, but a lot to sync! return diff --git a/opnode/l2/sync_start_test.go b/opnode/l2/sync_start_test.go index 33f28b97cf0d..d66aae971aff 100644 --- a/opnode/l2/sync_start_test.go +++ b/opnode/l2/sync_start_test.go @@ -94,6 +94,7 @@ type syncStartTestCase struct { ActualL1 string GenesisL2 rune + GenesisL1 rune ExpectedNextRefL1 rune ExpectedRefL2 rune @@ -112,7 +113,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { } genesis := &Genesis{ - L1: actL1[0], + L1: mockID(c.GenesisL1, c.OffsetL2), L2: mockID(c.GenesisL2, 0), } @@ -157,6 +158,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "ab", EngineL2: "AB", ActualL1: "abc", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 'c', ExpectedRefL2: 'B', @@ -168,6 +170,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "ab", EngineL2: "AB", ActualL1: "abcdef", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 'c', ExpectedRefL2: 'B', @@ -179,6 +182,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "abcde", EngineL2: "ABCDE", ActualL1: "abcde", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 'e', ExpectedRefL2: 'D', @@ -190,6 +194,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "a", EngineL2: "A", ActualL1: "a", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 'a', ExpectedRefL2: 0, // actual zero hash before genesis hash @@ -201,6 +206,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "abc", EngineL2: "ABC", ActualL1: "axy", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 'x', ExpectedRefL2: 'A', @@ -212,6 +218,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "abcd", EngineL2: "ABCD", ActualL1: "abcx", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 'x', ExpectedRefL2: 'C', @@ -223,6 +230,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "abcdef", EngineL2: "ABCDEF", ActualL1: "abc", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 0, ExpectedRefL2: 0, @@ -234,6 +242,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "abcdef", EngineL2: "ABCDEF", ActualL1: "abcx", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 'x', ExpectedRefL2: 'C', @@ -245,6 +254,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "abcdef", EngineL2: "ABCDEF", ActualL1: "xyz", + GenesisL1: 'a', GenesisL2: 'A', ExpectedNextRefL1: 0, ExpectedRefL2: 0, @@ -256,6 +266,7 @@ func TestFindSyncStart(t *testing.T) { EngineL1: "abcdef", EngineL2: "ABCDEF", ActualL1: "xyz", + GenesisL1: 'a', GenesisL2: 'X', ExpectedNextRefL1: 0, ExpectedRefL2: 0, From 90c8a1bdbd727ebc2ca2bcceabdd9eaa0888dafd Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 13 Jan 2022 02:44:26 +0100 Subject: [PATCH 148/585] ref impl: test sync start with offset L2 genesis --- opnode/l2/sync_start_test.go | 49 ++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/opnode/l2/sync_start_test.go b/opnode/l2/sync_start_test.go index d66aae971aff..a0d8f2668ba7 100644 --- a/opnode/l2/sync_start_test.go +++ b/opnode/l2/sync_start_test.go @@ -68,9 +68,9 @@ func mockID(id rune, num uint64) eth.BlockID { return eth.BlockID{Hash: h, Number: uint64(num)} } -func chainL1(ids string) (out []eth.BlockID) { +func chainL1(offset uint64, ids string) (out []eth.BlockID) { for i, id := range ids { - out = append(out, mockID(id, uint64(i))) + out = append(out, mockID(id, offset+uint64(i))) } return } @@ -93,8 +93,8 @@ type syncStartTestCase struct { EngineL2 string ActualL1 string - GenesisL2 rune GenesisL1 rune + GenesisL2 rune ExpectedNextRefL1 rune ExpectedRefL2 rune @@ -103,9 +103,9 @@ type syncStartTestCase struct { } func (c *syncStartTestCase) Run(t *testing.T) { - engL1 := chainL1(c.EngineL1) - engL2 := chainL2(engL1[c.OffsetL2:], c.EngineL2) - actL1 := chainL1(c.ActualL1) + engL1 := chainL1(c.OffsetL2, c.EngineL1) + engL2 := chainL2(engL1, c.EngineL2) + actL1 := chainL1(0, c.ActualL1) msr := &mockSyncReference{ L2: engL2, @@ -272,7 +272,42 @@ func TestFindSyncStart(t *testing.T) { ExpectedRefL2: 0, ExpectedErr: WrongChainErr, }, - // TODO more test cases + { + Name: "offset L2 genesis extend", + OffsetL2: 3, + EngineL1: "def", + EngineL2: "DEF", + ActualL1: "abcdefg", + GenesisL1: 'd', + GenesisL2: 'D', + ExpectedNextRefL1: 'g', + ExpectedRefL2: 'F', + ExpectedErr: nil, + }, + { + Name: "offset L2 genesis reorg", + OffsetL2: 3, + EngineL1: "defgh", + EngineL2: "DEFGH", + ActualL1: "abcdx", + GenesisL1: 'd', + GenesisL2: 'D', + ExpectedNextRefL1: 'x', + ExpectedRefL2: 'D', + ExpectedErr: nil, + }, + { + Name: "reorg past offset genesis", + OffsetL2: 3, + EngineL1: "defgh", + EngineL2: "DEFGH", + ActualL1: "abx", + GenesisL1: 'd', + GenesisL2: 'D', + ExpectedNextRefL1: 0, + ExpectedRefL2: 0, + ExpectedErr: WrongChainErr, + }, } for _, testCase := range testCases { From 576b37005225a19a7f2844fe2bdfbf7e8e724ef4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 18 Jan 2022 17:16:56 +0100 Subject: [PATCH 149/585] ref impl: no timeouts, called responsible instead --- opnode/l2/sync_reference.go | 8 +------- opnode/l2/sync_start.go | 5 ----- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/opnode/l2/sync_reference.go b/opnode/l2/sync_reference.go index 17be18664c53..697694a1b881 100644 --- a/opnode/l2/sync_reference.go +++ b/opnode/l2/sync_reference.go @@ -3,11 +3,9 @@ package l2 import ( "context" "fmt" - "math/big" - "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum/go-ethereum/common" + "math/big" ) // SyncSource implements SyncReference with a L2 block sources and L1 hash-by-number source @@ -21,8 +19,6 @@ func (src SyncSource) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.Bl } func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { - ctx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() refL2Block, err2 := src.L2.BlockByNumber(ctx, l2Num) // nil for latest block if err2 != nil { err = fmt.Errorf("failed to retrieve head L2 block: %v", err2) @@ -32,8 +28,6 @@ func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *G } func (src SyncSource) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { - ctx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() refL2Block, err2 := src.L2.BlockByHash(ctx, l2Hash) if err2 != nil { err = fmt.Errorf("failed to retrieve head L2 block: %v", err2) diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index 38dd6bd47d16..5110a83fd63d 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -4,8 +4,6 @@ import ( "context" "errors" "fmt" - "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -15,9 +13,6 @@ import ( var WrongChainErr = errors.New("wrong chain") func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - // 10 seconds for the whole thing (TODO: or do we want individual timeouts?) - ctx, cancel := context.WithTimeout(ctx, time.Second*10) - defer cancel() var refL1 eth.BlockID var parentL2 common.Hash // Start at L2 head From ef803617fd0d8b3b97f670235a1b645c5a303aec Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 18 Jan 2022 17:40:30 +0100 Subject: [PATCH 150/585] ref impl: clarify sync-start and sync-ref comments --- opnode/l2/sync_reference.go | 8 ++++++-- opnode/l2/sync_start.go | 16 +++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/opnode/l2/sync_reference.go b/opnode/l2/sync_reference.go index 697694a1b881..0df1e694ba34 100644 --- a/opnode/l2/sync_reference.go +++ b/opnode/l2/sync_reference.go @@ -14,23 +14,27 @@ type SyncSource struct { L2 eth.BlockSource } +// RefByL1Num fetches the canonical L1 block hash and the parent for the given L1 block height. func (src SyncSource) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) { return src.L1.BlockLinkByNumber(ctx, l1Num) } +// RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. +// Use a nil height to fetch the head. func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { refL2Block, err2 := src.L2.BlockByNumber(ctx, l2Num) // nil for latest block if err2 != nil { - err = fmt.Errorf("failed to retrieve head L2 block: %v", err2) + err = fmt.Errorf("failed to retrieve L2 block: %v", err2) return } return ParseBlockReferences(refL2Block, genesis) } +// RefByL2Hash fetches the L1 and L2 block IDs from the engine for the given L2 block hash. func (src SyncSource) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { refL2Block, err2 := src.L2.BlockByHash(ctx, l2Hash) if err2 != nil { - err = fmt.Errorf("failed to retrieve head L2 block: %v", err2) + err = fmt.Errorf("failed to retrieve L2 block: %v", err2) return } return ParseBlockReferences(refL2Block, genesis) diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index 5110a83fd63d..a040af0843c0 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -12,9 +12,11 @@ import ( var WrongChainErr = errors.New("wrong chain") +// FindSyncStart finds nextRefL1: the L1 block needed next for sync, to derive into a L2 block on top of refL2. +// If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - var refL1 eth.BlockID - var parentL2 common.Hash + var refL1 eth.BlockID // the L1 block that was derived into refL2 + var parentL2 common.Hash // the parent of refL2 // Start at L2 head refL1, refL2, parentL2, err = reference.RefByL2Num(ctx, nil, genesis) if err != nil { @@ -22,22 +24,22 @@ func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesi return } // Check if L1 source has the block - var currentL1 eth.BlockID + var currentL1 eth.BlockID // the expected L1 block at the height of refL1 currentL1, _, err = reference.RefByL1Num(ctx, refL1.Number) if err != nil { if !errors.Is(err, ethereum.NotFound) { err = fmt.Errorf("failed to lookup block %d in L1: %w", refL1.Number, err) return } - // if the L1 did not find the block, it might be out of sync. - // We cannot sync from L1 in this case, but must make sure we are not in - // a reorg to a L1 chain with less blocks. + // If the L1 did not find the block, it might be out of sync. + // We cannot sync from L1 in this case, but we still traverse back to + // make sure we are not just in a reorg to a L1 chain with fewer blocks. err = nil currentL1 = eth.BlockID{} // empty = not found } if currentL1 == refL1 { // L1 node has head-block of execution-engine, so we should fetch the L1 block that builds on top. - var ontoL1 eth.BlockID + var ontoL1 eth.BlockID // ontoL1 is the parent, to make sure we got a nextRefL1 that connects as expected. nextRefL1, ontoL1, err = reference.RefByL1Num(ctx, refL1.Number+1) if err != nil { // If refL1 is the head block, then we might not have a next block to build on the head From ae271a55a35e9e95f108b1bf4e234ebff662cc53 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 18 Jan 2022 17:44:46 +0100 Subject: [PATCH 151/585] ref impl: sync start finding - lint imports --- opnode/l2/sync_reference.go | 3 ++- opnode/l2/sync_start.go | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/opnode/l2/sync_reference.go b/opnode/l2/sync_reference.go index 0df1e694ba34..583e955e394a 100644 --- a/opnode/l2/sync_reference.go +++ b/opnode/l2/sync_reference.go @@ -3,9 +3,10 @@ package l2 import ( "context" "fmt" + "math/big" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum/go-ethereum/common" - "math/big" ) // SyncSource implements SyncReference with a L2 block sources and L1 hash-by-number source diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index a040af0843c0..e763c972c280 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/ethereum/go-ethereum" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" From 4074ef8816ad9d68c7d8eb3fb0ca1d11b57637da Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 00:45:09 +0100 Subject: [PATCH 152/585] specs/rollup-node: update & de-duplicate driver process description --- specs/exec-engine.md | 4 +- specs/rollup-node.md | 215 ++++++++++++++++--------------------------- 2 files changed, 84 insertions(+), 135 deletions(-) diff --git a/specs/exec-engine.md b/specs/exec-engine.md index 36d2e1e85b79..4ea5dc973d13 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -46,7 +46,9 @@ Within the rollup, the types of forkchoice updates translate as: - `finalizedBlockHash`: irreversible block hash, matches lower boundary of the dispute period. To support rollup functionality, one backwards-compatible change is introduced -to [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1]: +to [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1]: the extended `PayloadAttributesV1` + +#### Extended PayloadAttributesV1 [`PayloadAttributesV1`][PayloadAttributesV1] is extended with a `transactions` field, equivalent to the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 3d7787b748c6..d675bfa406e6 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -10,10 +10,10 @@ [block gossip]: glossary.md#block-gossip [rollup driver]: glossary.md#rollup-driver [deposits]: glossary.md#deposits -[deposit-feed]: glossary.md#L2-deposit-feed-contract +[deposit feed contract]: glossary.md#L2-deposit-feed-contract [L2 chain inception]: glossary.md#L2-chain-inception [receipts]: glossary.md#receipt -[L1 attributes deposit]: glossary.md#l1-attributes-deposit +[L1 attributes transaction]: glossary.md#l1-attributes-transaction [transaction deposits]: glossary.md#transaction-deposits The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their @@ -41,189 +41,135 @@ concerned with the specification of the rollup driver. ## L2 Chain Derivation -[l2-chain-derivation]: #l2-chain-derivation +This section specifies how the [rollup driver] derives one L2 block per every L1 block. -This section specifies how the [rollup driver] derives one L2 block per every L1 block. The L2 block will carry -*[deposits]*, including a single *[L1 attributes deposit]* (which carries L1 block attributes) and zero or more -*[transaction deposits]* submitted by user on L1. +First inputs are derived from L1 source data, then outputs are derived with L2 state through the [Engine API]. ----- +[Engine API]: exec-engine.md#engine-api -### From L1 blocks to payload attributes +### Input derivation -[payload-attr]: #From-L1-blocks-to-payload-attributes -[`PayloadAttributesOPV1`]: #From-L1-blocks-to-payload-attributes +The L2 block has the same format as a L1 block: a block-header and a list of transactions. -The rollup reads the following data from each L1 block: +The list of transaction carries: +- A *[L1 attributes transaction]* (always first item) +- L2 transactions deposited by users in the L1 block (*[deposits]*, if any) -- L1 block attributes - - block number - - timestamp - - basefee - - *random* (the output of the [`RANDOM` opcode][random]) -- L1 log entries emitted for [transaction deposits] +While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, +the word *deposit* should be understood as "a transaction *deposited* to L2". -[random]: https://eips.ethereum.org/EIPS/eip-4399 +The L1 attributes are read from the L1 block header, while other deposits are read from the block's [receipts]. -A [transaction deposit][transaction deposits] is an L2 transaction that has been submitted on L1, via a call to the -[deposit feed contract][deposit-feed]. +All derived deposits each get two additional attributes during derivation, to ensure uniqueness: -While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be -understood as "a transaction *deposited* to L2". +- `blockHeight`: the block-height of the L1 input the deposit was derived from +- `transactionIndex`: the transaction-index within the L2 transactions list -The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the -[**deposit feed contract specification**][deposit-feed-spec] for details on how deposits are encoded as log entries. +#### L1 attributes transaction derivation + +The rollup reads the following attributes from each L1 block to derive a [L1 attributes transaction]: + +- block number +- timestamp +- basefee +- *random* (the output of the [`RANDOM` opcode][random]) + +These are then encoded as a [L1 attributes deposit] to update the [L1 Attributes Predeploy]. + +[random]: https://eips.ethereum.org/EIPS/eip-4399 +[L1 attributes deposit]: deposits.md#l1-attributes-deposit +[L1 Attributes Predeploy]: deposits.md#l1-attributes-predeploy -[deposit-feed-spec]: deposits.md#deposit-feed-contract -From the data read from L1, the rollup node constructs an expanded version of the [Engine API PayloadAttributesV1 -object][PayloadAttributesV1], which includes an additional `transactions` field: +#### Transaction deposits derivation -[PayloadAttributesV1]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 +A [transaction deposit][transaction deposits] is an L2 transaction that has been submitted on L1, via a call to the +[deposit feed contract]. + +Refer to the[**deposit feed contract specification**][deposit-feed-spec] for details on how +deposit properties are emitted in deposit log entries. -```js -PayloadAttributesOPV1: { - timestamp: QUANTITY - random: DATA (32 bytes) - suggestedFeeRecipient: DATA (20 bytes) - transactions: array of DATA -} -``` +[deposit-feed-spec]: deposits.md#deposit-feed-contract -The type notation used here refers to the [HEX value encoding] used by the [Ethereum JSON-RPC API -specification][JSON-RPC-API], as this structure will need to be sent over JSON-RPC. `array` refers to a JSON array. +#### Payload attributes derivation -[HEX value encoding]: https://eth.wiki/json-rpc/API#hex-value-encoding -[JSON-RPC-API]: https://github.com/ethereum/execution-apis +From the data read from L1, the rollup node constructs an [expanded version of PayloadAttributesV1], +which includes an additional `transactions` field. The object properties must be set as follows: -- `timestamp` is set to the current [unix time] (number of elapsed seconds since 00:00:00 UTC on 1 January 1970), +- `timestamp` is set to the current [unix time], rounded to the closest multiple of 2 seconds. No two blocks may have the same timestamp. - `random` is set to the *random* L1 block attribute -- `suggestedFeeRecipient` is set to an address where the sequencer would like to direct the fees -- `transactions` is an array containing the [L1 attributes deposit] as well as [transaction deposits], whose format is - specified in the [next section][payload-format]. +- `suggestedFeeRecipient` is set to the zero-address for deposit-blocks, since there is no sequencer. +- `transactions` is an array of the derived deposits, all encoded in the [EIP-2718] format. +[expanded version of PayloadAttributesV1]: exec-engine.md#extended-payloadattributesv1 [unix time]: https://en.wikipedia.org/wiki/Unix_time -[yellow paper]: https://github.com/ethereum/yellowpaper -[EIP-155]: https://eips.ethereum.org/EIPS/eip-155 -[EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 ----- - -### Payload Transaction Format - -[payload-format]: #payload-transaction-format - -The `transactions` array is filled with user-submitted deposits, prefixed by the (single) [L1 attributes deposit]. The -format for deposits is described at [the top of the deposit specification][deposit-transaction-type]. - -[deposit-transaction-type]: deposits.md#the-deposit-transaction-type - -The rollup node is responsible for encoding the L1 attributes deposit based on the attributes (block number, timestamp -and basefee) of the L1 block, as specified in the [L1 Attributes Deposit][l1-attributes-deposit-spec] section of the -deposit specification. It must also encode the transaction deposits based on the `TransactionDeposited` event -emitted by the deposit contract, as specified by the [L1 Transaction Deposits][l1-transaction-deposits] section of the -same document. -[l1-attributes-deposit-spec]: deposits.md#l1-attributes-deposit -[l1-transaction-deposits]: deposits.md#l1-transaction-deposits +### Output derivation -Here is an example valid `PayloadAttributesOPV1` object, which contains an L1 attributes deposit as well as a single -transaction deposit: +Building a full block requires the earlier [derived payload attributes](#payload-attributes-derivation) +(`payloadAttributes` argument) as well as the previous L2 state (`forkchoiceState` argument), defined by +the [`engine_forkchoiceUpdatedV1`] method of the [Engine API]: -```js -{ - timestamp: "0x61a6336f", - random: "0xde5dff2b0982ecbbd38081eb8f4aed0525140dc1c1d56f995b4fa801a3f2649e", - suggestedFeeRecipient: "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B", - transactions: [ - "TODO generate abi-encoded L1 attribute deposit", - "0x02f87101058459682f0085199c82cc0082520894ab5801a7d398351b8be11c439e05c5b3259aec9b8609184e72a00080c080a0a6d217a91ea344fc09f740f104f764d71bb1ca9a8e159117d2d27091ea5fce91a04cf5add5f5b7d791a2c4663ab488cb581df800fe0910aa755099ba466b49fd69" - ] -} -``` +- `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. +- `safeBlockHash`: same as `headBlockHash`. +- `finalizedBlockHash`: the hash of the block whose number is `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if + the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS == 50400` + (approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the + first L1 block for which an L2 block was produced). See the [Finalization Guarantees][finalization] section for more + details. ----- +[`engine_forkchoiceUpdatedV1`]: exec-engine.md#engine_forkchoiceUpdatedV1 -### Building the L2 block with the execution engine +Once this first API call completes, `engine_getPayloadV1` is used to fetch the full L2 block, +as specified in the [Engine API]. -[calling-exec-engine]: #building-the-L2-block-with-the-execution-engine - -The Optimism [execution engine] is specified in the [Execution Engine Specification]. - -[Execution Engine Specification]: exec-engine.md - -This section defines how the rollup driver must interact with the execution engine's in order to convert [payload -attributes] into L2 blocks. - -> **TODO** This section probably includes too much redundant details that will -> need to be removed once the execution engine spec is up. - -Optimism's execution engine API is built upon [Ethereum's Engine API specification][eth-engine-api], with a -couple of modifications. That specification builds upon [Ethereum's JSON-RPC API specification][JSON-RPC-API], which -itself builds upon the [JSON-RPC specification][JSON-RPC]. - -[eth-engine-api]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md -[JSON-RPC]: https://www.jsonrpc.org/specification - -In particular, the [Ethereum's Engine API specification][eth-engine-api] specifies a [JSON-RPC] endpoint with a number -of JSON-RPC routes, which are the means through which the rollup driver interacts with the execution engine. +[`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 +[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 -Instead of calling [`engine_forkchoiceUpdatedV1`], the rollup driver must call the new [`engine_forkchoiceUpdatedOPV1`] -route. This has the same signature, except that: +## Completing a driver step -[`engine_forkchoiceUpdatedV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_forkchoiceupdatedv1 -[`engine_forkchoiceUpdatedOPV1`]: exec-engine.md#engine_forkchoiceupdatedv1 +After deriving a full L2 block, two more API calls are required to persist the result: +execute the new block, and update the forkchoice to reflect the new head. -- it takes a [`PayloadAttributesOPV1`] object as input instead of [`PayloadAttributesV1`][PayloadAttributesV1]. The - execution engine must include the valid transactions supplied in this object in the block, in the same order as they - were supplied, and only those. See the [previous section][payload-attr] for the specification of how the properties - must be set. +### Execute -- we repurpose the [`ForkchoiceStateV1`] structure with the following property semantics: - - `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. - - `safeBlockHash`: same as `headBlockHash`. - - `finalizedBlockHash`: the hash of the block whose number is `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if - the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS` = 50400, - approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the - first L1 block for which an L2 block was produced). See the [Finalization Guarantees][finalization] section for more - details. +Execute through the [`engine_executePayloadV1`] API method with the derived payload to update the engine state. +A `"status": "VALID"` result is required to continue. -[`ForkchoiceStateV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#ForkchoiceStateV1 +[`engine_executePayloadV1`]: exec-engine.md#engine_executepayloadv1 -> **Note:** the properties of `ForkchoiceStateV1` can be used to anchor queries to the regular (non-engine-API) JSON-RPC -> endpoint of the execution engine. [See here for more information.][L2-JSON-RPC-API] +### Forkchoice -[L2-JSON-RPC-API]: exec-engine.md#engine-api +Update the L2 head with a [`engine_forkchoiceUpdatedV1`] API call, now without `payloadAttributes` argument, +and updated `forkchoiceState` argument: -> **TODO LINK** L2 JSON RPC API (might be the same as [L1's][JSON-RPC-API]) +- `headBlockHash`: block hash of the derived payload +- `safeBlockHash`: same as `headBlockHash` +- `finalizedBlockHash`: finalized-block. May have changed since last call. + Not strictly required to change, this can be adjusted later. -The `payloadID` returned by [`engine_forkchoiceUpdatedOPV1`] can then be passed to [`engine_getPayloadV1`] in order to -obtain an [`ExecutionPayloadV1`], which fully defines a new L2 block. +A `"status": "SUCCESS"` result then indicates if the engine successfully updated the head to the derived payload. -The rollup driver must then instruct the execution engine to execute the block by calling [`engine_executePayloadV1`]. -This returns the new L2 block hash. +## API error handling -All invocations of [`engine_forkchoiceUpdatedOPV1`], [`engine_getPayloadV1`] and [`engine_executePayloadV1`] by the +All invocations of [`engine_forkchoiceUpdatedV1`], [`engine_getPayloadV1`] and [`engine_executePayloadV1`] by the rollup driver should not result in errors assuming conformity with the specification. Said otherwise, all errors are implementation concerns and it is up to them to handle them (e.g. by retrying, or by stopping the chain derivation and requiring manual user intervention). The following scenarios are assimilated to errors: -- [`engine_forkchoiceUpdatedOPV1`] returning a `status` of `"SYNCING"` instead of `"SUCCESS"` whenever passed a +- [`engine_forkchoiceUpdatedV1`] returning a `status` of `"SYNCING"` instead of `"SUCCESS"` whenever passed a `headBlockHash` that it retrieved from a previous call to [`engine_executePayloadV1`]. - [`engine_executePayloadV1`] returning a `status` of `"SYNCING"` or `"INVALID"` whenever passed an execution payload that was obtained by a previous call to [`engine_getPayloadV1`]. -[`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 -[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 -[`engine_executePayloadV1`]: exec-engine.md#engine_executepayloadv1 - ## Handling L1 Re-Orgs [l1-reorgs]: #handling-L1-re-orgs @@ -239,7 +185,7 @@ In practice, the L1 chain is processed incrementally. However, the L1 chain may head of the L1 chain changes to a block that is not the child of the previous head but rather one of its "cousins" (i.e. the descendant of an ancestor of the previous head). In those case, the rollup driver must: -1. Call [`engine_forkchoiceUpdatedOPV1`] for the new L2 chain head +1. Call [`engine_forkchoiceUpdatedV1`] for the new L2 chain head - Pass `null` for the `payloadAttributes` parameter. - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but set `headBlockHash` to the hash of the new L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated @@ -248,13 +194,14 @@ the descendant of an ancestor of the previous head). In those case, the rollup d 3. Otherwise the call returns `"SYNCING"`, and we must derive the new blocks ourselves. Start by locating the *common ancestor*, a block that is an ancestor of both the previous and new head. 4. Isolate the range of L1 blocks from `common ancestor` (excluded) to `new head` (included). -5. For each such block, call [`engine_forkchoiceUpdatedOPV1`], [`engine_getPayloadV1`], and [`engine_executePayloadV1`]. +5. For each such block, call [`engine_forkchoiceUpdatedV1`], [`engine_getPayloadV1`], and [`engine_executePayloadV1`]. - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but set `headBlockHash` to the hash of the last processed L2 block (use the hash of the common ancestor initially) instead of the last L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated accordingly. [block sync]: exec-engine.md#sync +[merge]: https://ethereum.org/en/eth2/merge/ > Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more > than `FINALIZATION_DELAY_BLOCKS == 50400` in the past, hence preserving our finalization guarantees. From 3be1d41ed9efe58e68a61a7cd4a9b3183f777d8d Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 01:30:27 +0100 Subject: [PATCH 153/585] specs/rollup-node: update sync algorithm --- specs/rollup-node.md | 60 +++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index d675bfa406e6..7f777edda737 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -32,12 +32,18 @@ concerned with the specification of the rollup driver. ## Table of Contents -- [L2 Chain Derivation][l2-chain-derivation] - - [From L1 blocks to payload attributes][payload-attr] - - [Payload Transaction Format][payload-format] - - [Building the L2 block with the execution engine][calling-exec-engine] -- [Handling L1 Re-Orgs][l1-reorgs] -- [Finalization Guarantees][finalization] +- [L2 Chain Derivation](#l2-chain-derivation) + - [Input derivation](#input-derivation) + - [L1 attributes transaction derivation](#l1-attributes-transaction-derivation) + - [Transaction deposits derivation](#transaction-deposits-derivation) + - [Payload attributes derivation](#payload-attributes-derivation) + - [Output derivation](#output-derivation) +- [Completing a driver step](#completing-a-driver-step) + - [Execute](#execute) + - [Forkchoice](#forkchoice) +- [API error handling](#api-error-handling) +- [Handling L1 Re-Orgs](#handling-l1-re-orgs) +- [Finalization Guarantees](#finalization-guarantees) ## L2 Chain Derivation @@ -182,26 +188,28 @@ processing the whole L1 chain since the [L2 chain inception]. > non-specificative** but shows how L1 re-orgs can be handled in practice. In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally re-organize, meaning the -head of the L1 chain changes to a block that is not the child of the previous head but rather one of its "cousins" (i.e. -the descendant of an ancestor of the previous head). In those case, the rollup driver must: - -1. Call [`engine_forkchoiceUpdatedV1`] for the new L2 chain head - - Pass `null` for the `payloadAttributes` parameter. - - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but - set `headBlockHash` to the hash of the new L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated - accordingly. -2. If the call returns `"SUCCESS"`, we are done: the execution engine retrieved all the new L2 blocks via [block sync]. -3. Otherwise the call returns `"SYNCING"`, and we must derive the new blocks ourselves. Start by locating the *common - ancestor*, a block that is an ancestor of both the previous and new head. -4. Isolate the range of L1 blocks from `common ancestor` (excluded) to `new head` (included). -5. For each such block, call [`engine_forkchoiceUpdatedV1`], [`engine_getPayloadV1`], and [`engine_executePayloadV1`]. - - Fill the [`PayloadAttributesOPV1`] object according to [the section on payload attributes][payload-attr]. - - Fill the [`ForkchoiceStateV1`] object according to [the section on the execution engine][calling-exec-engine], but - set `headBlockHash` to the hash of the last processed L2 block (use the hash of the common ancestor initially) - instead of the last L2 chain head. `safeBlockHash` and `finalizedBlockHash` must be updated accordingly. - -[block sync]: exec-engine.md#sync -[merge]: https://ethereum.org/en/eth2/merge/ +head of the L1 chain changes to a block that is not the child of the previous head but rather some other descendant +of an ancestor of the previous head. In that case, the rollup driver must first search for common ancestor, and can then +continue deriving with the new canonical L1 block after the common point. + +This sync starting point (L1 block to derive from, and L2 parent to build on) is determined by: + +- Retrieve the head block of the engine (`refL2`), then determine the L1 block it was derived from (`refL1`), + and where it builds on (`parentL2`). +- Fetch the L1 block at the same height (`currentL1`): + - If not found: consider this a reorg to a shorter L1 chain, continue. +- If the L1 source considers this canonical (`currentL1 == refL1`): + - Find the next L1 block (it may not exist yet) and return that as `nextRefL1`, along with the `refL2`. + - Note: after looking up `N+1` ensure L1 has not changed during block-by-number lookups (`refL1 == nextL1_parent`). +- While have not found a block in the engine common with the canonical chain, traverse the L2 chain back until genesis: + - Each step starts by caching the previous `currentL1` as `nextRefL1`. + - Lookup the parent by hash: Each step `refL2` should equal the previous `parentL2`. + `refL1` and `parentL2` are also traversed back by parsing the `refL2` block. + - The canonical L1 block is looked up at the same height (`currentL1`). + - If not found: consider this a reorg to a shorter L1 chain, continue. + - If the engine and canonical chain match (`refL1 == currentL1`), then return that as `nextRefL1`, along with `refL2`. +- If there are no common blocks after genesis, check if `refL2` and `currentL1` match the expected genesis blocks. +- If the genesis is correct, the last cached `nextRefL1` is returned, along with the L2 genesis. > Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more > than `FINALIZATION_DELAY_BLOCKS == 50400` in the past, hence preserving our finalization guarantees. From 55426b4b68ffd68a6ca25655cc7ac90bfa772290 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 01:38:51 +0100 Subject: [PATCH 154/585] specs/exec-engine: clarify sync section, refer to rollup node spec --- specs/exec-engine.md | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/specs/exec-engine.md b/specs/exec-engine.md index 4ea5dc973d13..23e6f48d8a38 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -119,12 +119,12 @@ as the engine implementation can sync state faster through methods like [snap-sy ### Happy-path sync -1. Engine API informs engine of chain head, unconditionally (part of regular node operation): +1. The rollup node informs the engine of the L2 chain head, unconditionally (part of regular node operation): - [`engine_executePayloadV1`][engine_executePayloadV1] is called with latest L2 block derived from L1. - [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1] is called with the current `unsafe`/`safe`/`finalized` L2 block hashes. -2. Engine requests headers from peers, in reverse till the parent hash matches the local chain -3. Engine catches up: +2. The engine requests headers from peers, in reverse till the parent hash matches the local chain +3. The engine catches up: a) A form of state sync is activated towards the finalized or head block hash b) A form of block sync pulls block bodies and processes towards head block hash @@ -134,17 +134,12 @@ the operation within the engine is the exact same as with L1 (although with an E ### Worst-case sync 1. Engine is out of sync, not peered and/or stalled due other reasons. -2. rollup node periodically fetches latest head from engine (`eth_getBlockByNumber`) -3. rollup node activates sync if the engine is out of sync but not syncing through P2P (`eth_syncing`) -4. rollup node inserts blocks, derived from L1, one by one, - starting from the engine head (or genesis block if unrecognized) up to the latest chain head. - (`engine_forkchoiceUpdatedV1`, `engine_executePayloadV1`) +2. The rollup node maintains latest head from engine (poll `eth_getBlockByNumber` and/or maintain a header subscription) +3. The rollup node activates sync if the engine is out of sync but not syncing through P2P (`eth_syncing`) +4. The rollup node inserts blocks, derived from L1, one by one, potentially adapting to L1 reorg(s), + as outlined in the [rollup node spec] (`engine_forkchoiceUpdatedV1`, `engine_executePayloadV1`) -See [rollup node sync spec][rollup-node-sync] for L1-based block syncing specification. - -> **TODO**: rollup node block-by-block sync (covered in rollup node PR #43) - -[rollup-node-sync]: ./rollup-node.md#sync +[rollup node spec]: rollup-node.md [eip-2718]: https://eips.ethereum.org/EIPS/eip-2718 [eip-2718-transactions]: https://eips.ethereum.org/EIPS/eip-2718#transactions From f5d763147e72e493015f560f1a36bbad0295f1f5 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 17:07:08 +0100 Subject: [PATCH 155/585] ref impl: return both refL1 and nextRefL1 for driver --- opnode/l2/sync_start.go | 3 +-- opnode/l2/sync_start_test.go | 2 +- specs/rollup-node.md | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index e763c972c280..19e9c855564d 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -15,8 +15,7 @@ var WrongChainErr = errors.New("wrong chain") // FindSyncStart finds nextRefL1: the L1 block needed next for sync, to derive into a L2 block on top of refL2. // If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. -func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - var refL1 eth.BlockID // the L1 block that was derived into refL2 +func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (refL1, nextRefL1, refL2 eth.BlockID, err error) { var parentL2 common.Hash // the parent of refL2 // Start at L2 head refL1, refL2, parentL2, err = reference.RefByL2Num(ctx, nil, genesis) diff --git a/opnode/l2/sync_start_test.go b/opnode/l2/sync_start_test.go index a0d8f2668ba7..2031c777126e 100644 --- a/opnode/l2/sync_start_test.go +++ b/opnode/l2/sync_start_test.go @@ -139,7 +139,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { } expectedRefL2 := mockID(c.ExpectedRefL2, expectedRefL2Num) - nextRefL1, refL2, err := FindSyncStart(context.Background(), msr, genesis) + _, nextRefL1, refL2, err := FindSyncStart(context.Background(), msr, genesis) if c.ExpectedErr != nil { assert.Error(t, err, "got next L1 %s (%d), onto L2: %s (%d)", nextRefL1.Hash[:1], nextRefL1.Number, refL2.Hash[:1], refL2.Number) assert.ErrorIs(t, err, c.ExpectedErr) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 7f777edda737..e7e353fb6310 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -58,6 +58,7 @@ First inputs are derived from L1 source data, then outputs are derived with L2 s The L2 block has the same format as a L1 block: a block-header and a list of transactions. The list of transaction carries: + - A *[L1 attributes transaction]* (always first item) - L2 transactions deposited by users in the L1 block (*[deposits]*, if any) @@ -86,7 +87,6 @@ These are then encoded as a [L1 attributes deposit] to update the [L1 Attributes [L1 attributes deposit]: deposits.md#l1-attributes-deposit [L1 Attributes Predeploy]: deposits.md#l1-attributes-predeploy - #### Transaction deposits derivation A [transaction deposit][transaction deposits] is an L2 transaction that has been submitted on L1, via a call to the @@ -115,7 +115,6 @@ The object properties must be set as follows: [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 - ### Output derivation Building a full block requires the earlier [derived payload attributes](#payload-attributes-derivation) From acf6a153cc83a7cb4ea9e70c5ab5a2fbc66ad934 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 11 Jan 2022 00:23:58 +0100 Subject: [PATCH 156/585] ref impl: driver agent: respond to head events and stay in sync --- opnode/l2/driver.go | 207 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 opnode/l2/driver.go diff --git a/opnode/l2/driver.go b/opnode/l2/driver.go new file mode 100644 index 000000000000..b7addb799a04 --- /dev/null +++ b/opnode/l2/driver.go @@ -0,0 +1,207 @@ +package l2 + +import ( + "context" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/event" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + + "github.com/ethereum/go-ethereum/log" +) + +type EngineDriver struct { + Ctx context.Context + Log log.Logger + // API bindings to execution engine + RPC DriverAPI + + SyncRef SyncReference + + // The current driving force, to shutdown before closing the engine. + driveSub ethereum.Subscription + // There may only be 1 driver at a time + driveLock sync.Mutex + + // Locks the L1 and L2 head changes, to keep a consistent view of the engine + headLock sync.RWMutex + + // l1Head tracks the L1 block corresponding to the l2Head + l1Head eth.BlockID + + // l2Head tracks the head-block of the engine + l2Head eth.BlockID + + // l2Finalized tracks the block the engine can safely regard as irreversible + // (a week for disputes, or maybe shorter if we see L1 finalize and take the derived L2 chain up till there) + l2Finalized eth.BlockID + + // The L1 block we are syncing towards, may be ahead of l1Head + l1Target eth.BlockID + + // Genesis starting point + Genesis Genesis +} + +// L1Head returns the block-id (hash and number) of the last L1 block that was derived into the L2 block +func (e *EngineDriver) L1Head() eth.BlockID { + e.headLock.RLock() + defer e.headLock.RUnlock() + return e.l1Head +} + +// L2Head returns the block-id (hash and number) of the L2 chain head +func (e *EngineDriver) L2Head() eth.BlockID { + e.headLock.RLock() + defer e.headLock.RUnlock() + return e.l2Head +} + +func (e *EngineDriver) Head() (l1Head eth.BlockID, l2Head eth.BlockID) { + e.headLock.RLock() + defer e.headLock.RUnlock() + return e.l1Head, e.l2Head +} + +func (e *EngineDriver) UpdateHead(l1Head eth.BlockID, l2Head eth.BlockID) { + e.headLock.Lock() + defer e.headLock.Unlock() + e.l1Head = l1Head + e.l2Head = l2Head +} + +func (e *EngineDriver) RequestHeadUpdate() error { + e.headLock.Lock() + defer e.headLock.Unlock() + refL1, refL2, _, err := e.SyncRef.RefByL2Num(e.Ctx, nil, &e.Genesis) + if err != nil { + return err + } + e.l1Head = refL1 + e.l2Head = refL2 + return nil +} + +func (e *EngineDriver) Drive(dl Downloader, l1Heads <-chan eth.HeadSignal) ethereum.Subscription { + e.driveLock.Lock() + defer e.driveLock.Unlock() + if e.driveSub != nil { + return e.driveSub + } + e.driveSub = event.NewSubscription(func(quit <-chan struct{}) error { + // keep making many sync steps if we can make sync progress + hot := time.Millisecond * 30 + // check on sync regularly, but prioritize sync triggers with head updates etc. + cold := time.Second * 8 + // at least try every minute to sync, even if things are going well + max := time.Minute + + syncTicker := time.NewTicker(cold) + defer syncTicker.Stop() + + // backoff sync attempts if we are not making progress + backoff := cold + syncQuickly := func() { + syncTicker.Reset(hot) + backoff = cold + } + // exponential backoff, add 10% each step, up to max. + syncBackoff := func() { + backoff += backoff / 10 + if backoff > max { + backoff = max + } + syncTicker.Reset(backoff) + } + + l2HeadPollTicker := time.NewTicker(time.Second * 14) + defer l2HeadPollTicker.Stop() + + onL2Update := func() { + // When we updated L2, we want to continue sync quickly + syncQuickly() + // And we want to slow down requesting the L2 engine for its head (we just changed it ourselves) + // Request head if we don't successfully change it in the next 14 seconds. + l2HeadPollTicker.Reset(time.Second * 14) + } + + for { + select { + case <-e.Ctx.Done(): + return e.Ctx.Err() + case <-quit: + return nil + case <-l2HeadPollTicker.C: + if err := e.RequestHeadUpdate(); err != nil { + e.Log.Error("failed to fetch L2 head info", "err", err) + } + continue + case l1HeadSig := <-l1Heads: + if e.l1Head == l1HeadSig.Self { + e.Log.Debug("Received L1 head signal, already synced to it, ignoring event", "l1_head", e.l1Head) + continue + } + if e.l1Head == l1HeadSig.Parent { + // Simple extend, a linear life is easy + if l2ID, err := DriverStep(e.Ctx, e.Log, e.RPC, dl, l1HeadSig.Self, e.l2Head, e.l2Finalized.Hash); err != nil { + e.Log.Error("Failed to extend L2 chain with new L1 block", "l1", l1HeadSig.Self, "l2", e.l2Head, "err", err) + // Retry sync later + e.l1Target = l1HeadSig.Self + onL2Update() + continue + } else { + e.UpdateHead(l1HeadSig.Self, l2ID) + continue + } + } + if e.l1Head.Number < l1HeadSig.Parent.Number { + e.Log.Debug("Received new L1 head, engine is out of sync, cannot immediately process", "l1", l1HeadSig.Self, "l2", e.l2Head) + } else { + e.Log.Warn("Received a L1 reorg, syncing new alternative chain", "l1", l1HeadSig.Self, "l2", e.l2Head) + } + + e.l1Target = l1HeadSig.Self + syncQuickly() + continue + case <-syncTicker.C: + // If already synced, or in case of failure, we slow down + syncBackoff() + if e.l1Head == e.l1Target { + e.Log.Debug("Engine is fully synced", "l1_head", e.l1Head, "l2_head", e.l2Head) + // TODO: even though we are fully synced, it may be worth attempting anyway, + // in case the e.l1Head is not updating (failed/broken L1 head subscription) + continue + } + e.Log.Debug("finding next sync step, engine syncing", "l2", e.l2Head, "l1", e.l1Head) + refL1, refL2, err := FindSyncStart(e.Ctx, e.SyncRef, &e.Genesis) + if err != nil { + e.Log.Error("Failed to find sync starting point", "err", err) + continue + } + if refL1 == e.l1Head { + e.Log.Debug("Engine is already synced, aborting sync", "l1_head", e.l1Head, "l2_head", e.l2Head) + continue + } + if l2ID, err := DriverStep(e.Ctx, e.Log, e.RPC, dl, refL1, refL2, e.l2Finalized.Hash); err != nil { + e.Log.Error("Failed to sync L2 chain with new L1 block", "l1", refL1, "onto_l2", refL2, "err", err) + continue + } else { + e.UpdateHead(refL1, l2ID) + } + // Successfully stepped toward target. Continue quickly if we are not there yet + if e.l1Head != e.l1Target { + onL2Update() + } + } + } + }) + return e.driveSub +} + +func (e *EngineDriver) Close() { + e.RPC.Close() + e.driveSub.Unsubscribe() +} From 26d812d38c082986d0e45ba9f9e7231e1a226f6b Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 12 Jan 2022 20:01:24 +0100 Subject: [PATCH 157/585] ref impl: no ctx in driver struct --- opnode/l2/driver.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/opnode/l2/driver.go b/opnode/l2/driver.go index b7addb799a04..d920b5481475 100644 --- a/opnode/l2/driver.go +++ b/opnode/l2/driver.go @@ -14,7 +14,6 @@ import ( ) type EngineDriver struct { - Ctx context.Context Log log.Logger // API bindings to execution engine RPC DriverAPI @@ -73,10 +72,10 @@ func (e *EngineDriver) UpdateHead(l1Head eth.BlockID, l2Head eth.BlockID) { e.l2Head = l2Head } -func (e *EngineDriver) RequestHeadUpdate() error { +func (e *EngineDriver) RequestHeadUpdate(ctx context.Context) error { e.headLock.Lock() defer e.headLock.Unlock() - refL1, refL2, _, err := e.SyncRef.RefByL2Num(e.Ctx, nil, &e.Genesis) + refL1, refL2, _, err := e.SyncRef.RefByL2Num(ctx, nil, &e.Genesis) if err != nil { return err } @@ -85,7 +84,7 @@ func (e *EngineDriver) RequestHeadUpdate() error { return nil } -func (e *EngineDriver) Drive(dl Downloader, l1Heads <-chan eth.HeadSignal) ethereum.Subscription { +func (e *EngineDriver) Drive(ctx context.Context, dl Downloader, l1Heads <-chan eth.HeadSignal) ethereum.Subscription { e.driveLock.Lock() defer e.driveLock.Unlock() if e.driveSub != nil { @@ -130,14 +129,16 @@ func (e *EngineDriver) Drive(dl Downloader, l1Heads <-chan eth.HeadSignal) ether for { select { - case <-e.Ctx.Done(): - return e.Ctx.Err() + case <-ctx.Done(): + return ctx.Err() case <-quit: return nil case <-l2HeadPollTicker.C: - if err := e.RequestHeadUpdate(); err != nil { + ctx, cancel := context.WithTimeout(ctx, time.Second*4) + if err := e.RequestHeadUpdate(ctx); err != nil { e.Log.Error("failed to fetch L2 head info", "err", err) } + cancel() continue case l1HeadSig := <-l1Heads: if e.l1Head == l1HeadSig.Self { @@ -146,7 +147,7 @@ func (e *EngineDriver) Drive(dl Downloader, l1Heads <-chan eth.HeadSignal) ether } if e.l1Head == l1HeadSig.Parent { // Simple extend, a linear life is easy - if l2ID, err := DriverStep(e.Ctx, e.Log, e.RPC, dl, l1HeadSig.Self, e.l2Head, e.l2Finalized.Hash); err != nil { + if l2ID, err := DriverStep(ctx, e.Log, e.RPC, dl, l1HeadSig.Self, e.l2Head, e.l2Finalized.Hash); err != nil { e.Log.Error("Failed to extend L2 chain with new L1 block", "l1", l1HeadSig.Self, "l2", e.l2Head, "err", err) // Retry sync later e.l1Target = l1HeadSig.Self @@ -176,7 +177,7 @@ func (e *EngineDriver) Drive(dl Downloader, l1Heads <-chan eth.HeadSignal) ether continue } e.Log.Debug("finding next sync step, engine syncing", "l2", e.l2Head, "l1", e.l1Head) - refL1, refL2, err := FindSyncStart(e.Ctx, e.SyncRef, &e.Genesis) + refL1, refL2, err := FindSyncStart(ctx, e.SyncRef, &e.Genesis) if err != nil { e.Log.Error("Failed to find sync starting point", "err", err) continue @@ -185,7 +186,7 @@ func (e *EngineDriver) Drive(dl Downloader, l1Heads <-chan eth.HeadSignal) ether e.Log.Debug("Engine is already synced, aborting sync", "l1_head", e.l1Head, "l2_head", e.l2Head) continue } - if l2ID, err := DriverStep(e.Ctx, e.Log, e.RPC, dl, refL1, refL2, e.l2Finalized.Hash); err != nil { + if l2ID, err := DriverStep(ctx, e.Log, e.RPC, dl, refL1, refL2, e.l2Finalized.Hash); err != nil { e.Log.Error("Failed to sync L2 chain with new L1 block", "l1", refL1, "onto_l2", refL2, "err", err) continue } else { From e3b8a00d4e5af814c2dba7ab372d034688600057 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 17:24:26 +0100 Subject: [PATCH 158/585] ref impl: driver - fix naming of nextRefL1 in driver, clarify head update --- opnode/l2/driver.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/opnode/l2/driver.go b/opnode/l2/driver.go index d920b5481475..2e1ffdea7d4a 100644 --- a/opnode/l2/driver.go +++ b/opnode/l2/driver.go @@ -177,20 +177,20 @@ func (e *EngineDriver) Drive(ctx context.Context, dl Downloader, l1Heads <-chan continue } e.Log.Debug("finding next sync step, engine syncing", "l2", e.l2Head, "l1", e.l1Head) - refL1, refL2, err := FindSyncStart(ctx, e.SyncRef, &e.Genesis) + _, nextRefL1, refL2, err := FindSyncStart(ctx, e.SyncRef, &e.Genesis) if err != nil { e.Log.Error("Failed to find sync starting point", "err", err) continue } - if refL1 == e.l1Head { + if nextRefL1 == e.l1Head { e.Log.Debug("Engine is already synced, aborting sync", "l1_head", e.l1Head, "l2_head", e.l2Head) continue } - if l2ID, err := DriverStep(ctx, e.Log, e.RPC, dl, refL1, refL2, e.l2Finalized.Hash); err != nil { - e.Log.Error("Failed to sync L2 chain with new L1 block", "l1", refL1, "onto_l2", refL2, "err", err) + if l2ID, err := DriverStep(ctx, e.Log, e.RPC, dl, nextRefL1, refL2, e.l2Finalized.Hash); err != nil { + e.Log.Error("Failed to sync L2 chain with new L1 block", "l1", nextRefL1, "onto_l2", refL2, "err", err) continue } else { - e.UpdateHead(refL1, l2ID) + e.UpdateHead(nextRefL1, l2ID) // l2ID is derived from the nextRefL1 } // Successfully stepped toward target. Continue quickly if we are not there yet if e.l1Head != e.l1Target { From 6314c80b0b9a0cce63c5e97cc7e38d6fde6eddcc Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 17:27:11 +0100 Subject: [PATCH 159/585] ref impl: undo extra refL1 return param --- opnode/l2/driver.go | 2 +- opnode/l2/sync_start.go | 3 ++- opnode/l2/sync_start_test.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/opnode/l2/driver.go b/opnode/l2/driver.go index 2e1ffdea7d4a..e1c5aea443a4 100644 --- a/opnode/l2/driver.go +++ b/opnode/l2/driver.go @@ -177,7 +177,7 @@ func (e *EngineDriver) Drive(ctx context.Context, dl Downloader, l1Heads <-chan continue } e.Log.Debug("finding next sync step, engine syncing", "l2", e.l2Head, "l1", e.l1Head) - _, nextRefL1, refL2, err := FindSyncStart(ctx, e.SyncRef, &e.Genesis) + nextRefL1, refL2, err := FindSyncStart(ctx, e.SyncRef, &e.Genesis) if err != nil { e.Log.Error("Failed to find sync starting point", "err", err) continue diff --git a/opnode/l2/sync_start.go b/opnode/l2/sync_start.go index 19e9c855564d..546fc055ac02 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/l2/sync_start.go @@ -15,7 +15,8 @@ var WrongChainErr = errors.New("wrong chain") // FindSyncStart finds nextRefL1: the L1 block needed next for sync, to derive into a L2 block on top of refL2. // If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. -func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (refL1, nextRefL1, refL2 eth.BlockID, err error) { +func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (nextRefL1, refL2 eth.BlockID, err error) { + var refL1 eth.BlockID // the L1 block the refL2 was derived from var parentL2 common.Hash // the parent of refL2 // Start at L2 head refL1, refL2, parentL2, err = reference.RefByL2Num(ctx, nil, genesis) diff --git a/opnode/l2/sync_start_test.go b/opnode/l2/sync_start_test.go index 2031c777126e..a0d8f2668ba7 100644 --- a/opnode/l2/sync_start_test.go +++ b/opnode/l2/sync_start_test.go @@ -139,7 +139,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { } expectedRefL2 := mockID(c.ExpectedRefL2, expectedRefL2Num) - _, nextRefL1, refL2, err := FindSyncStart(context.Background(), msr, genesis) + nextRefL1, refL2, err := FindSyncStart(context.Background(), msr, genesis) if c.ExpectedErr != nil { assert.Error(t, err, "got next L1 %s (%d), onto L2: %s (%d)", nextRefL1.Hash[:1], nextRefL1.Number, refL2.Hash[:1], refL2.Number) assert.ErrorIs(t, err, c.ExpectedErr) From ee435f93bf03ce1dcc7db8b50bafe3a61d125c0f Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 19 Jan 2022 14:22:25 -0500 Subject: [PATCH 160/585] Add revert on failed call in Dummy contract --- .../contracts/test/DummyContract.sol | 9 +- .../contracts/test/L1/DepositFeed.spec.ts | 135 ++++++++++-------- 2 files changed, 84 insertions(+), 60 deletions(-) diff --git a/packages/contracts/contracts/test/DummyContract.sol b/packages/contracts/contracts/test/DummyContract.sol index af6c38bde194..8d8aadfefb22 100644 --- a/packages/contracts/contracts/test/DummyContract.sol +++ b/packages/contracts/contracts/test/DummyContract.sol @@ -5,15 +5,18 @@ pragma solidity ^0.8.10; * For use in testing with a call from a contract rather than an EOA. */ contract Dummy { + error Failed(); + /** * Forwards a call. * @param _target Address to call * @param _data Data to forward */ function forward(address _target, bytes calldata _data) external payable { - (bool success, bytes memory ret) = _target.call{ value: msg.value }(_data); + (bool success, ) = _target.call{ value: msg.value }(_data); // Silence the 'Return value of low-level calls not used' warning. - success; - ret; + if (!success) { + revert Failed(); + } } } diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index 665fce2d4e93..d3dd712226e1 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -26,6 +26,8 @@ const decodeDepositEvent = async ( const events = await depositFeed.queryFilter( depositFeed.filters.TransactionDeposited() ) + console.log(events.length); + const eventArgs = events[events.length - 1].args return { @@ -63,13 +65,16 @@ describe('DepositFeed', () => { describe('Should emit the correct log values...', async () => { it('when an EOA deposits a transaction with 0 value.', async () => { - await depositFeed.depositTransaction( - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ) + const receipt = await ( + await depositFeed.depositTransaction( + ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ) + ).wait() + await expect(receipt.status).to.equal(1) const eventArgs = await decodeDepositEvent(depositFeed) @@ -85,13 +90,16 @@ describe('DepositFeed', () => { }) it('when an EOA deposits a contract creation with 0 value.', async () => { - await depositFeed.depositTransaction( - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA - ) + const receipt = await ( + await depositFeed.depositTransaction( + ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ) + ).wait() + await expect(receipt.status).to.equal(1) const eventArgs = await decodeDepositEvent(depositFeed) @@ -111,16 +119,19 @@ describe('DepositFeed', () => { const dummy = await (await ethers.getContractFactory('Dummy')).deploy() await dummy.deployed() - await dummy.forward( - depositFeed.address, - depositFeed.interface.encodeFunctionData('depositTransaction', [ - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA, - ]) - ) + const receipt = await ( + await dummy.forward( + depositFeed.address, + depositFeed.interface.encodeFunctionData('depositTransaction', [ + ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA, + ]) + ) + ).wait() + await expect(receipt.status).to.equal(1) const eventArgs = await decodeDepositEvent(depositFeed) @@ -138,16 +149,20 @@ describe('DepositFeed', () => { describe('and increase its eth balance...', async () => { it('when an EOA deposits a transaction with an ETH value.', async () => { const balBefore = await ethers.provider.getBalance(depositFeed.address) - await depositFeed.depositTransaction( - NON_ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - false, - '0x', - { - value: NON_ZERO_VALUE, - } - ) + const receipt = await ( + await depositFeed.depositTransaction( + NON_ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + false, + '0x', + { + value: NON_ZERO_VALUE, + } + ) + ).wait() + await expect(receipt.status).to.equal(1) + const balAfter = await ethers.provider.getBalance(depositFeed.address) const eventArgs = await decodeDepositEvent(depositFeed) @@ -166,16 +181,19 @@ describe('DepositFeed', () => { it('when an EOA deposits a contract creation with an ETH value.', async () => { const balBefore = await ethers.provider.getBalance(depositFeed.address) - await depositFeed.depositTransaction( - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - '0x', - { - value: NON_ZERO_VALUE, - } - ) + const receipt = await ( + await depositFeed.depositTransaction( + ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + true, + '0x', + { + value: NON_ZERO_VALUE, + } + ) + ).wait() + await expect(receipt.status).to.equal(1) const balAfter = await ethers.provider.getBalance(depositFeed.address) const eventArgs = await decodeDepositEvent(depositFeed) @@ -198,19 +216,22 @@ describe('DepositFeed', () => { await dummy.deployed() const balBefore = await ethers.provider.getBalance(depositFeed.address) - await dummy.forward( - depositFeed.address, - depositFeed.interface.encodeFunctionData('depositTransaction', [ - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA, - ]), - { - value: NON_ZERO_VALUE, - } - ) + const receipt = await ( + await dummy.forward( + depositFeed.address, + depositFeed.interface.encodeFunctionData('depositTransaction', [ + ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA, + ]), + { + value: NON_ZERO_VALUE, + } + ) + ).wait() + await expect(receipt.status).to.equal(1) const balAfter = await ethers.provider.getBalance(depositFeed.address) const eventArgs = await decodeDepositEvent(depositFeed) From 20a3ec9502d6e16c19ef08ddfea34b97f2d8f67a Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 19 Jan 2022 14:30:18 -0500 Subject: [PATCH 161/585] Add missing test cases --- .../contracts/test/L1/DepositFeed.spec.ts | 68 ++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index d3dd712226e1..edc6b2c4f0ba 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -26,7 +26,6 @@ const decodeDepositEvent = async ( const events = await depositFeed.queryFilter( depositFeed.filters.TransactionDeposited() ) - console.log(events.length); const eventArgs = events[events.length - 1].args @@ -65,7 +64,7 @@ describe('DepositFeed', () => { describe('Should emit the correct log values...', async () => { it('when an EOA deposits a transaction with 0 value.', async () => { - const receipt = await ( + const receipt = await( await depositFeed.depositTransaction( ZERO_ADDRESS, ZERO_BIGNUMBER, @@ -89,6 +88,37 @@ describe('DepositFeed', () => { }) }) + it('when a contract deposits a transaction with 0 value.', async () => { + // Deploy a dummy contract so we can impersonate it + const dummy = await (await ethers.getContractFactory('Dummy')).deploy() + await dummy.deployed() + + await expect( + dummy.forward( + depositFeed.address, + depositFeed.interface.encodeFunctionData('depositTransaction', [ + NON_ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA, + ]) + ) + ).to.not.be.reverted + + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(eventArgs).to.deep.equal({ + from: applyL1ToL2Alias(dummy.address), + to: NON_ZERO_ADDRESS, + value: ZERO_BIGNUMBER, + mint: ZERO_BIGNUMBER, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: false, + data: NON_ZERO_DATA, + }) + }) + it('when an EOA deposits a contract creation with 0 value.', async () => { const receipt = await ( await depositFeed.depositTransaction( @@ -179,6 +209,40 @@ describe('DepositFeed', () => { }) }) + it('when a contract deposits a transaction with an ETH value.', async () => { + // Deploy a dummy contract so we can impersonate it + const dummy = await (await ethers.getContractFactory('Dummy')).deploy() + await dummy.deployed() + // this is not emitting an event! + await expect( + dummy.forward( + depositFeed.address, + depositFeed.interface.encodeFunctionData('depositTransaction', [ + NON_ZERO_ADDRESS, + ZERO_BIGNUMBER, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA, + ]), + { + value: NON_ZERO_VALUE, + } + ) + ).to.not.be.reverted + + const eventArgs = await decodeDepositEvent(depositFeed) + + expect(eventArgs).to.deep.equal({ + from: applyL1ToL2Alias(dummy.address), + to: NON_ZERO_ADDRESS, + value: ZERO_BIGNUMBER, + mint: NON_ZERO_VALUE, + gasLimit: NON_ZERO_GASLIMIT, + isCreation: false, + data: NON_ZERO_DATA, + }) + }) + it('when an EOA deposits a contract creation with an ETH value.', async () => { const balBefore = await ethers.provider.getBalance(depositFeed.address) const receipt = await ( From 45b782b94c67a71bb44afd5fbbce6dc6dcd948a8 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 19 Jan 2022 14:33:16 -0500 Subject: [PATCH 162/585] Fix broken test --- packages/contracts/test/L1/DepositFeed.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index edc6b2c4f0ba..ed325b840c8c 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -66,7 +66,7 @@ describe('DepositFeed', () => { it('when an EOA deposits a transaction with 0 value.', async () => { const receipt = await( await depositFeed.depositTransaction( - ZERO_ADDRESS, + NON_ZERO_ADDRESS, ZERO_BIGNUMBER, NON_ZERO_GASLIMIT, false, @@ -79,7 +79,7 @@ describe('DepositFeed', () => { expect(eventArgs).to.deep.equal({ from: signerAddress, - to: ZERO_ADDRESS, + to: NON_ZERO_ADDRESS, mint: ZERO_BIGNUMBER, value: ZERO_BIGNUMBER, gasLimit: NON_ZERO_GASLIMIT, From a0f52018fde7a6c0e9fad2193e4496f9bd0aff5b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 20 Jan 2022 10:04:59 -0500 Subject: [PATCH 163/585] Ignore .deps folder --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 8bba35cddc0e..070c04688e8f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ node_modules yarn-error.log coverage.out +# hardhat automatically puts console.sol in here when you use it +.deps From a18d078b377e83e86895f7c5b7b86646dc6c325a Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 20 Jan 2022 21:54:32 +0100 Subject: [PATCH 164/585] ref impl: refactor driver into separate engine, loop and state --- opnode/l2/driver.go | 190 +++++--------------------------------- opnode/l2/driver_loop.go | 76 +++++++++++++++ opnode/l2/driver_state.go | 130 ++++++++++++++++++++++++++ 3 files changed, 228 insertions(+), 168 deletions(-) create mode 100644 opnode/l2/driver_loop.go create mode 100644 opnode/l2/driver_state.go diff --git a/opnode/l2/driver.go b/opnode/l2/driver.go index e1c5aea443a4..d4671caa7dcf 100644 --- a/opnode/l2/driver.go +++ b/opnode/l2/driver.go @@ -3,7 +3,6 @@ package l2 import ( "context" "sync" - "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/event" @@ -13,11 +12,17 @@ import ( "github.com/ethereum/go-ethereum/log" ) +type Driver interface { + requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) + findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) + driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) +} + type EngineDriver struct { Log log.Logger // API bindings to execution engine - RPC DriverAPI - + RPC DriverAPI + DL Downloader SyncRef SyncReference // The current driving force, to shutdown before closing the engine. @@ -25,184 +30,33 @@ type EngineDriver struct { // There may only be 1 driver at a time driveLock sync.Mutex - // Locks the L1 and L2 head changes, to keep a consistent view of the engine - headLock sync.RWMutex - - // l1Head tracks the L1 block corresponding to the l2Head - l1Head eth.BlockID - - // l2Head tracks the head-block of the engine - l2Head eth.BlockID - - // l2Finalized tracks the block the engine can safely regard as irreversible - // (a week for disputes, or maybe shorter if we see L1 finalize and take the derived L2 chain up till there) - l2Finalized eth.BlockID - - // The L1 block we are syncing towards, may be ahead of l1Head - l1Target eth.BlockID - - // Genesis starting point - Genesis Genesis -} - -// L1Head returns the block-id (hash and number) of the last L1 block that was derived into the L2 block -func (e *EngineDriver) L1Head() eth.BlockID { - e.headLock.RLock() - defer e.headLock.RUnlock() - return e.l1Head -} - -// L2Head returns the block-id (hash and number) of the L2 chain head -func (e *EngineDriver) L2Head() eth.BlockID { - e.headLock.RLock() - defer e.headLock.RUnlock() - return e.l2Head -} - -func (e *EngineDriver) Head() (l1Head eth.BlockID, l2Head eth.BlockID) { - e.headLock.RLock() - defer e.headLock.RUnlock() - return e.l1Head, e.l2Head -} - -func (e *EngineDriver) UpdateHead(l1Head eth.BlockID, l2Head eth.BlockID) { - e.headLock.Lock() - defer e.headLock.Unlock() - e.l1Head = l1Head - e.l2Head = l2Head + EngineDriverState } -func (e *EngineDriver) RequestHeadUpdate(ctx context.Context) error { - e.headLock.Lock() - defer e.headLock.Unlock() - refL1, refL2, _, err := e.SyncRef.RefByL2Num(ctx, nil, &e.Genesis) - if err != nil { - return err - } - e.l1Head = refL1 - e.l2Head = refL2 - return nil -} - -func (e *EngineDriver) Drive(ctx context.Context, dl Downloader, l1Heads <-chan eth.HeadSignal) ethereum.Subscription { +func (e *EngineDriver) Drive(ctx context.Context, l1Heads <-chan eth.HeadSignal) ethereum.Subscription { e.driveLock.Lock() defer e.driveLock.Unlock() if e.driveSub != nil { return e.driveSub } - e.driveSub = event.NewSubscription(func(quit <-chan struct{}) error { - // keep making many sync steps if we can make sync progress - hot := time.Millisecond * 30 - // check on sync regularly, but prioritize sync triggers with head updates etc. - cold := time.Second * 8 - // at least try every minute to sync, even if things are going well - max := time.Minute - - syncTicker := time.NewTicker(cold) - defer syncTicker.Stop() - // backoff sync attempts if we are not making progress - backoff := cold - syncQuickly := func() { - syncTicker.Reset(hot) - backoff = cold - } - // exponential backoff, add 10% each step, up to max. - syncBackoff := func() { - backoff += backoff / 10 - if backoff > max { - backoff = max - } - syncTicker.Reset(backoff) - } - - l2HeadPollTicker := time.NewTicker(time.Second * 14) - defer l2HeadPollTicker.Stop() + e.driveSub = event.NewSubscription(NewDriverLoop(ctx, &e.EngineDriverState, e.Log, l1Heads, e)) + return e.driveSub +} - onL2Update := func() { - // When we updated L2, we want to continue sync quickly - syncQuickly() - // And we want to slow down requesting the L2 engine for its head (we just changed it ourselves) - // Request head if we don't successfully change it in the next 14 seconds. - l2HeadPollTicker.Reset(time.Second * 14) - } +func (e *EngineDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { + refL1, refL2, _, err = e.SyncRef.RefByL2Num(ctx, nil, &e.Genesis) + return +} - for { - select { - case <-ctx.Done(): - return ctx.Err() - case <-quit: - return nil - case <-l2HeadPollTicker.C: - ctx, cancel := context.WithTimeout(ctx, time.Second*4) - if err := e.RequestHeadUpdate(ctx); err != nil { - e.Log.Error("failed to fetch L2 head info", "err", err) - } - cancel() - continue - case l1HeadSig := <-l1Heads: - if e.l1Head == l1HeadSig.Self { - e.Log.Debug("Received L1 head signal, already synced to it, ignoring event", "l1_head", e.l1Head) - continue - } - if e.l1Head == l1HeadSig.Parent { - // Simple extend, a linear life is easy - if l2ID, err := DriverStep(ctx, e.Log, e.RPC, dl, l1HeadSig.Self, e.l2Head, e.l2Finalized.Hash); err != nil { - e.Log.Error("Failed to extend L2 chain with new L1 block", "l1", l1HeadSig.Self, "l2", e.l2Head, "err", err) - // Retry sync later - e.l1Target = l1HeadSig.Self - onL2Update() - continue - } else { - e.UpdateHead(l1HeadSig.Self, l2ID) - continue - } - } - if e.l1Head.Number < l1HeadSig.Parent.Number { - e.Log.Debug("Received new L1 head, engine is out of sync, cannot immediately process", "l1", l1HeadSig.Self, "l2", e.l2Head) - } else { - e.Log.Warn("Received a L1 reorg, syncing new alternative chain", "l1", l1HeadSig.Self, "l2", e.l2Head) - } +func (e *EngineDriver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { + return FindSyncStart(ctx, e.SyncRef, &e.Genesis) +} - e.l1Target = l1HeadSig.Self - syncQuickly() - continue - case <-syncTicker.C: - // If already synced, or in case of failure, we slow down - syncBackoff() - if e.l1Head == e.l1Target { - e.Log.Debug("Engine is fully synced", "l1_head", e.l1Head, "l2_head", e.l2Head) - // TODO: even though we are fully synced, it may be worth attempting anyway, - // in case the e.l1Head is not updating (failed/broken L1 head subscription) - continue - } - e.Log.Debug("finding next sync step, engine syncing", "l2", e.l2Head, "l1", e.l1Head) - nextRefL1, refL2, err := FindSyncStart(ctx, e.SyncRef, &e.Genesis) - if err != nil { - e.Log.Error("Failed to find sync starting point", "err", err) - continue - } - if nextRefL1 == e.l1Head { - e.Log.Debug("Engine is already synced, aborting sync", "l1_head", e.l1Head, "l2_head", e.l2Head) - continue - } - if l2ID, err := DriverStep(ctx, e.Log, e.RPC, dl, nextRefL1, refL2, e.l2Finalized.Hash); err != nil { - e.Log.Error("Failed to sync L2 chain with new L1 block", "l1", nextRefL1, "onto_l2", refL2, "err", err) - continue - } else { - e.UpdateHead(nextRefL1, l2ID) // l2ID is derived from the nextRefL1 - } - // Successfully stepped toward target. Continue quickly if we are not there yet - if e.l1Head != e.l1Target { - onL2Update() - } - } - } - }) - return e.driveSub +func (e *EngineDriver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { + return DriverStep(ctx, e.Log, e.RPC, e.DL, nextRefL1, refL2, finalized.Hash) } func (e *EngineDriver) Close() { - e.RPC.Close() e.driveSub.Unsubscribe() } diff --git a/opnode/l2/driver_loop.go b/opnode/l2/driver_loop.go new file mode 100644 index 000000000000..3dd4b46a3c8c --- /dev/null +++ b/opnode/l2/driver_loop.go @@ -0,0 +1,76 @@ +package l2 + +import ( + "context" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/log" +) + +// keep making many sync steps if we can make sync progress +const hot = time.Millisecond * 30 + +// check on sync regularly, but prioritize sync triggers with head updates etc. +const cold = time.Second * 8 + +// at least try every minute to sync, even if things are going well +const max = time.Minute + +func NewDriverLoop(ctx context.Context, state StateMachine, log log.Logger, l1Heads <-chan eth.HeadSignal, driver Driver) func(quit <-chan struct{}) error { + + backoff := cold + syncTicker := time.NewTicker(cold) + l2HeadPoll := time.NewTicker(time.Second * 14) + + // exponential backoff, add 10% each step, up to max. + syncBackoff := func() { + backoff += backoff / 10 + if backoff > max { + backoff = max + } + syncTicker.Reset(backoff) + } + syncQuickly := func() { + syncTicker.Reset(hot) + backoff = cold + } + onL2Update := func() { + // And we want to slow down requesting the L2 engine for its head (we just changed it ourselves) + // Request head if we don't successfully change it in the next 14 seconds. + l2HeadPoll.Reset(time.Second * 14) + } + return func(quit <-chan struct{}) error { + defer syncTicker.Stop() + defer l2HeadPoll.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-quit: + return nil + case <-l2HeadPoll.C: + ctx, cancel := context.WithTimeout(ctx, time.Second*4) + if state.RequestUpdate(ctx, log, driver) { + onL2Update() + } + cancel() + continue + case l1HeadSig := <-l1Heads: + if state.NotifyL1Head(ctx, log, l1HeadSig, driver) { + syncQuickly() + } + continue + case <-syncTicker.C: + // If already synced, or in case of failure, we slow down + syncBackoff() + if state.RequestSync(ctx, log, driver) { + // Successfully stepped toward target. Continue quickly if we are not there yet + syncQuickly() + onL2Update() + } + } + } + } +} diff --git a/opnode/l2/driver_state.go b/opnode/l2/driver_state.go new file mode 100644 index 000000000000..5151e3c66d4d --- /dev/null +++ b/opnode/l2/driver_state.go @@ -0,0 +1,130 @@ +package l2 + +import ( + "context" + "sync" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/log" +) + +type StateMachine interface { + RequestUpdate(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) + RequestSync(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) + NotifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver Driver) (l2Updated bool) +} + +type EngineDriverState struct { + // Locks the L1 and L2 head changes, to keep a consistent view of the engine + headLock sync.RWMutex + + // l1Head tracks the L1 block corresponding to the l2Head + l1Head eth.BlockID + + // l2Head tracks the head-block of the engine + l2Head eth.BlockID + + // l2Finalized tracks the block the engine can safely regard as irreversible + // (a week for disputes, or maybe shorter if we see L1 finalize and take the derived L2 chain up till there) + l2Finalized eth.BlockID + + // The L1 block we are syncing towards, may be ahead of l1Head + l1Target eth.BlockID + + // Genesis starting point + Genesis Genesis +} + +// L1Head returns the block-id (hash and number) of the last L1 block that was derived into the L2 block +func (e *EngineDriverState) L1Head() eth.BlockID { + e.headLock.RLock() + defer e.headLock.RUnlock() + return e.l1Head +} + +// L2Head returns the block-id (hash and number) of the L2 chain head +func (e *EngineDriverState) L2Head() eth.BlockID { + e.headLock.RLock() + defer e.headLock.RUnlock() + return e.l2Head +} + +func (e *EngineDriverState) Head() (l1Head eth.BlockID, l2Head eth.BlockID) { + e.headLock.RLock() + defer e.headLock.RUnlock() + return e.l1Head, e.l2Head +} + +func (e *EngineDriverState) UpdateHead(l1Head eth.BlockID, l2Head eth.BlockID) { + e.headLock.Lock() + defer e.headLock.Unlock() + e.l1Head = l1Head + e.l2Head = l2Head +} + +func (e *EngineDriverState) RequestUpdate(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) { + refL1, refL2, err := driver.requestEngineHead(ctx) + if err != nil { + log.Error("failed to request engine head", "err", err) + return false + } + e.headLock.Lock() + defer e.headLock.Unlock() + + e.l1Head = refL1 + e.l2Head = refL2 + return e.l1Head != refL1 || e.l2Head != refL2 +} + +func (e *EngineDriverState) RequestSync(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) { + if e.l1Head == e.l1Target { + log.Debug("Engine is fully synced", "l1_head", e.l1Head, "l2_head", e.l2Head) + // TODO: even though we are fully synced, it may be worth attempting anyway, + // in case the e.l1Head is not updating (failed/broken L1 head subscription) + return false + } + log.Debug("finding next sync step, engine syncing", "l2", e.l2Head, "l1", e.l1Head) + nextRefL1, refL2, err := driver.findSyncStart(ctx) + if err != nil { + log.Error("Failed to find sync starting point", "err", err) + return false + } + if nextRefL1 == e.l1Head { + log.Debug("Engine is already synced, aborting sync", "l1_head", e.l1Head, "l2_head", e.l2Head) + return false + } + if l2ID, err := driver.driverStep(ctx, nextRefL1, refL2, e.l2Finalized); err != nil { + log.Error("Failed to sync L2 chain with new L1 block", "l1", nextRefL1, "onto_l2", refL2, "err", err) + return false + } else { + e.UpdateHead(nextRefL1, l2ID) // l2ID is derived from the nextRefL1 + } + return e.l1Head != e.l1Target +} + +func (e *EngineDriverState) NotifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver Driver) (l2Updated bool) { + if e.l1Head == l1HeadSig.Self { + log.Debug("Received L1 head signal, already synced to it, ignoring event", "l1_head", e.l1Head) + return + } + if e.l1Head == l1HeadSig.Parent { + // Simple extend, a linear life is easy + if l2ID, err := driver.driverStep(ctx, l1HeadSig.Self, e.l2Head, e.l2Finalized); err != nil { + log.Error("Failed to extend L2 chain with new L1 block", "l1", l1HeadSig.Self, "l2", e.l2Head, "err", err) + // Retry sync later + e.l1Target = l1HeadSig.Self + return false + } else { + e.UpdateHead(l1HeadSig.Self, l2ID) + return true + } + } + if e.l1Head.Number < l1HeadSig.Parent.Number { + log.Debug("Received new L1 head, engine is out of sync, cannot immediately process", "l1", l1HeadSig.Self, "l2", e.l2Head) + } else { + log.Warn("Received a L1 reorg, syncing new alternative chain", "l1", l1HeadSig.Self, "l2", e.l2Head) + } + + e.l1Target = l1HeadSig.Self + return false +} From 092adcde31bcf31e21a975a9d9dd05de8e6dd5a8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 20 Jan 2022 22:34:14 +0100 Subject: [PATCH 165/585] ref impl: include testlog for testing --- opnode/internal/testlog/LICENSE | 165 +++++++++++++++++++++++++++++ opnode/internal/testlog/README.md | 6 ++ opnode/internal/testlog/testlog.go | 142 +++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 opnode/internal/testlog/LICENSE create mode 100644 opnode/internal/testlog/README.md create mode 100644 opnode/internal/testlog/testlog.go diff --git a/opnode/internal/testlog/LICENSE b/opnode/internal/testlog/LICENSE new file mode 100644 index 000000000000..65c5ca88a67c --- /dev/null +++ b/opnode/internal/testlog/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/opnode/internal/testlog/README.md b/opnode/internal/testlog/README.md new file mode 100644 index 000000000000..3f340f73e488 --- /dev/null +++ b/opnode/internal/testlog/README.md @@ -0,0 +1,6 @@ +# testlog + +`github.com/ethereum/go-ethereum/internal/testlog`: a Go-ethereum util for logging in tests. + +Since we use the same logging, but as an external package, we have to move the test utility to our own internal package. + diff --git a/opnode/internal/testlog/testlog.go b/opnode/internal/testlog/testlog.go new file mode 100644 index 000000000000..684339f16d80 --- /dev/null +++ b/opnode/internal/testlog/testlog.go @@ -0,0 +1,142 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package testlog provides a log handler for unit tests. +package testlog + +import ( + "sync" + "testing" + + "github.com/ethereum/go-ethereum/log" +) + +// Handler returns a log handler which logs to the unit test log of t. +func Handler(t *testing.T, level log.Lvl) log.Handler { + return log.LvlFilterHandler(level, &handler{t, log.TerminalFormat(false)}) +} + +type handler struct { + t *testing.T + fmt log.Format +} + +func (h *handler) Log(r *log.Record) error { + h.t.Logf("%s", h.fmt.Format(r)) + return nil +} + +// logger implements log.Logger such that all output goes to the unit test log via +// t.Logf(). All methods in between logger.Trace, logger.Debug, etc. are marked as test +// helpers, so the file and line number in unit test output correspond to the call site +// which emitted the log message. +type logger struct { + t *testing.T + l log.Logger + mu *sync.Mutex + h *bufHandler +} + +type bufHandler struct { + buf []*log.Record + fmt log.Format +} + +func (h *bufHandler) Log(r *log.Record) error { + h.buf = append(h.buf, r) + return nil +} + +// Logger returns a logger which logs to the unit test log of t. +func Logger(t *testing.T, level log.Lvl) log.Logger { + l := &logger{ + t: t, + l: log.New(), + mu: new(sync.Mutex), + h: &bufHandler{fmt: log.TerminalFormat(false)}, + } + l.l.SetHandler(log.LvlFilterHandler(level, l.h)) + return l +} + +func (l *logger) Trace(msg string, ctx ...interface{}) { + l.t.Helper() + l.mu.Lock() + defer l.mu.Unlock() + l.l.Trace(msg, ctx...) + l.flush() +} + +func (l *logger) Debug(msg string, ctx ...interface{}) { + l.t.Helper() + l.mu.Lock() + defer l.mu.Unlock() + l.l.Debug(msg, ctx...) + l.flush() +} + +func (l *logger) Info(msg string, ctx ...interface{}) { + l.t.Helper() + l.mu.Lock() + defer l.mu.Unlock() + l.l.Info(msg, ctx...) + l.flush() +} + +func (l *logger) Warn(msg string, ctx ...interface{}) { + l.t.Helper() + l.mu.Lock() + defer l.mu.Unlock() + l.l.Warn(msg, ctx...) + l.flush() +} + +func (l *logger) Error(msg string, ctx ...interface{}) { + l.t.Helper() + l.mu.Lock() + defer l.mu.Unlock() + l.l.Error(msg, ctx...) + l.flush() +} + +func (l *logger) Crit(msg string, ctx ...interface{}) { + l.t.Helper() + l.mu.Lock() + defer l.mu.Unlock() + l.l.Crit(msg, ctx...) + l.flush() +} + +func (l *logger) New(ctx ...interface{}) log.Logger { + return &logger{l.t, l.l.New(ctx...), l.mu, l.h} +} + +func (l *logger) GetHandler() log.Handler { + return l.l.GetHandler() +} + +func (l *logger) SetHandler(h log.Handler) { + l.l.SetHandler(h) +} + +// flush writes all buffered messages and clears the buffer. +func (l *logger) flush() { + l.t.Helper() + for _, r := range l.h.buf { + l.t.Logf("%s", l.h.fmt.Format(r)) + } + l.h.buf = nil +} From b3b11d13cf034f4e2edc0543ec5e0261e49d9e99 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 20 Jan 2022 22:34:54 +0100 Subject: [PATCH 166/585] ref impl: test requestSync of driver state --- go.mod | 1 + go.sum | 1 + opnode/l2/driver_state_test.go | 111 +++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 opnode/l2/driver_state_test.go diff --git a/go.mod b/go.mod index fe6901c885bc..0dd26cc8bbd3 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/tsdb v0.7.1 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/stretchr/objx v0.1.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect diff --git a/go.sum b/go.sum index f2cb64c940d4..044d42ce4f0d 100644 --- a/go.sum +++ b/go.sum @@ -336,6 +336,7 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/opnode/l2/driver_state_test.go b/opnode/l2/driver_state_test.go new file mode 100644 index 000000000000..b2be025e6ff9 --- /dev/null +++ b/opnode/l2/driver_state_test.go @@ -0,0 +1,111 @@ +package l2 + +import ( + "context" + "strconv" + "strings" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +type testID string + +func (id testID) ID() eth.BlockID { + parts := strings.Split(string(id), ":") + if len(parts) != 2 { + panic("bad id") + } + if len(parts[0]) > 32 { + panic("test ID hash too long") + } + var h common.Hash + copy(h[:], parts[0]) + v, err := strconv.ParseUint(parts[1], 0, 64) + if err != nil { + panic(err) + } + return eth.BlockID{ + Hash: h, + Number: v, + } +} + +type testState struct { + l1Head testID + l2Head testID + l2Finalized testID + l1Target testID + genesisL1 testID + genesisL2 testID +} + +func makeState(st testState) *EngineDriverState { + return &EngineDriverState{ + l1Head: st.l1Head.ID(), + l2Head: st.l2Head.ID(), + l2Finalized: st.l2Finalized.ID(), + l1Target: st.l1Target.ID(), + Genesis: Genesis{ + L1: st.genesisL1.ID(), + L2: st.genesisL2.ID(), + }, + } +} + +type mockDriver struct { + mock.Mock +} + +func (m *mockDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { + returnArgs := m.Called(ctx) + refL1 = returnArgs.Get(0).(eth.BlockID) + refL2 = returnArgs.Get(1).(eth.BlockID) + err = returnArgs.Get(2).(error) + return +} + +func (m *mockDriver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { + returnArgs := m.Called(ctx) + nextRefL1 = returnArgs.Get(0).(eth.BlockID) + refL2 = returnArgs.Get(1).(eth.BlockID) + err, _ = returnArgs.Get(2).(error) + return +} + +func (m *mockDriver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { + returnArgs := m.Called(ctx, nextRefL1, refL2, finalized) + l2ID = returnArgs.Get(0).(eth.BlockID) + err, _ = returnArgs.Get(1).(error) + return +} + +var _ Driver = (*mockDriver)(nil) + +func TestEngineDriverState_RequestSync(t *testing.T) { + log := testlog.Logger(t, log.LvlTrace) + driver := new(mockDriver) + ctx := context.Background() + + state := makeState(testState{ + l1Head: "c:2", + l2Head: "C:2", + l2Finalized: "B:1", + l1Target: "e:4", + genesisL1: "a:0", + genesisL2: "b:0", + }) + driver.On("findSyncStart", ctx).Return(testID("d:3").ID(), testID("C:2").ID(), nil) + driver.On("driverStep", ctx, testID("d:3").ID(), testID("C:2").ID(), testID("B:1").ID()).Return(testID("D:3").ID(), nil) + + l2Updated := state.RequestSync(ctx, log, driver) + + assert.Equal(t, state.l1Head, testID("d:3").ID()) + assert.Equal(t, state.l2Head, testID("D:3").ID()) + assert.True(t, l2Updated) +} From 3b27b606160ff62cb1a1252092d3a848471c56b0 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 20 Jan 2022 22:38:32 +0100 Subject: [PATCH 167/585] specs/rollup-node: fix typo --- specs/rollup-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index e7e353fb6310..6b00dbd09d0f 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -92,7 +92,7 @@ These are then encoded as a [L1 attributes deposit] to update the [L1 Attributes A [transaction deposit][transaction deposits] is an L2 transaction that has been submitted on L1, via a call to the [deposit feed contract]. -Refer to the[**deposit feed contract specification**][deposit-feed-spec] for details on how +Refer to the [**deposit feed contract specification**][deposit-feed-spec] for details on how deposit properties are emitted in deposit log entries. [deposit-feed-spec]: deposits.md#deposit-feed-contract From 94dba5a5a67331abaf708a999fbf179937aea0ba Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 21 Jan 2022 16:53:09 +0100 Subject: [PATCH 168/585] ref impl: document the l2 StateMachine and Driver interfaces --- opnode/l2/driver.go | 9 +++++++++ opnode/l2/driver_state.go | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/opnode/l2/driver.go b/opnode/l2/driver.go index d4671caa7dcf..d6ed5ea8ef57 100644 --- a/opnode/l2/driver.go +++ b/opnode/l2/driver.go @@ -12,9 +12,18 @@ import ( "github.com/ethereum/go-ethereum/log" ) +// Driver exposes the driver functionality that maintains the external execution-engine. type Driver interface { + // requestEngineHead retrieves the L2 head reference of the engine, as well as the L1 reference it was derived from. + // An error is returned when the L2 head information could not be retrieved (timeout or connection issue) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) + // findSyncStart statelessly finds the next L1 block to derive, and on which L2 block it applies. + // If the engine is fully synced, then the last derived L1 block, and parent L2 block, is repeated. + // An error is returned if the sync starting point could not be determined (due to timeouts, wrong-chain, etc.) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) + // driverStep explicitly calls the engine to derive a L1 block into a L2 block, and apply it on top of the given L2 block. + // The finalized L2 block is provided to update the engine with finality, but does not affect the derivation step itself. + // The resulting L2 block ID is returned, or an error if the derivation fails. driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) } diff --git a/opnode/l2/driver_state.go b/opnode/l2/driver_state.go index 5151e3c66d4d..35c511838da2 100644 --- a/opnode/l2/driver_state.go +++ b/opnode/l2/driver_state.go @@ -8,9 +8,17 @@ import ( "github.com/ethereum/go-ethereum/log" ) +// StateMachine provides control over the driver state, when given control over the Driver actions. type StateMachine interface { + // RequestUpdate tries to update the state-machine with the driver head information. + // If the state-machine changed, considering the engine L1 and L2 head, it will return true. False otherwise. RequestUpdate(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) + // RequestSync tries to sync the provided driver towards the sync target of the state-machine. + // If the L2 syncs a step, but is not finished yet, it will return true. False otherwise. RequestSync(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) + // NotifyL1Head updates the state-machine with the L1 signal, + // and attempts to sync the driver if the update extends the previous head. + // Returns true if the driver successfully derived and synced the L2 block to match L1. False otherwise. NotifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver Driver) (l2Updated bool) } From ffa9f10fbb8da5d60f3eed29107ff7c5432db9cc Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 11 Jan 2022 00:39:23 +0100 Subject: [PATCH 169/585] ref impl: implement rollup node main process, connect to sources/engines, starts drivers, handle shutdown --- go.sum | 19 ++++ opnode/node/node.go | 220 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 238 insertions(+), 1 deletion(-) diff --git a/go.sum b/go.sum index 044d42ce4f0d..05182a2c2353 100644 --- a/go.sum +++ b/go.sum @@ -103,17 +103,20 @@ github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r 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 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a h1:ifL2rtsPv8plDlAucTQdLecBgLWph9HeXA0CHDKpxIE= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= 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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= 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= @@ -177,6 +180,7 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/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= @@ -185,15 +189,18 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= 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 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= 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= @@ -209,6 +216,7 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y 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-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -252,12 +260,14 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= 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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 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 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= @@ -265,7 +275,9 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -317,8 +329,10 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/protolambda/ask v0.1.2 h1:BSQP7VDmh+L0lLFjEYUMrTnb2SwdT64UY3vXqDuIIok= github.com/protolambda/ask v0.1.2/go.mod h1:7WB3T4BXZhKUaDcEjF7Ksgi7HCrBDxM37gyM1EhwkmM= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= 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= @@ -334,6 +348,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO 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 v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= 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 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= @@ -352,6 +367,7 @@ github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= 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= @@ -443,6 +459,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 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= @@ -496,6 +513,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -584,6 +602,7 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= 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= diff --git a/opnode/node/node.go b/opnode/node/node.go index 6d8d7858152e..9e338d576dd7 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -1,8 +1,69 @@ package node -import "context" +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + + "github.com/ethereum-optimism/optimistic-specs/opnode/l1" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum/go-ethereum/ethclient" + + "github.com/ethereum/go-ethereum/rpc" +) + +type GenesisConf struct { + L2Hash common.Hash `ask:"--l2-hash" help:"Genesis block hash of L2"` + L1Hash common.Hash `ask:"--l1-hash" help:"Block hash of L1 after (not incl.) which L1 starts deriving blocks"` + L1Num uint64 `ask:"--l1-num" help:"Block number of L1 matching the l1-hash"` +} + +func (conf *GenesisConf) GetGenesis() l2.Genesis { + return l2.Genesis{ + L1: eth.BlockID{Hash: conf.L1Hash, Number: conf.L1Num}, + // TODO: if we start from a squashed snapshot we might have a non-zero L2 genesis number + L2: eth.BlockID{Hash: conf.L2Hash, Number: 0}, + } +} type OpNodeCmd struct { + L1NodeAddrs []string `ask:"--l1" help:"Addresses of L1 User JSON-RPC endpoints to use (eth namespace required)"` + L2EngineAddrs []string `ask:"--l2" help:"Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)"` + + LogCmd `ask:".log" help:"Log configuration"` + + Genesis GenesisConf `ask:".genesis" help:"Genesis anchor point"` + + // during later sequencer rollup implementation: + // TODO: multi-addrs option (static peers) + // TODO: bootnodes option (bootstrap discovery of more peers) + + log log.Logger + + // (combined) source to fetch data from + l1Source eth.L1Source + + // engines to keep synced + l2Engines []*l2.EngineDriver + + l1Downloader l1.Downloader + + ctx context.Context + close chan chan error +} + +func (c *OpNodeCmd) Default() { + c.L1NodeAddrs = []string{"http://127.0.0.1:8545"} + c.L2EngineAddrs = []string{"http://127.0.0.1:8551"} } func (c *OpNodeCmd) Help() string { @@ -10,9 +71,166 @@ func (c *OpNodeCmd) Help() string { } func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { + logger := c.LogCmd.Create() + c.log = logger + c.ctx = ctx + + if c.Genesis == (GenesisConf{}) { + return errors.New("genesis configuration required") + } + + l1Sources := make([]eth.L1Source, 0, len(c.L1NodeAddrs)) + for i, addr := range c.L1NodeAddrs { + // L1 exec engine: read-only, to update L2 consensus with + l1Node, err := rpc.DialContext(ctx, addr) + if err != nil { + // HTTP or WS RPC may create a disconnected client, RPC over IPC may fail directly + if l1Node == nil { + return fmt.Errorf("failed to dial L1 address %d (%s): %v", i, addr, err) + } + c.log.Warn("failed to dial L1 address, but may connect later", "i", i, "addr", addr, "err", err) + } + // TODO: we may need to authenticate the connection with L1 + // l1Node.SetHeader() + cl := ethclient.NewClient(l1Node) + l1Sources = append(l1Sources, cl) + } + if len(l1Sources) == 0 { + return fmt.Errorf("need at least one L1 source endpoint, see --l1") + } + + // Combine L1 sources, so work can be balanced between them + c.l1Source = eth.NewCombinedL1Source(l1Sources) + l1CanonicalChain := eth.CanonicalChain(c.l1Source) + + c.l1Downloader = l1.NewDownloader(c.l1Source) + + for i, addr := range c.L2EngineAddrs { + // L2 exec engine: updated by this OpNode (L2 consensus layer node) + backend, err := rpc.DialContext(ctx, addr) + if err != nil { + if backend == nil { + return fmt.Errorf("failed to dial L2 address %d (%s): %v", i, addr, err) + } + c.log.Warn("failed to dial L2 address, but may connect later", "i", i, "addr", addr, "err", err) + } + // TODO: we may need to authenticate the connection with L2 + // backend.SetHeader() + client := &l2.EngineClient{ + RPCBackend: backend, + EthBackend: ethclient.NewClient(backend), + Log: c.log.New("engine_client", i), + } + engine := &l2.EngineDriver{ + Ctx: c.ctx, + Log: c.log.New("engine", i), + RPC: client, + SyncRef: l2.SyncSource{ + L1: l1CanonicalChain, + L2: client, + }, + } + c.l2Engines = append(c.l2Engines, engine) + } + + // TODO: maybe spin up an API server + // (to get debug data, change runtime settings like logging, serve pprof, get peering info, node health, etc.) + + c.close = make(chan chan error) + + go c.RunNode() + return nil } +func (c *OpNodeCmd) RunNode() { + c.log.Info("Starting OpNode") + + var unsub []func() + mergeSub := func(sub ethereum.Subscription, errMsg string) { + unsub = append(unsub, sub.Unsubscribe) + go func() { + err, ok := <-sub.Err() + if !ok { + return + } + c.log.Error(errMsg, "err", err) + }() + } + + c.log.Info("Fetching rollup starting point") + + // We download receipts in parallel + c.l1Downloader.AddReceiptWorkers(4) + + // Feed of eth.HeadSignal + var l1HeadsFeed event.Feed + + c.log.Info("Attaching execution engine(s)") + for _, eng := range c.l2Engines { + // Update genesis info, to anchor sync at + eng.Genesis = c.Genesis.GetGenesis() + // Request initial head update, default to genesis otherwise + if err := eng.RequestHeadUpdate(); err != nil { + eng.Log.Error("failed to fetch engine head, defaulting to genesis", "err", err) + eng.UpdateHead(eng.Genesis.L1, eng.Genesis.L2) + } + + // driver subscribes to L1 head changes + l1SubCh := make(chan eth.HeadSignal, 10) + l1HeadsFeed.Subscribe(l1SubCh) + // start driving engine: sync blocks by deriving them from L1 and driving them into the engine + engDriveSub := eng.Drive(c.l1Downloader, l1SubCh) + mergeSub(engDriveSub, "engine driver unexpectedly failed") + } + + // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync + l1HeadsSub := event.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (event.Subscription, error) { + if err != nil { + c.log.Warn("resubscribing after failed L1 subscription", "err", err) + } + return eth.WatchHeadChanges(c.ctx, c.l1Source, eth.HeadSignalFn(func(sig eth.HeadSignal) { + l1HeadsFeed.Send(sig) + })) + }) + mergeSub(l1HeadsSub, "l1 heads subscription failed") + + // subscribe to L1 heads for info + l1Heads := make(chan eth.HeadSignal, 10) + l1HeadsFeed.Subscribe(l1Heads) + + c.log.Info("Start-up complete!") + + for { + select { + case l1Head := <-l1Heads: + c.log.Info("New L1 head", "head", l1Head.Self, "parent", l1Head.Parent) + // TODO: maybe log other info on interval or other chain events (individual engines also log things) + case done := <-c.close: + c.log.Info("Closing OpNode") + // close all tasks + for _, f := range unsub { + f() + } + // close L1 data source + c.l1Source.Close() + // close L2 engines + for _, eng := range c.l2Engines { + eng.Close() + } + // signal back everything closed without error + done <- nil + return + } + } +} + func (c *OpNodeCmd) Close() error { + if c.close != nil { + done := make(chan error) + c.close <- done + err := <-done + return err + } return nil } From 475cbce1fccdafa39804d72bf17e54dc101bf1cb Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 12 Jan 2022 19:47:17 +0100 Subject: [PATCH 170/585] ref impl: readme --- opnode/README.md | 38 ++++++++++++++++++++++++++++++++++++++ package.json | 6 +++--- 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 opnode/README.md diff --git a/opnode/README.md b/opnode/README.md new file mode 100644 index 000000000000..d93e12510d03 --- /dev/null +++ b/opnode/README.md @@ -0,0 +1,38 @@ +# opnode + +This is the reference implementation of the [rollup-node spec](../specs/rollup-node.md). + +## Compiling + +```shell +go build -o op ./opnode/cmd +``` + +## Running + +Options can be reviewed with: + +```shell +./op run --help +``` + +To start syncing the rollup: + +Connect to at least one L1 RPC and L2 execution engine: + +- L1: use any L1 node / RPC (websocket connection path may differ) +- L2: run the Optimism fork of geth: + +Initialize the L2 chain with a `genesis.json` chain spec like L1, with the Merge fork activated from genesis. + +Specify genesis details: + +- L1 number / hash: starting-point of L2 chain inputs +- L2 genesis hash: to confirm we are building on the correct L2 genesis + +```shell +# websockets or IPC preferred for event notifications to improve sync, http RPC works with adaptive polling. +op node run \ + --l1=ws://localhost:8546 --l2=ws//localhost:9001 \ + --genesis.l1-num=.... --genesis.l1-hash=..... --genesis.l2-hash=.... +``` diff --git a/package.json b/package.json index f1302f9a1dfb..1e5e8808b0d5 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "scripts": { "setup": "yarn install && cargo install lychee", "lint": "yarn lint:fix && yarn lint:check", - "lint:fix": "markdownlint-cli2-fix \"./specs/**/*.md\" \"#node_modules\"", - "lint:check": "markdownlint-cli2 \"./specs/**/*.md\" \"#node_modules\"", - "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"" + "lint:fix": "markdownlint-cli2-fix \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", + "lint:check": "markdownlint-cli2 \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", + "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./opnode/README.md\" \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"" } } From 1efef020d39892b69926f63aab2b9f0c7973fc15 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 19:40:22 +0100 Subject: [PATCH 171/585] ref impl: pass context to Drive instead of into engine-driver struct. And remove unnecessary type conversion --- opnode/node/node.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index 9e338d576dd7..db169dc0ef00 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -122,7 +122,6 @@ func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { Log: c.log.New("engine_client", i), } engine := &l2.EngineDriver{ - Ctx: c.ctx, Log: c.log.New("engine", i), RPC: client, SyncRef: l2.SyncSource{ @@ -171,16 +170,18 @@ func (c *OpNodeCmd) RunNode() { // Update genesis info, to anchor sync at eng.Genesis = c.Genesis.GetGenesis() // Request initial head update, default to genesis otherwise - if err := eng.RequestHeadUpdate(); err != nil { + reqCtx, reqCancel := context.WithTimeout(c.ctx, time.Second*10) + if err := eng.RequestHeadUpdate(reqCtx); err != nil { eng.Log.Error("failed to fetch engine head, defaulting to genesis", "err", err) eng.UpdateHead(eng.Genesis.L1, eng.Genesis.L2) } + reqCancel() // driver subscribes to L1 head changes l1SubCh := make(chan eth.HeadSignal, 10) l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine - engDriveSub := eng.Drive(c.l1Downloader, l1SubCh) + engDriveSub := eng.Drive(c.ctx, c.l1Downloader, l1SubCh) mergeSub(engDriveSub, "engine driver unexpectedly failed") } @@ -189,9 +190,9 @@ func (c *OpNodeCmd) RunNode() { if err != nil { c.log.Warn("resubscribing after failed L1 subscription", "err", err) } - return eth.WatchHeadChanges(c.ctx, c.l1Source, eth.HeadSignalFn(func(sig eth.HeadSignal) { + return eth.WatchHeadChanges(c.ctx, c.l1Source, func(sig eth.HeadSignal) { l1HeadsFeed.Send(sig) - })) + }) }) mergeSub(l1HeadsSub, "l1 heads subscription failed") From 8ab6af818ba1e5ef2d23d1db10e8f678a8d980fe Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jan 2022 19:42:43 +0100 Subject: [PATCH 172/585] ref impl: rename mergeSub to handleUnsubscribe --- opnode/node/node.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index db169dc0ef00..fbffd9fb4dba 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -146,7 +146,7 @@ func (c *OpNodeCmd) RunNode() { c.log.Info("Starting OpNode") var unsub []func() - mergeSub := func(sub ethereum.Subscription, errMsg string) { + handleUnsubscribe := func(sub ethereum.Subscription, errMsg string) { unsub = append(unsub, sub.Unsubscribe) go func() { err, ok := <-sub.Err() @@ -182,7 +182,7 @@ func (c *OpNodeCmd) RunNode() { l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine engDriveSub := eng.Drive(c.ctx, c.l1Downloader, l1SubCh) - mergeSub(engDriveSub, "engine driver unexpectedly failed") + handleUnsubscribe(engDriveSub, "engine driver unexpectedly failed") } // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync @@ -194,7 +194,7 @@ func (c *OpNodeCmd) RunNode() { l1HeadsFeed.Send(sig) }) }) - mergeSub(l1HeadsSub, "l1 heads subscription failed") + handleUnsubscribe(l1HeadsSub, "l1 heads subscription failed") // subscribe to L1 heads for info l1Heads := make(chan eth.HeadSignal, 10) From 59acf60f4d4fa081a3df4d0befa2b5368441006d Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 21 Jan 2022 17:03:57 +0100 Subject: [PATCH 173/585] ref impl: adapt node to driver actions/state separation refactor --- opnode/node/node.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index fbffd9fb4dba..43d108b5f664 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -104,6 +104,7 @@ func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { l1CanonicalChain := eth.CanonicalChain(c.l1Source) c.l1Downloader = l1.NewDownloader(c.l1Source) + genesis := c.Genesis.GetGenesis() for i, addr := range c.L2EngineAddrs { // L2 exec engine: updated by this OpNode (L2 consensus layer node) @@ -124,10 +125,12 @@ func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { engine := &l2.EngineDriver{ Log: c.log.New("engine", i), RPC: client, + DL: c.l1Downloader, SyncRef: l2.SyncSource{ L1: l1CanonicalChain, L2: client, }, + EngineDriverState: l2.EngineDriverState{Genesis: genesis}, } c.l2Engines = append(c.l2Engines, engine) } @@ -167,12 +170,10 @@ func (c *OpNodeCmd) RunNode() { c.log.Info("Attaching execution engine(s)") for _, eng := range c.l2Engines { - // Update genesis info, to anchor sync at - eng.Genesis = c.Genesis.GetGenesis() // Request initial head update, default to genesis otherwise reqCtx, reqCancel := context.WithTimeout(c.ctx, time.Second*10) - if err := eng.RequestHeadUpdate(reqCtx); err != nil { - eng.Log.Error("failed to fetch engine head, defaulting to genesis", "err", err) + if !eng.RequestUpdate(reqCtx, eng.Log, eng) { + eng.Log.Error("failed to fetch engine head, defaulting to genesis") eng.UpdateHead(eng.Genesis.L1, eng.Genesis.L2) } reqCancel() @@ -181,7 +182,7 @@ func (c *OpNodeCmd) RunNode() { l1SubCh := make(chan eth.HeadSignal, 10) l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine - engDriveSub := eng.Drive(c.ctx, c.l1Downloader, l1SubCh) + engDriveSub := eng.Drive(c.ctx, l1SubCh) handleUnsubscribe(engDriveSub, "engine driver unexpectedly failed") } From 55bf74ba0b9a48d536b98bdfff8c4d23d8a10b1d Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 21 Jan 2022 19:15:05 +0100 Subject: [PATCH 174/585] deposit feed test: rm old comment --- packages/contracts/test/L1/DepositFeed.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index ed325b840c8c..11a95f2618c2 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -213,7 +213,6 @@ describe('DepositFeed', () => { // Deploy a dummy contract so we can impersonate it const dummy = await (await ethers.getContractFactory('Dummy')).deploy() await dummy.deployed() - // this is not emitting an event! await expect( dummy.forward( depositFeed.address, From 0fe5e2e7058fdb88718ceda14e87f44e6270f1c4 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 21 Jan 2022 13:47:22 -0500 Subject: [PATCH 175/585] Forward full balance from Dummy contract --- packages/contracts/contracts/test/DummyContract.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/contracts/contracts/test/DummyContract.sol b/packages/contracts/contracts/test/DummyContract.sol index 8d8aadfefb22..6ce8e40fc24d 100644 --- a/packages/contracts/contracts/test/DummyContract.sol +++ b/packages/contracts/contracts/test/DummyContract.sol @@ -13,7 +13,8 @@ contract Dummy { * @param _data Data to forward */ function forward(address _target, bytes calldata _data) external payable { - (bool success, ) = _target.call{ value: msg.value }(_data); + uint256 amount = address(this).balance; + (bool success, ) = _target.call{ value: amount }(_data); // Silence the 'Return value of low-level calls not used' warning. if (!success) { revert Failed(); From 819b3688f0cc0adca94f4c14148b441c44950739 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 21 Jan 2022 13:47:45 -0500 Subject: [PATCH 176/585] Lint test script --- packages/contracts/test/L1/DepositFeed.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts index 11a95f2618c2..f355d66dbc93 100644 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ b/packages/contracts/test/L1/DepositFeed.spec.ts @@ -64,7 +64,7 @@ describe('DepositFeed', () => { describe('Should emit the correct log values...', async () => { it('when an EOA deposits a transaction with 0 value.', async () => { - const receipt = await( + const receipt = await ( await depositFeed.depositTransaction( NON_ZERO_ADDRESS, ZERO_BIGNUMBER, From fe6e6e7c6c294249155bd83f313b99d0219f00b4 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 20 Jan 2022 19:44:30 +0100 Subject: [PATCH 177/585] add new terms to glossary, fixing internal links but not yet external links --- specs/glossary.md | 215 +++++++++++++++++++++++++++++----------------- 1 file changed, 134 insertions(+), 81 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index 98ea789e3aca..17bbc1887026 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -13,7 +13,17 @@ - [Receipt](#receipt) - [Transaction Type](#transaction-type) - [Fork Choice Rule](#fork-choice-rule) -- [L2 Chain Concepts](#l2-chain-concepts) +- [Deposits](#deposits) + - [Deposited Transaction](#deposited-transaction) + - [Deposit Block](#deposit-block) + - [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) + - [User-Deposited Transaction](#user-deposited-transaction) + - [Depositing Call](#depositing-call) + - [Depositing Transaction](#depositing-transaction) + - [Depositor](#depositor) + - [Deposited Transaction Type](#deposited-transaction-type) + - [Deposit Contract](#deposit-contract) +- [Other L2 Chain Concepts](#other-l2-chain-concepts) - [Address Aliasing](#address-aliasing) - [L2 Chain Inception](#l2-chain-inception) - [Rollup Node](#rollup-node) @@ -21,15 +31,12 @@ - [L2 Chain Derivation](#l2-chain-derivation) - [L2 Derivation Inputs](#l2-derivation-inputs) - [Payload Attributes](#payload-attributes) - - [Deposits](#deposits) - - [L1 Attributes Deposit](#l1-attributes-deposit) - - [Transaction Deposit](#transaction-deposit) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - - [Deposit Transaction Type](#deposit-transaction-type) - - [Deposit Feed Contract](#deposit-feed-contract) - [Execution Engine Concepts](#execution-engine-concepts) - [Execution Engine](#execution-engine) +------------------------------------------------------------------------------------------------------------------------ + # General Terms ## Layer 1 (L1) @@ -129,7 +136,124 @@ on-chain-confirmed head, or the on-chain-finalized head. ------------------------------------------------------------------------------------------------------------------------ -# L2 Chain Concepts +# Deposits + +[deposits]: glossary.md#deposits + +In general, a deposit is an L2 transaction derived from an L1 block (by the [rollup driver]). + +While transaction deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word +*deposit* should be understood as "a transaction *deposited* to L2 from L1". + +This term *deposit* is somewhat ambiguous as these "transactions" exist at multiple levels. This section disambiguates all +deposit-related terms. + +Notably, a *deposit* can refer to: + +- A [deposited transaction][deposited] (on L2) that is part of a [deposite block][deposit-block]. +- A [depositing call][depositing-call] that causes a [deposited transaction][deposited] to be derived. +- The event/log data generated by the [depositing call][depositing-call], which is what the [rollup driver] reads to + derive the [deposited transaction][deposited]. + +We sometimes also talk about *user deposit* which is a similar term that explicitly excludes [L1 attributes deposited +transactions][l1-attr-deposit]. + +Deposits are specified in the [deposits specification][deposits-spec]. + +[deposits-spec]: deposits.md + +## Deposited Transaction + +[deposited]: glossary.md#deposited-transaction + +A *deposited transaction* is a L2 transaction that was derived from L1 and is included in a [deposit +block][deposit-block]. + +There are two kinds of deposited transactions: + +- [L1 attributes deposited transaction][l1-attr-deposit], which submits the L1 block's attributes to the [L1 Attributes + Predeployed Contract][l1-attr-predeploy]. +- [User-deposited transactions][user-deposited], which are transactions derived from an L1 call to the [deposit + contract][deposit-contract]. + +[deposits-spec]: deposits.md + +## Deposit Block + +[deposit-block]: glossary.md#deposit-block + +A *deposit block* is a L2 block that contains only [deposited transactions][deposited]. + +## L1 Attributes Deposited Transaction + +[l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction + +An *L1 attributes deposited transaction* is [deposited transaction][deposited] that is used to register the L1 block +attributes (number, timestamp, ...) on L2 via a call to the [L1 Attributes Predeployed Contract][l1-attr-predeploy]. +That contract can then be used to read the the attributes of the L1 block corresponding to the current L2 block. + +L1 attributes deposited transactions are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the +deposits specification. + +[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposit + +## User-Deposited Transaction + +[user-deposited]: glossary.md#user-deposited-transaction + +A *user-deposited transaction* is a [deposited transaction][deposited] which is derived from an L1 call to the [deposit + contract][deposit-contract] (a [depositing call][depositing-call]). + +User-deposited transactions are specified in the [Transaction Deposits][tx-deposits-spec] section of the deposits +specification. + +[tx-deposits-spec]: deposits.md##l1-transaction-deposits + +## Depositing Call + +[depositing-call]: glossary.md#depositing-call + +A *depositing call* is an L1 call to the [deposit contract][deposit-contract], which will be derived to a +[user-deposited transaction][user-deposited] by the [rollup driver]. + +This call specifies all the data (destination, value, calldata, ...) for the deposited transaction. "submits* + +## Depositing Transaction + +[depositing-tx]: glossary.md#depositing-transaction + +A *depositing transaction* is an L1 transaction that makes one or more [depositing calls][depositing-call]. + +## Depositor + +[depositor]: glossary.md#depositor + +The *depositor* is the L1 account (contract or [EOA]) that makes (is the `msg.sender` of) the [depositing +call][depositing-call]. The *depositor* is **NOT** the originator of the depositing transaction (i.e. `tx.origin`). + +## Deposited Transaction Type + +[deposit-tx-type]: glossary.md#deposited-transaction-type + +The *deposited transaction type* is an [EIP-2718] [transaction type][transaction-type], which specifies the input fields +and correct handling of a [deposited transaction][deposited]. + +## Deposit Contract + +[deposit-contract]: glossary.md#deposit-contract + +The *deposit contract* is qn [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are +emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. + +Advanced note: the deposits are not stored in calldata because they can be sent by contracts, in which case the calldata +is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 +block. + +cf. [Deposits Specification](deposits.md) + +------------------------------------------------------------------------------------------------------------------------ + +# Other L2 Chain Concepts ## Address Aliasing @@ -177,13 +301,13 @@ Specification)](rollup-node.md#l2-chain-derivation) This term refers to data that is found in L1 blocks and is read by the [rollup node] to construct [payload attributes]. -Chain derivation attributes include: +L2 derivation inputs include: - L1 block attributes - block number - timestamp - basefee -- [deposits] +- [deposits] (as log data) ## Payload Attributes @@ -200,57 +324,6 @@ cf. [Execution Engine Specification](exec-engine.md) Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using this term. -## Deposits - -[deposits]: glossary.md#deposits - -A deposit is an L2 transaction derived from an L1 block. - -There are two kinds of deposits: - -- [L1 Attributes Deposit][l1-attributes-deposit], which submits the L1 block's attributes to the [L1 Attributes - Predeployed Contract][l1-attr-predeploy]. -- [Transaction Deposits][tx-deposits], which are transaction that have been submitted on L1, via a transaction sent to -the [deposit feed contract][deposit-feed]. - -While transaction deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word -*deposit* should be understood as "a transaction *deposited* to L2 from L1". - -The term *deposit* performs the double duty of referring to both: - -1. The transaction information submitted on L1 to the [deposit feed contract][deposit-feed]. This is a kind of [L2 - derivation input][deriv-inputs]. -2. The actual L2 transaction derived from this L1 input. - -Deposits are specified in the [deposits specification][deposits-spec]. - -[deposits-spec]: deposits.md - -## L1 Attributes Deposit - -[l1-attributes-deposit]: glossary.md#l1-attributes-deposit - -A [deposit][deposits] that is used to register the L1 block attributes (number, timestamp, ...) on L2 via a call to the -[L1 Attributes Predeployed Contract][l1-attr-predeploy]. That contract can then be used to read the the attributes of -the L1 block corresponding to the current L2 block. - -L1 attributes deposits are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the deposits -specification. - -[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposit - -## Transaction Deposits - -[tx-deposits]: #transaction-deposits - -These [deposits] are transaction that have been submitted on L1, via a transaction sent to the [deposit feed -contract][deposit-feed]. - -Transaction deposits are specified in the [Transaction Deposits][tx-deposits-spec] section of the deposits -specification. - -[tx-deposits-spec]: deposits.md#l1-transaction-deposits - ## L1 Attributes Predeployed Contract [l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract @@ -258,27 +331,7 @@ specification. A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given block number or a given block hash. -cf. [L1 Attributes Predeployed Contract Specification](#l1-attributes--reference-implementation) - -## Deposit Transaction Type - -[deposit-tx-type]: glossary.md#deposit-transaction-type - -The deposit transaction type is an [EIP-2718] [transaction type][transaction-type], which specifies -the input fields and correct handling of a [deposit][deposits]. - -## Deposit Feed Contract - -[deposit-feed]: glossary.md#deposit-feed-contract - -An [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are emitted as log records (in -Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. - -Advanced note: the deposits are not stored in calldata because they can be send by contracts, in which case the calldata -is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 -block. - -cf. [Deposits Specification](deposits.md) +cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes--reference-implementation) ------------------------------------------------------------------------------------------------------------------------ From 449d02ee1aa8c0da879f0d374b0e4f2f126037f7 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 20 Jan 2022 19:57:26 +0100 Subject: [PATCH 178/585] add table of contents to deposit spec --- specs/deposits.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index 175ba5bd8af2..d1117e114f9e 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -12,6 +12,24 @@ new [transaction type][transaction-type] for deposits. It also describes how deposits are initiated on L1, along with the authorization and validation conditions on L2. +## Table of Contents + +- [The Deposit Transaction Type](#the-deposit-transaction-type) + - [Uses of the Deposit Transaction Type](#uses-of-the-deposit-transaction-type) + - [Validation and Authorization of Deposit Transaction + Types](#validation-and-authorization-of-deposit-transaction-types) + - [Execution](#execution) + - [Nonce Handling](#nonce-handling) +- [L1 Attributes Deposits](#l1-attributes-deposit) +- [Special Accounts on L2](#special-accounts-on-l2) + - [L1 Attributes Depositor Account](l1-attributes-depositor-account) + - [L1 Attributes Predeploy](#l1-attributes-predeploy) + - [L1 Attributes: Reference Implementation](#l1-attributes--reference-implementation) +- [L1 Transaction Deposits](#l1-transaction-deposits) + - [Deposit Feed Contract](#deposit-feed-contract) + - [Address Aliasing](#address-aliasing) + - [Deposit Feed: Reference Implementation](#deposit-feed--reference-implementation) + ## The Deposit Transaction Type [deposit-transaction-type]: #the-deposit-transaction-type @@ -201,7 +219,7 @@ The deposit feed handles two special cases: > **TODO** Define if/how ETH withdrawals occur. -#### Address aliasing +#### Address Aliasing [address-aliasing]: #address-aliasing From ed90cf1a85c6b421099aa49f0bbb5b17bdfd448f Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 01:54:56 +0100 Subject: [PATCH 179/585] update deposits.md to use standardized terms --- specs/deposits.md | 143 +++++++++++++++++++++++----------------------- specs/glossary.md | 6 +- 2 files changed, 75 insertions(+), 74 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index d1117e114f9e..f675fcdcbf7c 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -4,40 +4,48 @@ [transaction-type]: glossary.md#transaction-type [derivation]: glossary.md#L2-chain-derivation [execution-engine]: glossary.md#execution-engine +[deposited]: glossary.md#deposited [deposits]: glossary.md#deposits -[L1 attributes deposit]: glossary.md#l1-attributes-deposit -[transaction deposits]: glossary.md#transaction-deposits +[g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction +[g-user-deposited]: glossary.md#user-deposited-transaction +[g-deposit-block]: glossary.md#deposit-block +[g-eoa]: glossary.md#eoa -[Deposits] are transactions which are initiated on L1, and executed on L2. This document outlines a -new [transaction type][transaction-type] for deposits. It also describes how deposits are initiated -on L1, along with the authorization and validation conditions on L2. +[Deposited transactions], also known as [deposits] are transactions which are initiated on L1, and +executed on L2. This document outlines a new [transaction type][transaction-type] for deposits. It +also describes how deposits are initiated on L1, along with the authorization and validation +conditions on L2. + +**Vocabulary note**: *deposited transaction* refers specifically to an L2 transaction, while +*deposit* can refer to the transaction at various stages (for instance when it is deposited on L1). ## Table of Contents -- [The Deposit Transaction Type](#the-deposit-transaction-type) - - [Uses of the Deposit Transaction Type](#uses-of-the-deposit-transaction-type) - - [Validation and Authorization of Deposit Transaction - Types](#validation-and-authorization-of-deposit-transaction-types) +- [The Deposited Transaction Type](#the-deposited-transaction-type) + - [Kinds of Deposited Transactions](#kinds-of-deposited-transactions) + - [Validation and Authorization of Deposited + Transaction](#validation-and-authorization-of-deposit-transaction-types) - [Execution](#execution) - [Nonce Handling](#nonce-handling) -- [L1 Attributes Deposits](#l1-attributes-deposit) +- [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) - [Special Accounts on L2](#special-accounts-on-l2) - - [L1 Attributes Depositor Account](l1-attributes-depositor-account) - - [L1 Attributes Predeploy](#l1-attributes-predeploy) - - [L1 Attributes: Reference Implementation](#l1-attributes--reference-implementation) -- [L1 Transaction Deposits](#l1-transaction-deposits) + - [L1 Attributes Depositor Account](#l1-attributes-depositor-account) + - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) + - [L1 Attributes Predeployed Contract: Reference Implementation](#l1-attributes-predeployed-contract--reference-implementation) +- [User-Deposited Transactions](#user-deposited-transactions) - [Deposit Feed Contract](#deposit-feed-contract) - [Address Aliasing](#address-aliasing) - - [Deposit Feed: Reference Implementation](#deposit-feed--reference-implementation) + - [Deposit Feed Contract: Reference Implementation](#deposit-feed-contract--reference-implementation) -## The Deposit Transaction Type +## The Deposited Transaction Type -[deposit-transaction-type]: #the-deposit-transaction-type +[deposited-tx-type]: #the-deposited-transaction-type -Deposit transactions have the following notable distinctions from existing transaction types: +[Deposited transactions][deposited] have the following notable distinctions from existing +transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. -2. They do not include signature validation (see [L1 transaction deposits][l1-transaction-deposits] +2. They do not include signature validation (see [User-Deposited Transactions][user-deposited] for the rationale). We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following @@ -62,41 +70,36 @@ Picking a high identifier minimizes the risk that the identifier will be used be transaction type on the L1 chain in the future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. -### Uses of the Deposit Transaction Type - -Although in practice we define only one new transaction type we can distinguish between two distinct -situations which occur in the deposit block, based on their positioning. +### Kinds of Deposited Transactions -1. The first transaction MUST be a [L1 attributes deposit][l1-attributes-deposit], followed by -2. an array of zero-or-more [L1 transaction deposits][l1-transaction-deposits] submitted to the -deposit feed contract on L1. +Although we define only one new transaction type, we can distinguish between two kinds of deposited +transactions, based on their positioning in the [deposit block][g-deposit-block]: -The rationale for creating only one new transaction type is to minimize both -modifications to L1 client software and complexity in general. +1. The first transaction MUST be a [L1 attributes deposited transaction][l1-attr-deposit], followed + by +2. an array of zero-or-more [user-deposited transactions][user-deposited] submitted to the deposit + feed contract on L1. -> **TODO** Specify and link to deposit blocks +We only define a single new transaction type in order to minimize modifications to L1 client +software, and complexity in general. -### Validation and Authorization of Deposit Transaction Types +### Validation and Authorization of Deposited Transactions -[authorization]: #validation-and-authorization-of-deposit-transaction-types +[authorization]: #validation-and-authorization-of-deposited-transaction -As noted above, the deposit transaction type does not include a signature for validation. Rather, -authorization is handled by the [L2 chain Derivation][derivation] process, which when correctly -processed will only derive transactions with a `from` address attested to by the logs of the [L1 +As noted above, the deposited transaction type does not include a signature for validation. Rather, +authorization is handled by the [L2 chain derivation][derivation] process, which when correctly +applied will only derive transactions with a `from` address attested to by the logs of the [L1 deposit feed contract][deposit-feed-contract]. -In the event a deposit transaction is included which is not derived by the [execution -engine][execution-engine] using the correct derivation algorithm, the resulting state transition -would be invalid. - ### Execution -In order to execute a deposit transaction: +In order to execute a deposited transaction: First, the balance of the `from` account MUST be increased by the amount of `mint`. -Then, the execution environment for a deposit transaction is initialized based on the transaction's -values, in exactly the same manner as it would be for an EIP-155 transaction. +Then, the execution environment for a deposited transaction is initialized based on the +transaction's attributes, in exactly the same manner as it would be for an EIP-155 transaction. Specifically, a new EVM call frame targeting the `to` address is created with values initialized as follows: @@ -108,7 +111,7 @@ follows: - `context.gas` set to `gasLimit` - `context.value` set to `sendValue` -#### Nonce handling +#### Nonce Handling Despite the lack of signature validation, we still increment the nonce of the `from` account when a deposit transaction is executed. In the context of a deposit-only roll up, this is not necessary @@ -118,46 +121,46 @@ tooling (such as wallets and block explorers). [create-nonce]: https://github.com/ethereum/execution-specs/blob/617903a8f8d7b50cf71bf1aa733c37897c8d75c1/src/ethereum/frontier/utils/address.py#L40 -## L1 Attributes Deposit +## L1 Attributes Deposited Transaction -[l1-attributes-deposit]: #l1-attributes-deposit +[l1-attr-deposit]: #l1-attributes-deposited-transaction -An [L1 attributes deposit] is a deposit transaction sent to the [L1 attributes predeploy][predeploy] -contract. +An [L1 attributes deposited transaction][g-l1-attr-deposit] is a deposit transaction sent to the [L1 +attributes predeployed contract][predeploy]. This transaction MUST have the following values: 1. `from` is `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001` (the address of the [L1 Attributes depositor account][depositor-account]) -2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 attributes predeploy - contract). +2. `to` is `0x4200000000000000000000000000000000000014` (the address of the [L1 attributes predeployed + contract][predeploy]). 3. `mint` is `0` 4. `value` is `0` 5. `gasLimit` is set to the maximum available. -6. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's +6. `data` is an [ABI] encoded call to the [L1 attributes predeployed contract][predeploy]'s `setL1BlockValues()` function with correct values associated with the corresponding L1 block (cf. - [reference implementation][l1-attrib-ref-implem]). + [reference implementation][l1-attr-ref-implem]). - +No gas is paid for L1 attributes deposited transactions. ## Special Accounts on L2 The L1 attributes deposit transaction involves two special purpose accounts: 1. The L1 attributes depositor account -2. The L1 attributes predeploy +2. The L1 attributes predeployed contract ### L1 Attributes Depositor Account [depositor-account]: #l1-attributes-depositor-account -The depositor account is an EOA with no known private key. It has the address +The depositor account is an [EOA][g-eoa] with no known private key. It has the address `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value is returned by the `CALLER` and `ORIGIN` opcodes during execution of the L1 attributes deposit transaction. -### L1 Attributes Predeploy +### L1 Attributes Predeployed Contract -[predeploy]: #l1-attributes-predeploy +[predeploy]: #l1-attributes-predeployed-contract A predeployed contract on L2 at address `0x4200000000000000000000000000000000000014`, which holds certain block variables from the corresponding L1 block in storage, so that they may be accessed @@ -171,9 +174,9 @@ The contract has the following solidity interface, and can be interacted with ac [ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html -#### L1 Attributes: Reference Implementation +#### L1 Attributes Predeployed Contract: Reference Implementation -[l1-attrib-ref-implem]: #l1-attributes--reference-implementation +[l1-attr-ref-implem]: #l1-attributes-predeployed-contract--reference-implementation A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. @@ -183,14 +186,14 @@ After running `yarn build` in the `packages/contracts` directory, the bytecode t file will be located in the `deployedBytecode` field of the build artifacts file at `/packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json`. -## L1 Transaction Deposits +## User-Deposited Transactions -[l1-transaction-deposits]: #l1-transaction-deposits +[user-deposited]: #user-deposited-transactions -L1 [transaction deposits] are [deposit transactions][deposit-transaction-type] generated by the [L2 -Chain Derivation][derivation] process. The values of each transaction are determined by the -corresponding `TransactionDeposited` event emitted by the [deposit feed -contract][deposit-feed-contract] on L1. +[User-deposited transactions][g-user-deposited] are [deposited transactions][deposited-tx-type] +generated by the [L2 Chain Derivation][derivation] process. The content of each user-deposited +transaction are determined by the corresponding `TransactionDeposited` event emitted by the [deposit +feed contract][deposit-feed-contract] on L1. 1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in the deposit feed contract). @@ -203,22 +206,20 @@ contract][deposit-feed-contract] on L1. 6. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as either calldata or initialization code depending on the value of `to`. -### Deposit Feed Contract +### Deposit Contract -[deposit-feed-contract]: #deposit-feed-contract +[deposit-contract]: #deposit-contract -The deposit feed contract is deployed to L1. Deposited transactions are derived from the values in -the `TransactionDeposited` event(s) emitted by the deposit feed contract. +The deposit contract is deployed to L1. Deposited transactions are derived from the values in +the `TransactionDeposited` event(s) emitted by the deposit contract. -The deposit feed handles two special cases: +The deposit contract handles two special cases: 1. A contract creation deposit, which is indicated by setting the `isCreation` flag to `true`. In the event that the `to` address is non-zero, the contract will revert. 2. A call from a contract account, in which case the `from` value is transformed to its L2 [alias][address-aliasing]. -> **TODO** Define if/how ETH withdrawals occur. - #### Address Aliasing [address-aliasing]: #address-aliasing @@ -229,7 +230,7 @@ has the same address as a contract on L2 but doesn't have the same code. We can for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes it possible for users to interact with contracts on L2 even when the Sequencer is down. -#### Deposit Feed: Reference Implementation +#### Deposit Feed Contract: Reference Implementation A reference implementation of the Deposit Feed contract can be found in [DepositFeed.sol]. diff --git a/specs/glossary.md b/specs/glossary.md index 17bbc1887026..171473f601f3 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -145,8 +145,8 @@ In general, a deposit is an L2 transaction derived from an L1 block (by the [rol While transaction deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be understood as "a transaction *deposited* to L2 from L1". -This term *deposit* is somewhat ambiguous as these "transactions" exist at multiple levels. This section disambiguates all -deposit-related terms. +This term *deposit* is somewhat ambiguous as these "transactions" exist at multiple levels. This section disambiguates +all deposit-related terms. Notably, a *deposit* can refer to: @@ -331,7 +331,7 @@ this term. A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given block number or a given block hash. -cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes--reference-implementation) +cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes-predeployed-contract) ------------------------------------------------------------------------------------------------------------------------ From 5c2c043570427f5417d5002946825e7c9e8f6290 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 01:57:23 +0100 Subject: [PATCH 180/585] add g-prefix to glossary links in deposits.md --- specs/deposits.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index f675fcdcbf7c..6c375535bb09 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -1,20 +1,19 @@ # Deposits -[transaction-type]: glossary.md#transaction-type -[derivation]: glossary.md#L2-chain-derivation -[execution-engine]: glossary.md#execution-engine -[deposited]: glossary.md#deposited -[deposits]: glossary.md#deposits +[g-transaction-type]: glossary.md#transaction-type +[g-derivation]: glossary.md#L2-chain-derivation +[g-deposited]: glossary.md#deposited +[g-deposits]: glossary.md#deposits [g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction [g-user-deposited]: glossary.md#user-deposited-transaction [g-deposit-block]: glossary.md#deposit-block [g-eoa]: glossary.md#eoa -[Deposited transactions], also known as [deposits] are transactions which are initiated on L1, and -executed on L2. This document outlines a new [transaction type][transaction-type] for deposits. It -also describes how deposits are initiated on L1, along with the authorization and validation -conditions on L2. +[Deposited transactions][g-deposited], also known as [deposits][g-deposits] are transactions which +are initiated on L1, and executed on L2. This document outlines a new [transaction +type][g-transaction-type] for deposits. It also describes how deposits are initiated on L1, along +with the authorization and validation conditions on L2. **Vocabulary note**: *deposited transaction* refers specifically to an L2 transaction, while *deposit* can refer to the transaction at various stages (for instance when it is deposited on L1). @@ -41,7 +40,7 @@ conditions on L2. [deposited-tx-type]: #the-deposited-transaction-type -[Deposited transactions][deposited] have the following notable distinctions from existing +[Deposited transactions][g-deposited] have the following notable distinctions from existing transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. @@ -88,7 +87,7 @@ software, and complexity in general. [authorization]: #validation-and-authorization-of-deposited-transaction As noted above, the deposited transaction type does not include a signature for validation. Rather, -authorization is handled by the [L2 chain derivation][derivation] process, which when correctly +authorization is handled by the [L2 chain derivation][g-derivation] process, which when correctly applied will only derive transactions with a `from` address attested to by the logs of the [L1 deposit feed contract][deposit-feed-contract]. @@ -191,7 +190,7 @@ file will be located in the `deployedBytecode` field of the build artifacts file [user-deposited]: #user-deposited-transactions [User-deposited transactions][g-user-deposited] are [deposited transactions][deposited-tx-type] -generated by the [L2 Chain Derivation][derivation] process. The content of each user-deposited +generated by the [L2 Chain Derivation][g-derivation] process. The content of each user-deposited transaction are determined by the corresponding `TransactionDeposited` event emitted by the [deposit feed contract][deposit-feed-contract] on L1. From 2e21031b0bdcd173f63262d8323256500aca9f9d Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 14:39:12 +0100 Subject: [PATCH 181/585] rewrite rollup node spec to standardize terminology, add pseudocode and clarify content --- specs/exec-engine.md | 32 +++-- specs/glossary.md | 6 +- specs/rollup-node.md | 279 +++++++++++++++++++++++++++---------------- 3 files changed, 203 insertions(+), 114 deletions(-) diff --git a/specs/exec-engine.md b/specs/exec-engine.md index 23e6f48d8a38..e3fd40f68555 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -50,17 +50,31 @@ to [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1]: the extended `Pay #### Extended PayloadAttributesV1 -[`PayloadAttributesV1`][PayloadAttributesV1] is extended with a `transactions` field, -equivalent to the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: -> `Array of DATA` - Array of transaction objects, each object is a byte list ([`DATA`][exec-api-data]) representing -> `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718][eip-2718]. +[`PayloadAttributesV1`][PayloadAttributesV1] is extended with a `transactions` field, equivalent to +the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: -This `transactions` field is an optional JSON field: +```js +PayloadAttributesOPV1: { + timestamp: QUANTITY + random: DATA (32 bytes) + suggestedFeeRecipient: DATA (20 bytes) + transactions: array of DATA +} +``` -- If empty or missing: no changes to engine behavior. - Utilized by sequencers (if enabled) to consume the transaction pool. +The type notation used here refers to the [HEX value encoding] used by the [Ethereum JSON-RPC API +specification][JSON-RPC-API], as this structure will need to be sent over JSON-RPC. `array` refers +to a JSON array. + +Each item of the `transactions` array is a byte list encoding a transaction: `TransactionType || +TransactionPayload` or `LegacyTransaction`, as defined in [EIP-2718][eip-2718]. + +The `transactions` field is optional: + +- If empty or missing: no changes to engine behavior. The sequencers will (if enabled) build a block + by consuming transactions from the transaction pool. - If present and non-empty: the payload MUST only be produced with this exact list of transactions. - Utilized by [rollup driver][rollup-driver] to compute full block payloads based on deterministic inputs. + The [rollup driver][rollup-driver] determines the transaction list based on deterministic L1 inputs. > **TODO**: derivation function spec in rollup node doc or separate driver doc @@ -150,3 +164,5 @@ the operation within the engine is the exact same as with L1 (although with an E [engine_forkchoiceUpdatedV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_forkchoiceupdatedv1 [engine_executePayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_executePayloadV1 [engine_getPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_getPayloadV1 +[HEX value encoding]: https://eth.wiki/json-rpc/API#hex-value-encoding +[JSON-RPC-API]: https://github.com/ethereum/execution-apis diff --git a/specs/glossary.md b/specs/glossary.md index 171473f601f3..d90c5a0aef70 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -24,7 +24,7 @@ - [Deposited Transaction Type](#deposited-transaction-type) - [Deposit Contract](#deposit-contract) - [Other L2 Chain Concepts](#other-l2-chain-concepts) - - [Address Aliasing](#address-aliasing) + - [Address Aliasing](#address-aliasing) - [L2 Chain Inception](#l2-chain-inception) - [Rollup Node](#rollup-node) - [Rollup Driver](#rollup-driver) @@ -195,7 +195,7 @@ That contract can then be used to read the the attributes of the L1 block corres L1 attributes deposited transactions are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the deposits specification. -[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposit +[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposited-transaction ## User-Deposited Transaction @@ -207,7 +207,7 @@ A *user-deposited transaction* is a [deposited transaction][deposited] which is User-deposited transactions are specified in the [Transaction Deposits][tx-deposits-spec] section of the deposits specification. -[tx-deposits-spec]: deposits.md##l1-transaction-deposits +[tx-deposits-spec]: deposits.md#user-deposited-transactions ## Depositing Call diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 6b00dbd09d0f..48293ae44b97 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -7,21 +7,27 @@ [block]: glossary.md#block [execution engine]: glossary.md#execution-engine [reorg]: glossary.md#re-organization -[block gossip]: glossary.md#block-gossip [rollup driver]: glossary.md#rollup-driver -[deposits]: glossary.md#deposits -[deposit feed contract]: glossary.md#L2-deposit-feed-contract [L2 chain inception]: glossary.md#L2-chain-inception [receipts]: glossary.md#receipt -[L1 attributes transaction]: glossary.md#l1-attributes-transaction -[transaction deposits]: glossary.md#transaction-deposits +[L1 attributes deposit]: glossary.md#l1-attributes-deposit +[g-deposit-contract]: glossary.md#deposit-contract +[g-deposits]: glossary.md#deposits +[g-deposit-block]: glossary.md#deposit-block +[g-deposited]: glossary.md#deposited-transaction +[g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction +[g-user-deposited]: glossary.md#user-deposited-transaction +[g-l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract +[g-depositing-call]: glossary.md#depositing-call +[g-depositing-transaction]: glossary.md#depositing-transaction The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their associated [receipts]). This process happens in two steps: 1. Read from L1 blocks and associated receipts, in order to generate [payload attributes] (essentially [a block without output properties][block]). -2. Pass the payload attributes to the [execution engine], so that [output block properties][block] may be computed. +2. Pass the payload attributes to the [execution engine], so that the L2 block (including [output block + properties][block]) may be computed. While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The L2 chain is extended whenever new L1 blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the @@ -33,135 +39,188 @@ concerned with the specification of the rollup driver. ## Table of Contents - [L2 Chain Derivation](#l2-chain-derivation) - - [Input derivation](#input-derivation) - - [L1 attributes transaction derivation](#l1-attributes-transaction-derivation) - - [Transaction deposits derivation](#transaction-deposits-derivation) - - [Payload attributes derivation](#payload-attributes-derivation) - - [Output derivation](#output-derivation) -- [Completing a driver step](#completing-a-driver-step) - - [Execute](#execute) - - [Forkchoice](#forkchoice) -- [API error handling](#api-error-handling) + - [From L1 Blocks to Payload Attributes](#from-l1-blocks-to-payload-attributes) + - [Reading L1 Inputs](#reading-l1-inputs) + - [Encoding the L1 Attributes Deposited Transaction](#encoding-the-l1-attributes-deposited-transaction) + - [Encoding User-Deposited Transactions](#encoding-user-deposited-transactions) + - [Building the Payload Attributes](#building-the-payload-attributes) + - [From Payload Attributes to L2 Block](#from-payload-attributes-to-L2-block) + - [Inductive Derivation Step](#inductive-derivation-step) + - [Engine API Error Handling](#engine-api-error-handling) + - [Finalization Guarantees](#finalization-guarantees) + - [Whole L2 Chain Derivation](#whole-l2-chain-derivation) - [Handling L1 Re-Orgs](#handling-l1-re-orgs) -- [Finalization Guarantees](#finalization-guarantees) -## L2 Chain Derivation +# L2 Chain Derivation -This section specifies how the [rollup driver] derives one L2 block per every L1 block. +[l2-chain-derivation]: #l2-chain-derivation -First inputs are derived from L1 source data, then outputs are derived with L2 state through the [Engine API]. +This section specifies how the [rollup driver] derives one L2 [deposit block][g-deposit-block] per every L1 block. The +L2 block carries *[deposited transactions][g-deposited]* of two kinds: -[Engine API]: exec-engine.md#engine-api +- a single *[L1 attributes deposited transaction][g-l1-attr-deposit]* (always first) +- zero or more *[user-deposited transactions][g-user-deposited]* -### Input derivation +------------------------------------------------------------------------------------------------------------------------ -The L2 block has the same format as a L1 block: a block-header and a list of transactions. +## From L1 Blocks to Payload Attributes -The list of transaction carries: +### Reading L1 inputs -- A *[L1 attributes transaction]* (always first item) -- L2 transactions deposited by users in the L1 block (*[deposits]*, if any) +The rollup reads the following data from each L1 block: -While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, -the word *deposit* should be understood as "a transaction *deposited* to L2". +- L1 block attributes + - block number + - timestamp + - basefee + - *random* (the output of the [`RANDOM` opcode][random]) +- L1 log entries emitted for [user deposits][g-deposits], augmented with + - `blockHeight`: the block-height of the L1 block + - `transactionIndex`: the transaction-index within the L2 transactions list -The L1 attributes are read from the L1 block header, while other deposits are read from the block's [receipts]. +[random]: https://eips.ethereum.org/EIPS/eip-4399 -All derived deposits each get two additional attributes during derivation, to ensure uniqueness: +> Design note: The extra log entry metadata will be used to ensure that deposited transactions will be unique. Without +> them, two different deposited transaction could have the same exact hash. +> +> We do not use the sender's nonce to ensure uniqueness because this would require an extra L2 EVM state read from the +> [execution engine]. -- `blockHeight`: the block-height of the L1 input the deposit was derived from -- `transactionIndex`: the transaction-index within the L2 transactions list +The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the +[**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log entries. -#### L1 attributes transaction derivation +[deposit-contract-spec]: deposits.md#deposit-contract -The rollup reads the following attributes from each L1 block to derive a [L1 attributes transaction]: +### Encoding the L1 Attributes Deposited Transaction -- block number -- timestamp -- basefee -- *random* (the output of the [`RANDOM` opcode][random]) +The [L1 attributes deposited transaction][g-l1-attr-deposit] is a call that submits the L1 block attributes (listed +above) to the [L1 attributes predeployed contract][g-l1-attr-predeploy]. -These are then encoded as a [L1 attributes deposit] to update the [L1 Attributes Predeploy]. +To encode the L1 attributes deposited transaction, refer to the following sections of the deposits spec: -[random]: https://eips.ethereum.org/EIPS/eip-4399 -[L1 attributes deposit]: deposits.md#l1-attributes-deposit -[L1 Attributes Predeploy]: deposits.md#l1-attributes-predeploy +- [The Deposited Transaction Type](deposits.md#the-deposited-transaction-type) +- [L1 Attributes Deposited Transaction](deposits.md#l1-attributes-deposited-transaction) + +### Encoding User-Deposited Transactions -#### Transaction deposits derivation +A [user-deposited-transactions][g-deposited] is an L2 transaction derived from a [user deposit][g-deposits] submitted on +L1 to the [deposit contract][g-deposit-contract]. Refer to the [deposit contract specification][deposit-contract-spec] +for more details. -A [transaction deposit][transaction deposits] is an L2 transaction that has been submitted on L1, via a call to the -[deposit feed contract]. +The user-deposited transaction is derived from the log entry emitted by the [depositing call][g-depositing-call], which +is stored in the [depositing transaction][g-depositing-transaction]'s log receipt. -Refer to the [**deposit feed contract specification**][deposit-feed-spec] for details on how -deposit properties are emitted in deposit log entries. +To encode user-deposited transactions, refer to the following sections of the deposits spec: -[deposit-feed-spec]: deposits.md#deposit-feed-contract +- [The Deposited Transaction Type](deposits.md#the-deposited-transaction-type) +- [User-Deposited Transactions](deposits.md#user-deposited-transactions) -#### Payload attributes derivation +### Building the Payload Attributes -From the data read from L1, the rollup node constructs an [expanded version of PayloadAttributesV1], -which includes an additional `transactions` field. +[payload attributes]: #building-the-payload-attributes -The object properties must be set as follows: +From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded version][expanded-paylod] of +[`PayloadAttributesV1`], which includes an additional `transactions` field. -- `timestamp` is set to the current [unix time], - rounded to the closest multiple of 2 seconds. No two blocks may have the same timestamp. +The object's properties must be set as follows: + +- `timestamp` is set to the timestamp of the L1 block. - `random` is set to the *random* L1 block attribute - `suggestedFeeRecipient` is set to the zero-address for deposit-blocks, since there is no sequencer. -- `transactions` is an array of the derived deposits, all encoded in the [EIP-2718] format. +- `transactions` is an array of the derived deposits, encoded as per the two preceding sections. -[expanded version of PayloadAttributesV1]: exec-engine.md#extended-payloadattributesv1 -[unix time]: https://en.wikipedia.org/wiki/Unix_time -[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -[EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 +[expanded-payload]: exec-engine.md#extended-payloadattributesv1 +[`PayloadAttributesV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 -### Output derivation +------------------------------------------------------------------------------------------------------------------------ -Building a full block requires the earlier [derived payload attributes](#payload-attributes-derivation) -(`payloadAttributes` argument) as well as the previous L2 state (`forkchoiceState` argument), defined by -the [`engine_forkchoiceUpdatedV1`] method of the [Engine API]: +## From Payload Attributes to L2 Block -- `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. -- `safeBlockHash`: same as `headBlockHash`. -- `finalizedBlockHash`: the hash of the block whose number is `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if - the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS == 50400` - (approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the - first L1 block for which an L2 block was produced). See the [Finalization Guarantees][finalization] section for more - details. +Once the [payload attributes] for a given L1 block `B` have been built, and if we have already derived an L2 block from +`B`'s parent block, then we can use the payload attributes to derive a new L2 block. -[`engine_forkchoiceUpdatedV1`]: exec-engine.md#engine_forkchoiceUpdatedV1 +### Inductive Derivation Step -Once this first API call completes, `engine_getPayloadV1` is used to fetch the full L2 block, -as specified in the [Engine API]. +Let -[`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 -[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 +- `refL2` be the (hash of) the current L2 chain head +- `refL1` be the (hash of) the L1 block from which `refL2` was derived +- `payloadAttributes` be some previously derived [payload attributes] for the L1 block with number `l1Number(refL1) + 1` + +Then we can apply the following pseudocode logic to update the state of both the rollup driver and execution engine: + +``` +// request a new execution payload +forkChoiceState = { + headBlockHash: refL2, + safeBlockHash: refL2, + finalizedBlockHash: l2BlockHashAt(l2Number(refL2) - FINALIZATION_DELAY_BLOCKS) +} +(status, payloadID) = engine_forkchoiceUpdatedV1(forkChoiceState, payloadAttributes) +if (status != "SUCCESS") error() -## Completing a driver step +// retrieve and execute the execution payload +(executionPayload, error) = engine_getPayloadV1(payloadID) +if (error != null) error() +(status, latestValidHash, validationError) = engine_executePayloadV1(executionPayload) +if (status != "VALID" || validationError != null) error() -After deriving a full L2 block, two more API calls are required to persist the result: -execute the new block, and update the forkchoice to reflect the new head. +refL2 = latestValidHash +refL1 = l1HashForNumber(l1Number(refL1) + 1)) -### Execute +// update head to new refL2 +forkChoiceState = { + headBlockHash: refL2, + safeBlockHash: refL2, + finalizedBlockHash: l2BlockHashAt(l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS) +} +(status, payloadID) = engine_forkchoiceUpdatedV1(refL2, null) +if (status != "SUCCESS") error() +``` -Execute through the [`engine_executePayloadV1`] API method with the derived payload to update the engine state. -A `"status": "VALID"` result is required to continue. +The following JSON-RPC methods are part of the [execution engine API][exec-engine]: +> **TODO** fortify the execution engine spec with more information regarding JSON-RPC, notably covering +> information found [here][json-rpc-info-1] and [here][json-rpc-info-2] + +[json-rpc-info-1]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#from-l1-blocks-to-payload-attributes +[json-rpc-info-2]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#building-the-l2-block-with-the-execution-engine + +[exec-engine]: execution-engine.md + +- [`engine_forkchoiceUpdatedV1`] — updates the forkchoice (i.e. the chain head) to `headBlockHash` if different, and + instructs the engine to start building an execution payload given payload attributes the second argument isn't `null` +- [`engine_getPayloadV1`] — retrieves a previously requested execution payload +- [`engine_executePayloadV1`] — executes an execution payload to create a block + +[`engine_forkchoiceUpdatedV1`]: exec-engine.md#engine_forkchoiceUpdatedV1 +[`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 [`engine_executePayloadV1`]: exec-engine.md#engine_executepayloadv1 -### Forkchoice +The execution payload is an object of type [`ExecutionPayloadV1`]. -Update the L2 head with a [`engine_forkchoiceUpdatedV1`] API call, now without `payloadAttributes` argument, -and updated `forkchoiceState` argument: +[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 + +Within the `forkChoiceState` object, the properties have the following meaning: + +- `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. +- `safeBlockHash`: same as `headBlockHash`. +- `finalizedBlockHash`: the hash of the block whose number is `l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if the + number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (\*) See the [Finalization Guarantees][finalization] + section for more details. -- `headBlockHash`: block hash of the derived payload -- `safeBlockHash`: same as `headBlockHash` -- `finalizedBlockHash`: finalized-block. May have changed since last call. - Not strictly required to change, this can be adjusted later. +(\*) where: -A `"status": "SUCCESS"` result then indicates if the engine successfully updated the head to the derived payload. +- `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 blocks) +- `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the first L1 block for which an L2 block was + produced). -## API error handling +Finally, the `error()` function signals an error that must be handled by the implementation. Refer to the next section +for more details. + +### Engine API Error Handling + +[error-handling]: #engine-api-error-handling All invocations of [`engine_forkchoiceUpdatedV1`], [`engine_getPayloadV1`] and [`engine_executePayloadV1`] by the rollup driver should not result in errors assuming conformity with the specification. Said otherwise, all errors are @@ -175,7 +234,34 @@ The following scenarios are assimilated to errors: - [`engine_executePayloadV1`] returning a `status` of `"SYNCING"` or `"INVALID"` whenever passed an execution payload that was obtained by a previous call to [`engine_getPayloadV1`]. -## Handling L1 Re-Orgs +### Finalization Guarantees + +[finalization]: #finalization-guarantees + +As stated earlier, an L2 block is considered *finalized* after a delay of `FINALIZATION_DELAY_BLOCKS == 50400` L1 blocks +after the L1 block that generated it. This is a duration of approximately 7 days worth of L1 blocks. This is also known +as the "fault proof window", as after this time the block can no longer be challenged by a fault proof. + +L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality]. L2 blocks generated from finalized L1 blocks +are "safer" than most recent L2 blocks because they will never disappear from the chain's history because of a re-org. +However, they can still be challenged by a fault proof until the end of the fault proof window. + +[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge/ + +> **TODO** the spec doesn't encode the notion of fault proof yet, revisit this (and include links) when it does + +## Whole L2 Chain Derivation + +The previous two sections presents an inductive process: given that we know the "current" L2 block, well as the next L1 +block, then we can derive [payload attributes] for the next L1 block, and from that the next L2 block. + +To derive the whole L2 chain from scratch, we simply start with the L2 genesis block as the current L2 block, and the +block at height `L2_CHAIN_INCEPTION + 1` as the next L1 block. Then we iteratively apply the derivation process from the +previous section to each successive L1 block until we have caught up with the L1 head. + +> **TODO** specify genesis block + +# Handling L1 Re-Orgs [l1-reorgs]: #handling-L1-re-orgs @@ -217,16 +303,3 @@ This sync starting point (L1 block to derive from, and L2 parent to build on) is Just like before, the meaning of errors returned by RPC calls is unspecified and must be handled at the implementer's discretion, while remaining compatible with the specification. - -## Finalization Guarantees - -[finalization]: #finalization-guarantees - -As already alluded to in the section on [interacting with the execution engine][calling-exec-engine], an L2 block is -considered *finalized* after a delay of `FINALIZATION_DELAY_BLOCKS == 50400` blocks after the L1 block that generated -it. This is a duration of approximately 7 days worth of L1 blocks. - -L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality], so these L2 blocks can safely be considered -to be final: they will never disappear from the chain's history because of a re-org. - -[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge/ From 4bf2bf1baff3bc4727e0005bc0e446a982c5e75c Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 15:02:11 +0100 Subject: [PATCH 182/585] update execution engine specs --- specs/exec-engine.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/exec-engine.md b/specs/exec-engine.md index e3fd40f68555..c668c42b8317 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -2,7 +2,7 @@ This document outlines the modifications, configuration and usage of a L1 execution engine for L2. -## Deposit processing +## Depositited transaction processing The Engine interfaces abstract away transaction types with [EIP-2718][eip-2718]. @@ -14,18 +14,18 @@ and introduce L1 information to enshrined contracts in the execution state. [deposit-spec]: deposits.md -### Deposit boundaries +### Deposited transaction boundaries Transactions cannot be blindly trusted, trust is established through authentication. Unlike other transaction types deposits are not authenticated by a signature: the rollup node authenticates them, outside of the engine. -To process deposits safely, the deposits MUST be authenticated first: +To process deposited transactions safely, the deposits MUST be authenticated first: - Ingest directly through trusted Engine API - Part of sync towards a trusted block hash (trusted through previous Engine API instruction) -Deposits MUST never be consumed from the transaction pool. +Deposited transactions MUST never be consumed from the transaction pool. *The transaction pool can be disabled in a deposits-only rollup* ## Engine API From ec8aab3c422204f628babe4cbd6c469f1a587d21 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:05:01 +0100 Subject: [PATCH 183/585] simplify/clarify sync start algorithm --- specs/rollup-node.md | 59 +++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 48293ae44b97..1cb3a8c480b1 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -273,33 +273,36 @@ processing the whole L1 chain since the [L2 chain inception]. > non-specificative** but shows how L1 re-orgs can be handled in practice. In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally re-organize, meaning the -head of the L1 chain changes to a block that is not the child of the previous head but rather some other descendant -of an ancestor of the previous head. In that case, the rollup driver must first search for common ancestor, and can then -continue deriving with the new canonical L1 block after the common point. - -This sync starting point (L1 block to derive from, and L2 parent to build on) is determined by: - -- Retrieve the head block of the engine (`refL2`), then determine the L1 block it was derived from (`refL1`), - and where it builds on (`parentL2`). -- Fetch the L1 block at the same height (`currentL1`): - - If not found: consider this a reorg to a shorter L1 chain, continue. -- If the L1 source considers this canonical (`currentL1 == refL1`): - - Find the next L1 block (it may not exist yet) and return that as `nextRefL1`, along with the `refL2`. - - Note: after looking up `N+1` ensure L1 has not changed during block-by-number lookups (`refL1 == nextL1_parent`). -- While have not found a block in the engine common with the canonical chain, traverse the L2 chain back until genesis: - - Each step starts by caching the previous `currentL1` as `nextRefL1`. - - Lookup the parent by hash: Each step `refL2` should equal the previous `parentL2`. - `refL1` and `parentL2` are also traversed back by parsing the `refL2` block. - - The canonical L1 block is looked up at the same height (`currentL1`). - - If not found: consider this a reorg to a shorter L1 chain, continue. - - If the engine and canonical chain match (`refL1 == currentL1`), then return that as `nextRefL1`, along with `refL2`. -- If there are no common blocks after genesis, check if `refL2` and `currentL1` match the expected genesis blocks. -- If the genesis is correct, the last cached `nextRefL1` is returned, along with the L2 genesis. - -> Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more -> than `FINALIZATION_DELAY_BLOCKS == 50400` in the past, hence preserving our finalization guarantees. +head of the L1 chain changes to a block that is not the child of the previous head but rather another descendant of an +ancestor of the previous head. In that case, the rollup driver must first search for the common L1 ancestor, and can +re-derive the L2 chain from that L1 block and onwards. + +The starting point of the re-derivation is a pair `(refL2, nextRefL1)` where `refL2` refers to the L2 block to build +upon and `nextRefL1` refers to the next L1 block to derive from (i.e. if `refL2` is derived from L1 block `refL1`, +`nextRefL1` is the canonicla L1 block at height `l1Number(refL1) + 1`). + +In practice, the happy path (no re-org) and the re-org paths are merged. The happy path is simply a special case of the +re-org path where the starting point of the re-derivation is `(currentL2Head, newL1Block)`. + +This re-derivation starting point can be found by applying the following algorithm: + +1. (Initialization) Set the initial `refL2` to the head block of the L2 execution engine. +2. Set `parentL2` to `refL2`'s parent block and `refL1` to the L1 block that `refL2` was derived from. +3. Fetch `currentL1`, the canonical L1 block at the same height as `refL1`. + - If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: + - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the re-derivation. + - It is necessary to ensure that no L1 re-org occured during this lookup, i.e. that `nextRefL1.parent == refL1`. + - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the + process. + - Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that + requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration). + - Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this + algorithm from step 2. + - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. + - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an + extra lookup. + +Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, +approximately 12 minutes). [merge]: https://ethereum.org/en/eth2/merge/ - -Just like before, the meaning of errors returned by RPC calls is unspecified and must be handled at the implementer's -discretion, while remaining compatible with the specification. From 9d544706eaa96e72afecf69ef3e1175185437369 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:12:56 +0100 Subject: [PATCH 184/585] lint --- specs/rollup-node.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 1cb3a8c480b1..8fcae7b28e4d 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -119,8 +119,8 @@ To encode user-deposited transactions, refer to the following sections of the de [payload attributes]: #building-the-payload-attributes -From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded version][expanded-paylod] of -[`PayloadAttributesV1`], which includes an additional `transactions` field. +From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded +version][expanded-paylod] of [`PayloadAttributesV1`], which includes an additional `transactions` field. The object's properties must be set as follows: @@ -149,7 +149,7 @@ Let Then we can apply the following pseudocode logic to update the state of both the rollup driver and execution engine: -``` +```pseudocode // request a new execution payload forkChoiceState = { headBlockHash: refL2, @@ -186,7 +186,7 @@ The following JSON-RPC methods are part of the [execution engine API][exec-engin [json-rpc-info-1]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#from-l1-blocks-to-payload-attributes [json-rpc-info-2]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#building-the-l2-block-with-the-execution-engine -[exec-engine]: execution-engine.md +[exec-engine]: exec-engine.md - [`engine_forkchoiceUpdatedV1`] — updates the forkchoice (i.e. the chain head) to `headBlockHash` if different, and instructs the engine to start building an execution payload given payload attributes the second argument isn't `null` @@ -205,8 +205,8 @@ Within the `forkChoiceState` object, the properties have the following meaning: - `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. - `safeBlockHash`: same as `headBlockHash`. -- `finalizedBlockHash`: the hash of the block whose number is `l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if the - number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (\*) See the [Finalization Guarantees][finalization] +- `finalizedBlockHash`: the hash of the block whose number is `l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if + the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (\*) See the [Finalization Guarantees][finalization] section for more details. (\*) where: @@ -289,17 +289,19 @@ This re-derivation starting point can be found by applying the following algorit 1. (Initialization) Set the initial `refL2` to the head block of the L2 execution engine. 2. Set `parentL2` to `refL2`'s parent block and `refL1` to the L1 block that `refL2` was derived from. 3. Fetch `currentL1`, the canonical L1 block at the same height as `refL1`. - - If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: - - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the re-derivation. - - It is necessary to ensure that no L1 re-org occured during this lookup, i.e. that `nextRefL1.parent == refL1`. - - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the + +- If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: + - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the + re-derivation. + - It is necessary to ensure that no L1 re-org occured during this lookup, i.e. that `nextRefL1.parent == refL1`. + - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the process. - - Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that +- Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration). - - Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this +- Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this algorithm from step 2. - - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. - - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an + - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. + - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an extra lookup. Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, From ddfe868ffc6e459132790b11fdf59e85ab5cedb8 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:43:21 +0100 Subject: [PATCH 185/585] switch glossary links in rollup node spec to use g-prefix --- specs/glossary.md | 15 +++++----- specs/rollup-node.md | 67 ++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index d90c5a0aef70..08315a2b5ccd 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -313,16 +313,17 @@ L2 derivation inputs include: [payload attributes]: glossary.md#payload-attributes -This term refers to data that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are then -passed to the [execution engine][execution-engine] to construct L2 blocks. +This term refers to an object that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are +then passed to the [execution engine][execution-engine] to construct L2 blocks. -"Payload attributes" is a term that originates and is specified in the [Ethereum Engine API specification][engine-api], -which we extend in this specification. +The payload attributes object essentially essentially encodes a [a block without output properties][block]. -cf. [Execution Engine Specification](exec-engine.md) +Payload attributes are originally specified in the [Ethereum Engine API specification][engine-api], which we expand in +the [Execution Engine Specification](exec-engine.md). -Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using -this term. +See also the [Building The Payload Attributes][building-payload-attr] section of the rollup node specification. + +[building-payload-attr]: rollup-node.md#building-the-payload-attributes ## L1 Attributes Predeployed Contract diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 8fcae7b28e4d..41a817e61ab8 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -1,16 +1,15 @@ # Rollup Node Specification -[rollup node]: glossary.md#rollup-node -[derivation]: glossary.md#L2-chain-derivation -[payload attributes]: glossary.md#payload-attributes -[block]: glossary.md#block -[execution engine]: glossary.md#execution-engine -[reorg]: glossary.md#re-organization -[rollup driver]: glossary.md#rollup-driver -[L2 chain inception]: glossary.md#L2-chain-inception -[receipts]: glossary.md#receipt -[L1 attributes deposit]: glossary.md#l1-attributes-deposit +[g-rollup-node]: glossary.md#rollup-node +[g-derivation]: glossary.md#L2-chain-derivation +[g-payload-attr]: glossary.md#payload-attributes +[g-block]: glossary.md#block +[g-exec-engine]: glossary.md#execution-engine +[g-reorg]: glossary.md#re-organization +[g-rollup-driver]: glossary.md#rollup-driver +[g-inception]: glossary.md#L2-chain-inception +[g-receipts]: glossary.md#receipt [g-deposit-contract]: glossary.md#deposit-contract [g-deposits]: glossary.md#deposits [g-deposit-block]: glossary.md#deposit-block @@ -21,20 +20,20 @@ [g-depositing-call]: glossary.md#depositing-call [g-depositing-transaction]: glossary.md#depositing-transaction -The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their -associated [receipts]). This process happens in two steps: +The [rollup node][g-rollup-node] is the component responsible for [deriving the L2 chain][g-derivation] from L1 blocks +(and their associated [receipts][g-receipts]). This process happens in two steps: -1. Read from L1 blocks and associated receipts, in order to generate [payload attributes] (essentially [a block without - output properties][block]). -2. Pass the payload attributes to the [execution engine], so that the L2 block (including [output block - properties][block]) may be computed. +1. Read from L1 blocks and associated receipts, in order to generate [payload attributes][g-payload-attr] (essentially + [a block without output properties][g-block]). +2. Pass the payload attributes to the [execution engine][g-exec-engine], so that the L2 block (including [output block + properties][g-block]) may be computed. While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The L2 chain is extended whenever new L1 blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the -L1 chain [re-organizes][reorg]. +L1 chain [re-organizes][g-reorg]. -The part of the rollup node that derives the L2 chain is called the [rollup driver]. This document is currently only -concerned with the specification of the rollup driver. +The part of the rollup node that derives the L2 chain is called the [rollup driver][g-rollup-driver]. This document is +currently only concerned with the specification of the rollup driver. ## Table of Contents @@ -55,8 +54,8 @@ concerned with the specification of the rollup driver. [l2-chain-derivation]: #l2-chain-derivation -This section specifies how the [rollup driver] derives one L2 [deposit block][g-deposit-block] per every L1 block. The -L2 block carries *[deposited transactions][g-deposited]* of two kinds: +This section specifies how the [rollup driver][g-rollup-driver] derives one L2 [deposit block][g-deposit-block] per +every L1 block. The L2 block carries *[deposited transactions][g-deposited]* of two kinds: - a single *[L1 attributes deposited transaction][g-l1-attr-deposit]* (always first) - zero or more *[user-deposited transactions][g-user-deposited]* @@ -84,10 +83,11 @@ The rollup reads the following data from each L1 block: > them, two different deposited transaction could have the same exact hash. > > We do not use the sender's nonce to ensure uniqueness because this would require an extra L2 EVM state read from the -> [execution engine]. +> [execution engine][g-exec-engine]. -The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the -[**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log entries. +The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts][g-receipts]. +Refer to the [**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log +entries. [deposit-contract-spec]: deposits.md#deposit-contract @@ -119,8 +119,9 @@ To encode user-deposited transactions, refer to the following sections of the de [payload attributes]: #building-the-payload-attributes -From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded -version][expanded-paylod] of [`PayloadAttributesV1`], which includes an additional `transactions` field. +From the data read from L1 and the encoded transactions, the rollup node constructs the [payload +attributes][g-payload-attr] as an [expanded version][expanded-paylod] of the [`PayloadAttributesV1`] object, which +includes an additional `transactions` field. The object's properties must be set as follows: @@ -212,8 +213,8 @@ Within the `forkChoiceState` object, the properties have the following meaning: (\*) where: - `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 blocks) -- `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the first L1 block for which an L2 block was - produced). +- `L2_CHAIN_INCEPTION` is the [L2 chain inception][g-inception] (the number of the first L1 block for which an L2 block + was produced). Finally, the `error()` function signals an error that must be handled by the implementation. Refer to the next section for more details. @@ -267,15 +268,15 @@ previous section to each successive L1 block until we have caught up with the L1 The [previous section on L2 chain derivation][l2-chain-derivation] assumes linear progression of the L1 chain. It is also applicable for batch processing, meaning that any given point in time, the canonical L2 chain is given by -processing the whole L1 chain since the [L2 chain inception]. +processing the whole L1 chain since the [L2 chain inception][g-inception]. > By itself, the previous section fully specifies the behaviour of the rollup driver. **The current section is > non-specificative** but shows how L1 re-orgs can be handled in practice. -In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally re-organize, meaning the -head of the L1 chain changes to a block that is not the child of the previous head but rather another descendant of an -ancestor of the previous head. In that case, the rollup driver must first search for the common L1 ancestor, and can -re-derive the L2 chain from that L1 block and onwards. +In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally [re-organize][g-reorg], +meaning the head of the L1 chain changes to a block that is not the child of the previous head but rather another +descendant of an ancestor of the previous head. In that case, the rollup driver must first search for the common L1 +ancestor, and can re-derive the L2 chain from that L1 block and onwards. The starting point of the re-derivation is a pair `(refL2, nextRefL1)` where `refL2` refers to the L2 block to build upon and `nextRefL1` refers to the next L1 block to derive from (i.e. if `refL2` is derived from L1 block `refL1`, From a9087ce53d6953057c36d5dec741cdff603d659a Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:43:38 +0100 Subject: [PATCH 186/585] add specifications for markdown style --- meta/README.md | 6 ++++++ meta/markdown-style.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 meta/README.md create mode 100644 meta/markdown-style.md diff --git a/meta/README.md b/meta/README.md new file mode 100644 index 000000000000..5329ee3c3b65 --- /dev/null +++ b/meta/README.md @@ -0,0 +1,6 @@ +# Meta Processes + +This directory describes processes that we use to build the specification. + +- [Linting](linting.md): how to lint source files. +- [Markdown Style Guide](markdown-style.md): how to format and structure Markdown files. diff --git a/meta/markdown-style.md b/meta/markdown-style.md new file mode 100644 index 000000000000..af0998f72ada --- /dev/null +++ b/meta/markdown-style.md @@ -0,0 +1,42 @@ +# Markdown Style Guide + +## Linting + +Respect the [linting rules] (you can run the linter with `yarn lint`). + +Notably: + +- lines should be < 120 characters long + - in practice, some of our files are justified at 100 characters, some at 120 + +[linting rules]: linting.md#markdown + +## Links + +In general: + +- Use link references preferentially. + - e.g. `[my text][link-ref]` and then on its own line `[link-ref]: https://mylink.com` + - e.g. `[my text]` and then on its own line: `[my text]: https://mylink.com` + - exceptions: where it fits neatly on a single line, in particular in lists of links +- Excepted for internal and glossary links (see below), add the link reference definition directly + after the paragraph where the link first appears. + +### Glossary + +- Use links to the [glossary] liberally. +- Include the references to all the glossary links at the top of the file, under the top-level + title. +- A glossary link reference should start with the `g-` prefix. This enables to see what links to the + glossary at a glance when editing the specification. + - e.g. `[g-block]: glossary.md#block` +- Example: [Rollup Node Specification source][rollup-node] + +[glossary]: ../specs/glossary.md +[rollup-node]: https://raw.githubusercontent.com/ethereum-optimism/optimistic-specs/main/specs/rollup-node.md + +## Internal (In-File) Links + +If linking to another heading to the same file, add the link reference directly under that heading. +This makes it easier to keep the heading and the link in-sync, and signals that the heading is being +linked to from elsewhere. From 1593cd84034a94a2a1e39b9bb20b62a886ff90b9 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 25 Jan 2022 17:28:12 +0100 Subject: [PATCH 187/585] ref impl: reduce command running boilerplate --- go.mod | 2 +- go.sum | 4 +-- opnode/cmd/main.go | 70 +--------------------------------------------- 3 files changed, 4 insertions(+), 72 deletions(-) diff --git a/go.mod b/go.mod index 0dd26cc8bbd3..1fd835d3c23d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/ethereum/go-ethereum v1.10.13 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.0 - github.com/protolambda/ask v0.1.2 + github.com/protolambda/ask v0.1.3 github.com/stretchr/testify v1.7.0 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 ) diff --git a/go.sum b/go.sum index 05182a2c2353..544b34383c0b 100644 --- a/go.sum +++ b/go.sum @@ -326,8 +326,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/protolambda/ask v0.1.2 h1:BSQP7VDmh+L0lLFjEYUMrTnb2SwdT64UY3vXqDuIIok= -github.com/protolambda/ask v0.1.2/go.mod h1:7WB3T4BXZhKUaDcEjF7Ksgi7HCrBDxM37gyM1EhwkmM= +github.com/protolambda/ask v0.1.3 h1:DhROikobv9hgj6zUh9svByFvzvsAHvDSzjwsGDMYAu8= +github.com/protolambda/ask v0.1.3/go.mod h1:7WB3T4BXZhKUaDcEjF7Ksgi7HCrBDxM37gyM1EhwkmM= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index a8d83d9c3b46..3ca05227d73d 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -1,13 +1,6 @@ package main import ( - "context" - "fmt" - "io" - "os" - "os/signal" - "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/protolambda/ask" ) @@ -33,67 +26,6 @@ func (c *MainCmd) Routes() []string { return []string{"run"} } -type start struct { - cmd *ask.CommandDescription - err error -} - func main() { - interrupt := make(chan os.Signal, 1) - signal.Notify(interrupt, os.Interrupt) - ctx, cancel := context.WithCancel(context.Background()) - - cmd := &MainCmd{} - descr, err := ask.Load(cmd) - if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "failed to load main command: %v", err.Error()) - os.Exit(1) - } - onDeprecated := func(fl ask.PrefixedFlag) error { - fmt.Fprintf(os.Stderr, "warning: flag %q is deprecated: %s", fl.Path, fl.Deprecated) - return nil - } - - starter := make(chan start) - - // run command in the background, so we can stop it at any time - go func() { - cmd, err := descr.Execute(ctx, &ask.ExecutionOptions{OnDeprecated: onDeprecated}, os.Args[1:]...) - starter <- start{cmd, err} - }() - - for { - select { - case start := <-starter: - if cmd, err := start.cmd, start.err; err == nil { - // if the command is long-running and closeable later on, then have the interrupt close it. - if cl, ok := cmd.Command.(io.Closer); ok { - <-interrupt - err := cl.Close() - cancel() - if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "failed to close node gracefully. Exiting in 5 seconds. %v", err.Error()) - <-time.After(time.Second * 5) - os.Exit(1) - } - os.Exit(0) - } else { - os.Exit(0) - } - } else if err == ask.UnrecognizedErr { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } else if err == ask.HelpErr { - _, _ = fmt.Fprintln(os.Stderr, cmd.Usage(false)) - os.Exit(0) - } else { - _, _ = fmt.Fprintln(os.Stderr, err.Error()) - os.Exit(1) - } - case <-interrupt: // if interrupted during start, then we try to cancel - cancel() - // TODO: multiple interrupts to force quick exit? - } - } - + ask.Run(new(MainCmd)) } From a90526997d92241eb0cdffb19671b41efed3dafe Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 25 Jan 2022 15:46:53 -0800 Subject: [PATCH 188/585] ref impl: Go contract bindings This adds go contract bindings for the deposit and l1 block info contracts. These bindings are creating with `abigen`. These are currently generated from the artifacts directory with a manual script rather than `go generate` or a CI script. --- opnode/contracts/deposit/deposit_feed_raw.go | 359 ++++++++++++++++++ opnode/contracts/l1block/l1_block_info_raw.go | 356 +++++++++++++++++ 2 files changed, 715 insertions(+) create mode 100644 opnode/contracts/deposit/deposit_feed_raw.go create mode 100644 opnode/contracts/l1block/l1_block_info_raw.go diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/opnode/contracts/deposit/deposit_feed_raw.go new file mode 100644 index 000000000000..c6a34dd23863 --- /dev/null +++ b/opnode/contracts/deposit/deposit_feed_raw.go @@ -0,0 +1,359 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package deposit + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// DepositMetaData contains all meta data concerning the Deposit contract. +var DepositMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", +} + +// DepositABI is the input ABI used to generate the binding from. +// Deprecated: Use DepositMetaData.ABI instead. +var DepositABI = DepositMetaData.ABI + +// Deposit is an auto generated Go binding around an Ethereum contract. +type Deposit struct { + DepositCaller // Read-only binding to the contract + DepositTransactor // Write-only binding to the contract + DepositFilterer // Log filterer for contract events +} + +// DepositCaller is an auto generated read-only Go binding around an Ethereum contract. +type DepositCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DepositTransactor is an auto generated write-only Go binding around an Ethereum contract. +type DepositTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DepositFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type DepositFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DepositSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type DepositSession struct { + Contract *Deposit // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DepositCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type DepositCallerSession struct { + Contract *DepositCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// DepositTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type DepositTransactorSession struct { + Contract *DepositTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DepositRaw is an auto generated low-level Go binding around an Ethereum contract. +type DepositRaw struct { + Contract *Deposit // Generic contract binding to access the raw methods on +} + +// DepositCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type DepositCallerRaw struct { + Contract *DepositCaller // Generic read-only contract binding to access the raw methods on +} + +// DepositTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type DepositTransactorRaw struct { + Contract *DepositTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewDeposit creates a new instance of Deposit, bound to a specific deployed contract. +func NewDeposit(address common.Address, backend bind.ContractBackend) (*Deposit, error) { + contract, err := bindDeposit(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Deposit{DepositCaller: DepositCaller{contract: contract}, DepositTransactor: DepositTransactor{contract: contract}, DepositFilterer: DepositFilterer{contract: contract}}, nil +} + +// NewDepositCaller creates a new read-only instance of Deposit, bound to a specific deployed contract. +func NewDepositCaller(address common.Address, caller bind.ContractCaller) (*DepositCaller, error) { + contract, err := bindDeposit(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &DepositCaller{contract: contract}, nil +} + +// NewDepositTransactor creates a new write-only instance of Deposit, bound to a specific deployed contract. +func NewDepositTransactor(address common.Address, transactor bind.ContractTransactor) (*DepositTransactor, error) { + contract, err := bindDeposit(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &DepositTransactor{contract: contract}, nil +} + +// NewDepositFilterer creates a new log filterer instance of Deposit, bound to a specific deployed contract. +func NewDepositFilterer(address common.Address, filterer bind.ContractFilterer) (*DepositFilterer, error) { + contract, err := bindDeposit(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &DepositFilterer{contract: contract}, nil +} + +// bindDeposit binds a generic wrapper to an already deployed contract. +func bindDeposit(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(DepositABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Deposit *DepositRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Deposit.Contract.DepositCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Deposit *DepositRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Deposit.Contract.DepositTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Deposit *DepositRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Deposit.Contract.DepositTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Deposit *DepositCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Deposit.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Deposit *DepositTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Deposit.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Deposit *DepositTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Deposit.Contract.contract.Transact(opts, method, params...) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_Deposit *DepositTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _Deposit.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_Deposit *DepositSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _Deposit.Contract.DepositTransaction(&_Deposit.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_Deposit *DepositTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _Deposit.Contract.DepositTransaction(&_Deposit.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the Deposit contract. +type DepositTransactionDepositedIterator struct { + Event *DepositTransactionDeposited // 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 *DepositTransactionDepositedIterator) 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(DepositTransactionDeposited) + 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(DepositTransactionDeposited) + 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 *DepositTransactionDepositedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DepositTransactionDepositedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DepositTransactionDeposited represents a TransactionDeposited event raised by the Deposit contract. +type DepositTransactionDeposited struct { + From common.Address + To common.Address + Mint *big.Int + Value *big.Int + GasLimit *big.Int + IsCreation bool + Data []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +func (_Deposit *DepositFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DepositTransactionDepositedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Deposit.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule) + if err != nil { + return nil, err + } + return &DepositTransactionDepositedIterator{contract: _Deposit.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil +} + +// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +func (_Deposit *DepositFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *DepositTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Deposit.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule) + 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(DepositTransactionDeposited) + if err := _Deposit.contract.UnpackLog(event, "TransactionDeposited", 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 +} + +// ParseTransactionDeposited is a log parse operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +func (_Deposit *DepositFilterer) ParseTransactionDeposited(log types.Log) (*DepositTransactionDeposited, error) { + event := new(DepositTransactionDeposited) + if err := _Deposit.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/opnode/contracts/l1block/l1_block_info_raw.go b/opnode/contracts/l1block/l1_block_info_raw.go new file mode 100644 index 000000000000..d1151840b516 --- /dev/null +++ b/opnode/contracts/l1block/l1_block_info_raw.go @@ -0,0 +1,356 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package l1block + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// L1blockMetaData contains all meta data concerning the L1block contract. +var L1blockMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// L1blockABI is the input ABI used to generate the binding from. +// Deprecated: Use L1blockMetaData.ABI instead. +var L1blockABI = L1blockMetaData.ABI + +// L1block is an auto generated Go binding around an Ethereum contract. +type L1block struct { + L1blockCaller // Read-only binding to the contract + L1blockTransactor // Write-only binding to the contract + L1blockFilterer // Log filterer for contract events +} + +// L1blockCaller is an auto generated read-only Go binding around an Ethereum contract. +type L1blockCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L1blockTransactor is an auto generated write-only Go binding around an Ethereum contract. +type L1blockTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L1blockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type L1blockFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L1blockSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type L1blockSession struct { + Contract *L1block // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// L1blockCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type L1blockCallerSession struct { + Contract *L1blockCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// L1blockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type L1blockTransactorSession struct { + Contract *L1blockTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// L1blockRaw is an auto generated low-level Go binding around an Ethereum contract. +type L1blockRaw struct { + Contract *L1block // Generic contract binding to access the raw methods on +} + +// L1blockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type L1blockCallerRaw struct { + Contract *L1blockCaller // Generic read-only contract binding to access the raw methods on +} + +// L1blockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type L1blockTransactorRaw struct { + Contract *L1blockTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewL1block creates a new instance of L1block, bound to a specific deployed contract. +func NewL1block(address common.Address, backend bind.ContractBackend) (*L1block, error) { + contract, err := bindL1block(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &L1block{L1blockCaller: L1blockCaller{contract: contract}, L1blockTransactor: L1blockTransactor{contract: contract}, L1blockFilterer: L1blockFilterer{contract: contract}}, nil +} + +// NewL1blockCaller creates a new read-only instance of L1block, bound to a specific deployed contract. +func NewL1blockCaller(address common.Address, caller bind.ContractCaller) (*L1blockCaller, error) { + contract, err := bindL1block(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &L1blockCaller{contract: contract}, nil +} + +// NewL1blockTransactor creates a new write-only instance of L1block, bound to a specific deployed contract. +func NewL1blockTransactor(address common.Address, transactor bind.ContractTransactor) (*L1blockTransactor, error) { + contract, err := bindL1block(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &L1blockTransactor{contract: contract}, nil +} + +// NewL1blockFilterer creates a new log filterer instance of L1block, bound to a specific deployed contract. +func NewL1blockFilterer(address common.Address, filterer bind.ContractFilterer) (*L1blockFilterer, error) { + contract, err := bindL1block(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &L1blockFilterer{contract: contract}, nil +} + +// bindL1block binds a generic wrapper to an already deployed contract. +func bindL1block(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(L1blockABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_L1block *L1blockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L1block.Contract.L1blockCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_L1block *L1blockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L1block.Contract.L1blockTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_L1block *L1blockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L1block.Contract.L1blockTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_L1block *L1blockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L1block.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_L1block *L1blockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L1block.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_L1block *L1blockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L1block.Contract.contract.Transact(opts, method, params...) +} + +// DEPOSITORACCOUNT is a free data retrieval call binding the contract method 0xe591b282. +// +// Solidity: function DEPOSITOR_ACCOUNT() view returns(address) +func (_L1block *L1blockCaller) DEPOSITORACCOUNT(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _L1block.contract.Call(opts, &out, "DEPOSITOR_ACCOUNT") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// DEPOSITORACCOUNT is a free data retrieval call binding the contract method 0xe591b282. +// +// Solidity: function DEPOSITOR_ACCOUNT() view returns(address) +func (_L1block *L1blockSession) DEPOSITORACCOUNT() (common.Address, error) { + return _L1block.Contract.DEPOSITORACCOUNT(&_L1block.CallOpts) +} + +// DEPOSITORACCOUNT is a free data retrieval call binding the contract method 0xe591b282. +// +// Solidity: function DEPOSITOR_ACCOUNT() view returns(address) +func (_L1block *L1blockCallerSession) DEPOSITORACCOUNT() (common.Address, error) { + return _L1block.Contract.DEPOSITORACCOUNT(&_L1block.CallOpts) +} + +// Basefee is a free data retrieval call binding the contract method 0x5cf24969. +// +// Solidity: function basefee() view returns(uint256) +func (_L1block *L1blockCaller) Basefee(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L1block.contract.Call(opts, &out, "basefee") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Basefee is a free data retrieval call binding the contract method 0x5cf24969. +// +// Solidity: function basefee() view returns(uint256) +func (_L1block *L1blockSession) Basefee() (*big.Int, error) { + return _L1block.Contract.Basefee(&_L1block.CallOpts) +} + +// Basefee is a free data retrieval call binding the contract method 0x5cf24969. +// +// Solidity: function basefee() view returns(uint256) +func (_L1block *L1blockCallerSession) Basefee() (*big.Int, error) { + return _L1block.Contract.Basefee(&_L1block.CallOpts) +} + +// Hash is a free data retrieval call binding the contract method 0x09bd5a60. +// +// Solidity: function hash() view returns(bytes32) +func (_L1block *L1blockCaller) Hash(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _L1block.contract.Call(opts, &out, "hash") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// Hash is a free data retrieval call binding the contract method 0x09bd5a60. +// +// Solidity: function hash() view returns(bytes32) +func (_L1block *L1blockSession) Hash() ([32]byte, error) { + return _L1block.Contract.Hash(&_L1block.CallOpts) +} + +// Hash is a free data retrieval call binding the contract method 0x09bd5a60. +// +// Solidity: function hash() view returns(bytes32) +func (_L1block *L1blockCallerSession) Hash() ([32]byte, error) { + return _L1block.Contract.Hash(&_L1block.CallOpts) +} + +// Number is a free data retrieval call binding the contract method 0x8381f58a. +// +// Solidity: function number() view returns(uint256) +func (_L1block *L1blockCaller) Number(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L1block.contract.Call(opts, &out, "number") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Number is a free data retrieval call binding the contract method 0x8381f58a. +// +// Solidity: function number() view returns(uint256) +func (_L1block *L1blockSession) Number() (*big.Int, error) { + return _L1block.Contract.Number(&_L1block.CallOpts) +} + +// Number is a free data retrieval call binding the contract method 0x8381f58a. +// +// Solidity: function number() view returns(uint256) +func (_L1block *L1blockCallerSession) Number() (*big.Int, error) { + return _L1block.Contract.Number(&_L1block.CallOpts) +} + +// Timestamp is a free data retrieval call binding the contract method 0xb80777ea. +// +// Solidity: function timestamp() view returns(uint256) +func (_L1block *L1blockCaller) Timestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L1block.contract.Call(opts, &out, "timestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Timestamp is a free data retrieval call binding the contract method 0xb80777ea. +// +// Solidity: function timestamp() view returns(uint256) +func (_L1block *L1blockSession) Timestamp() (*big.Int, error) { + return _L1block.Contract.Timestamp(&_L1block.CallOpts) +} + +// Timestamp is a free data retrieval call binding the contract method 0xb80777ea. +// +// Solidity: function timestamp() view returns(uint256) +func (_L1block *L1blockCallerSession) Timestamp() (*big.Int, error) { + return _L1block.Contract.Timestamp(&_L1block.CallOpts) +} + +// SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. +// +// Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() +func (_L1block *L1blockTransactor) SetL1BlockValues(opts *bind.TransactOpts, _number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { + return _L1block.contract.Transact(opts, "setL1BlockValues", _number, _timestamp, _basefee, _hash) +} + +// SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. +// +// Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() +func (_L1block *L1blockSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { + return _L1block.Contract.SetL1BlockValues(&_L1block.TransactOpts, _number, _timestamp, _basefee, _hash) +} + +// SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. +// +// Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() +func (_L1block *L1blockTransactorSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { + return _L1block.Contract.SetL1BlockValues(&_L1block.TransactOpts, _number, _timestamp, _basefee, _hash) +} From 3c699683e7f74f5fd517323d8e641535dffb41a5 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Wed, 26 Jan 2022 15:43:37 +0100 Subject: [PATCH 189/585] add lychee information to meta/linting.md --- meta/linting.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/meta/linting.md b/meta/linting.md index d68b1dbd5ea4..1645d61af596 100644 --- a/meta/linting.md +++ b/meta/linting.md @@ -15,10 +15,21 @@ Justification for linting rules in [.markdownlint.json](/.markdownlint.json): - *no-emphasis-as-heading*: enable emphasized paragraphs ```shell -yarn # Install dependencies -yarn lint # Run linter +yarn # Install dependencies +yarn lint # Run linter +yarn lint:links # Check links ``` +To check links, you'll need to install [lychee]. The [version ran in CI][lychee-ci] is 0.8.1, but +you should install lychee 0.8.2 locally with `cargo install --version 0.8.2 lychee` (there are some +reported build problems with 0.8.1). + +You can install cargo (the Rust package manager) via [rustup]. + +[lychee]: https://github.com/lycheeverse/lychee +[lychee-ci]: https://github.com/lycheeverse/lychee-action/blob/f76b8412c668f78311212d16d33c4784a7d8762c/Dockerfile +[rustup]: https://www.rust-lang.org/tools/install + ## Go See From 65786d32313c8f66afd03d2037515ded0b16c96a Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 25 Jan 2022 15:47:43 -0800 Subject: [PATCH 190/585] ref impl: E2E Test in go This implements an end-to-end test of the rollup node system. It creates a L1, rollup, and L2 nodes, all of which are in process. It then submits a deposit transaction and asserts that the resulting mint shows up on layer 2. --- go.mod | 24 +++- go.sum | 33 +++++- opnode/test/geth.go | 77 +++++++++++++ opnode/test/setup.go | 161 ++++++++++++++++++++++++++ opnode/test/system_test.go | 230 +++++++++++++++++++++++++++++++++++++ 5 files changed, 522 insertions(+), 3 deletions(-) create mode 100644 opnode/test/geth.go create mode 100644 opnode/test/setup.go create mode 100644 opnode/test/system_test.go diff --git a/go.mod b/go.mod index 1fd835d3c23d..95ddb8d9ca90 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/ethereum/go-ethereum v1.10.13 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.0 + github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/protolambda/ask v0.1.3 github.com/stretchr/testify v1.7.0 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 @@ -14,27 +15,48 @@ require ( require ( github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect - github.com/btcsuite/btcd v0.20.1-beta // indirect + github.com/btcsuite/btcd v0.21.0-beta // indirect + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect + github.com/edsrzf/mmap-go v1.0.0 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.1.5 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/huin/goupnp v1.0.2 // indirect + github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 // indirect + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/tsdb v0.7.1 // indirect + github.com/rjeczalik/notify v0.9.1 // indirect + github.com/rs/cors v1.7.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect github.com/stretchr/objx v0.1.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef // indirect golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect + golang.org/x/text v0.3.6 // indirect + golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/urfave/cli.v1 v1.20.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index 544b34383c0b..c471f1f28b1a 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,9 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA 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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/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/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= @@ -60,17 +61,24 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 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 v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 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 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -93,13 +101,17 @@ 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 v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 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.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf h1:sh8rkQZavChcmakYiSlqu2425CHyFXLZZnvm7PDpU8M= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 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= @@ -109,6 +121,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a h1:ifL2rtsPv8plDlAucTQdLecBgLWph9HeXA0CHDKpxIE= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -135,6 +148,7 @@ github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= @@ -161,6 +175,7 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -200,6 +215,7 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= @@ -220,6 +236,7 @@ github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJye github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/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/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -228,9 +245,11 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 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 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 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.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -258,6 +277,7 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN 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.0/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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= @@ -265,6 +285,7 @@ github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= @@ -275,6 +296,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= +github.com/miguelmota/go-ethereum-hdwallet v0.1.1/go.mod h1:f9m9uXokAHA6WNoYOPjj4AqjJS5pquQRiYYj/XSyPYc= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -295,6 +318,7 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= @@ -360,6 +384,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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= @@ -389,6 +414,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -422,9 +449,11 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20181011144130-49bb7cea24b1/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= diff --git a/opnode/test/geth.go b/opnode/test/geth.go new file mode 100644 index 000000000000..223b1d901893 --- /dev/null +++ b/opnode/test/geth.go @@ -0,0 +1,77 @@ +package test + +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/accounts/keystore" + "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/node" + + hdwallet "github.com/miguelmota/go-ethereum-hdwallet" +) + +// 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) (*node.Node, *eth.Ethereum, error) { + + n, err := node.New(nodeCfg) + if err != nil { + n.Close() + return nil, nil, err + } + + keydir := n.KeyStoreDir() + scryptN := keystore.LightScryptN + scryptP := keystore.LightScryptP + n.AccountManager().AddBackend(keystore.NewKeyStore(keydir, scryptN, scryptP)) + ks := n.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + + for _, pk := range privateKeys { + act, err := ks.ImportECDSA(pk, "foobar") + if err != nil { + n.Close() + return nil, nil, err + } + err = ks.Unlock(act, "foobar") + if err != nil { + n.Close() + return nil, nil, err + } + } + + backend, err := eth.New(n, ethCfg) + if err != nil { + n.Close() + return nil, nil, err + + } + // Enable catalyst if l2 + if l2 { + if err := catalyst.Register(n, backend); err != nil { + n.Close() + return nil, nil, err + } + } + return n, backend, nil + +} + +func l1Geth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { + wallet, err := hdwallet.NewFromMnemonic(cfg.mnemonic) + if err != nil { + return nil, nil, err + } + + signer := deriveAccount(wallet, cfg.cliqueSigners[0]) + pk, _ := wallet.PrivateKey(signer) + + return createGethNode(false, cfg.l1.nodeConfig, cfg.l1.ethConfig, []*ecdsa.PrivateKey{pk}) +} + +func l2Geth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { + return createGethNode(true, cfg.l2.nodeConfig, cfg.l2.ethConfig, []*ecdsa.PrivateKey{}) +} diff --git a/opnode/test/setup.go b/opnode/test/setup.go new file mode 100644 index 000000000000..514fa224c5dc --- /dev/null +++ b/opnode/test/setup.go @@ -0,0 +1,161 @@ +package test + +import ( + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" + + hdwallet "github.com/miguelmota/go-ethereum-hdwallet" +) + +// TODO: Make sure these stay up to date +var depositContractByteCode = "0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea2646970667358221220267a1955ffafb2cf1004819eb2b511ad2922e2ca0436708e171243ac92ac637e64736f6c634300080b0033" +var l1InfoContractByteCode = "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220ef072e1b541577d5392b0cc2b83515eee307c6b7483589377f51e691ef42552e64736f6c634300080b0033" + +// deriveAddress returns the address associated derivation path for the wallet. +// It will panic if the derivation path is not correctly formatted. +func deriveAddress(w accounts.Wallet, path string) common.Address { + return deriveAccount(w, path).Address +} + +// deriveAccount returns the account associated derivation path for the wallet. +// It will panic if the derivation path is not correctly formatted. +func deriveAccount(w accounts.Wallet, path string) accounts.Account { + derivPath := hdwallet.MustParseDerivationPath(path) + account, err := w.Derive(derivPath, false) + if err != nil { + panic(err) + } + return account +} + +// gethConfig is configuration for either and L1 or L2 geth node +type gethConfig struct { + nodeConfig *node.Config + ethConfig *ethconfig.Config +} + +// systemConfig holds the information necessary to create a L1 <-> Rollup <-> L2 system +type systemConfig struct { + mnemonic string + l1 gethConfig + l2 gethConfig + premine map[string]int // Derivation path -> amount in ETH (not wei) + cliqueSigners []string // derivation path + depositContractAddress string + l1InforPredeployAddress string +} + +func precompileAlloc() core.GenesisAlloc { + alloc := make(map[common.Address]core.GenesisAccount) + var addr [common.AddressLength]byte + for i := 0; i < 256; i++ { + addr[common.AddressLength-1] = byte(i) + alloc[addr] = core.GenesisAccount{Balance: common.Big1} + } + return alloc +} + +func cliqueExtraData(w accounts.Wallet, signers []string) []byte { + // 32 Empty bytes + ret := make([]byte, 32) + // Signer addresses + for _, signer := range signers { + address := deriveAddress(w, signer) + // Was not able to automatically do this + for i := 0; i < len(address); i++ { + ret = append(ret, address[i]) + } + } + // 65 Empty bytes + t := make([]byte, 65) + return append(ret, t...) +} + +// initializeGenesis creates a L1 and L2 genesis from the config and places them in l1 and l2 configurations +func initializeGenesis(cfg *systemConfig) { + wallet, err := hdwallet.NewFromMnemonic(cfg.mnemonic) + if err != nil { + panic(fmt.Errorf("Failed to create wallet: %w", err)) + } + + eth := new(big.Int) + eth = eth.Exp(big.NewInt(10), big.NewInt(10), nil) + + l1Alloc := precompileAlloc() + l2Alloc := precompileAlloc() + + for path, amt := range cfg.premine { + balance := big.NewInt(int64(amt)) + balance.Mul(balance, eth) + addr := deriveAddress(wallet, path) + l1Alloc[addr] = core.GenesisAccount{Balance: balance} + l2Alloc[addr] = core.GenesisAccount{Balance: balance} + } + + l1Alloc[common.HexToAddress(cfg.depositContractAddress)] = core.GenesisAccount{Code: common.FromHex(depositContractByteCode), Balance: common.Big0} + l2Alloc[common.HexToAddress(cfg.l1InforPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1InfoContractByteCode), Balance: common.Big0} + + genesisTimestamp := uint64(time.Now().Unix()) + + l1Genesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: new(big.Int).SetUint64((cfg.l1.ethConfig.NetworkId)), + HomesteadBlock: common.Big0, + EIP150Block: common.Big0, + EIP155Block: common.Big0, + EIP158Block: common.Big0, + ByzantiumBlock: common.Big0, + ConstantinopleBlock: common.Big0, + PetersburgBlock: common.Big0, + IstanbulBlock: common.Big0, + BerlinBlock: common.Big0, + LondonBlock: common.Big0, + Clique: ¶ms.CliqueConfig{ + Period: 1, + Epoch: 30000, + }, + }, + Alloc: l1Alloc, + Difficulty: common.Big1, + ExtraData: cliqueExtraData(wallet, cfg.cliqueSigners), + GasLimit: 5000000, + Nonce: 4660, + Timestamp: genesisTimestamp, + BaseFee: big.NewInt(7), + } + l2Genesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: new(big.Int).SetUint64((cfg.l2.ethConfig.NetworkId)), + HomesteadBlock: common.Big0, + EIP150Block: common.Big0, + EIP155Block: common.Big0, + EIP158Block: common.Big0, + ByzantiumBlock: common.Big0, + ConstantinopleBlock: common.Big0, + PetersburgBlock: common.Big0, + IstanbulBlock: common.Big0, + BerlinBlock: common.Big0, + LondonBlock: common.Big0, + MergeForkBlock: common.Big0, + TerminalTotalDifficulty: common.Big0, + }, + Alloc: l2Alloc, + Difficulty: common.Big1, + GasLimit: 5000000, + Nonce: 4660, + Timestamp: genesisTimestamp, + BaseFee: big.NewInt(7), + } + + cfg.l1.ethConfig.Genesis = l1Genesis + cfg.l2.ethConfig.Genesis = l2Genesis + +} diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go new file mode 100644 index 000000000000..a8ce9614961c --- /dev/null +++ b/opnode/test/system_test.go @@ -0,0 +1,230 @@ +package test + +import ( + "context" + "fmt" + "math/big" + "testing" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" + rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" + + "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/core/types" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/node" +) + +func getGenesisHash(client *ethclient.Client) common.Hash { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + block, err := client.BlockByNumber(ctx, common.Big0) + if err != nil { + panic(err) + } + return block.Hash() +} + +func endpoint(cfg *node.Config) string { + return fmt.Sprintf("ws://%v", cfg.WSEndpoint()) +} + +// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. +// All nodes are run in process (but are the full nodes, not mocked or stubbed). +func TestSystemE2E(t *testing.T) { + // System Config + cfg := &systemConfig{ + mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness", + l1: gethConfig{ + nodeConfig: &node.Config{ + Name: "l1geth", + WSHost: "127.0.0.1", + WSPort: 9090, + }, + ethConfig: ðconfig.Config{ + NetworkId: 900, + }, + }, + l2: gethConfig{ + nodeConfig: &node.Config{ + Name: "l2geth", + DataDir: "", + IPCPath: "", + WSHost: "127.0.0.1", + WSPort: 9091, + }, + ethConfig: ðconfig.Config{ + NetworkId: 901, + }, + }, + premine: map[string]int{ + "m/44'/60'/0'/0/0": 10000000, + "m/44'/60'/0'/0/1": 10000000, + "m/44'/60'/0'/0/2": 10000000, + }, + cliqueSigners: []string{"m/44'/60'/0'/0/0"}, + depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", + l1InforPredeployAddress: "0x4242424242424242424242424242424242424242", + } + // Create genesis & assign it to ethconfigs + initializeGenesis(cfg) + + // Start L1 + l1Node, l1Backend, err := l1Geth(cfg) + if err != nil { + t.Fatal(err) + } + defer l1Node.Close() + err = l1Node.Start() + if err != nil { + t.Fatal(err) + } + err = l1Backend.StartMining(1) + if err != nil { + t.Fatal(err) + } + l1Client, err := ethclient.Dial(endpoint(cfg.l1.nodeConfig)) + if err != nil { + t.Fatal(err) + } + l1GenesisHash := getGenesisHash(l1Client) + + // Start L2 + l2Node, _, err := l2Geth(cfg) + if err != nil { + t.Fatal(err) + } + defer l2Node.Close() + err = l2Node.Start() + if err != nil { + t.Fatal(err) + } + l2Client, err := ethclient.Dial(endpoint(cfg.l2.nodeConfig)) + if err != nil { + t.Fatal(err) + } + l2GenesisHash := getGenesisHash(l2Client) + + // Rollup Node + node := rollupNode.OpNodeCmd{ + Genesis: rollupNode.GenesisConf{ + L2Hash: l2GenesisHash, + L1Hash: l1GenesisHash, + L1Num: 0, + }, + LogCmd: rollupNode.LogCmd{ + LogLvl: "warn", + Color: true, + Format: "text", + }, + L1NodeAddrs: []string{endpoint(cfg.l1.nodeConfig)}, + L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, + } + err = node.Run(context.Background()) + defer node.Close() + if err != nil { + t.Fatal(err) + } + + // Send Transaction & wait for success + contractAddr := common.HexToAddress(cfg.depositContractAddress) + fromAddr := common.HexToAddress("0x30ec912c5b1d14aa6d1cb9aa7a6682415c4f7eb0") + + // start balance + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + startBalance, err := l2Client.BalanceAt(ctx, fromAddr, nil) + if err != nil { + t.Fatal(err) + } + + // Contract + depositContract, err := deposit.NewDeposit(contractAddr, l1Client) + if err != nil { + t.Fatal(err) + } + + // Signer + ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], big.NewInt(int64(cfg.l1.ethConfig.NetworkId))) + if err != nil { + t.Fatal(err) + } + + // Setup for L1 Confirmation + watchChan := make(chan *deposit.DepositTransactionDeposited) + watcher, err := depositContract.WatchTransactionDeposited(&bind.WatchOpts{}, watchChan, []common.Address{fromAddr}, []common.Address{fromAddr}) + if err != nil { + t.Fatalf("with watcher: %v", err) + } + defer watcher.Unsubscribe() + + // Setup for L2 Confirmation + headChan := make(chan *types.Header, 100) + l2HeadSub, err := l2Client.SubscribeNewHead(context.Background(), headChan) + if err != nil { + t.Fatalf("with l2 head sub: %v", err) + } + defer l2HeadSub.Unsubscribe() + + // Finally send TX + mintAmount := big.NewInt(1_000_000_000_000) + tx, err := depositContract.DepositTransaction(opts, fromAddr, mintAmount, big.NewInt(1_000_000), false, nil) + if err != nil { + t.Fatalf("with deposit txt: %v", err) + } + + // Wait for tx to be mined on L1 (or timeout) + select { + case <-watchChan: + // continue + case err := <-watcher.Err(): + t.Fatalf("Failed on watcher channel: %v", err) + case <-time.After(5 * time.Second): + t.Fatal("Timeout waiting for L1 tx to succeed") + + } + + // Get the L1 Block of the tx + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + receipt, err := l1Client.TransactionReceipt(ctx, tx.Hash()) + if err != nil { + t.Fatalf("Could not get tranaction receipt: %v", err) + } + + // Wait (or timeout) for that block to show up on L2 + timeoutCh := time.After(3 * time.Second) +loop: + for { + select { + case head := <-headChan: + if head.Number.Cmp(receipt.BlockNumber) >= 0 { + break loop + } + case err := <-l2HeadSub.Err(): + t.Fatalf("Error in l2 head subscription: %v", err) + case <-timeoutCh: + t.Fatal("Timeout waiting for l2 head") + } + } + + // Confirm balance + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + endBalance, err := l2Client.BalanceAt(ctx, fromAddr, nil) + if err != nil { + t.Fatal(err) + } + + diff := new(big.Int) + diff = diff.Sub(endBalance, startBalance) + if diff.Cmp(mintAmount) != 0 { + t.Fatalf("Did not get expected balance change. start: %v, end: %v, mint: %v", startBalance, endBalance, mintAmount) + } + +} From 518ebe44739c85e4eb2258705b399e08d5bd499b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 25 Jan 2022 16:33:09 -0800 Subject: [PATCH 191/585] ref impl: Generate contract bindings --- opnode/contracts/doc.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 opnode/contracts/doc.go diff --git a/opnode/contracts/doc.go b/opnode/contracts/doc.go new file mode 100644 index 000000000000..d8a255b530f4 --- /dev/null +++ b/opnode/contracts/doc.go @@ -0,0 +1,14 @@ +/* + +The contracts package provides Go bindings for our contracts. + + +The bindings are generated with `abigen`. `jq` is required to parse out the ABI section +from the hardhat artifacts. + +*/ + +package contracts + +//go:generate sh -c "jq .abi ../../packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | abigen --pkg deposit --out deposit/deposit_feed_raw.go --abi -" +//go:generate sh -c "jq .abi ../../packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | abigen --pkg l1block --out l1block/l1_block_info_raw.go --abi -" From 2df2fab25e07da9d2063afb1ed4977af3dfdf074 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 26 Jan 2022 10:09:50 -0800 Subject: [PATCH 192/585] ref impl: Slow down L1 block speed during the test --- opnode/test/setup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 514fa224c5dc..126b5576c26d 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -119,7 +119,7 @@ func initializeGenesis(cfg *systemConfig) { BerlinBlock: common.Big0, LondonBlock: common.Big0, Clique: ¶ms.CliqueConfig{ - Period: 1, + Period: 2, Epoch: 30000, }, }, From b498f5359d4e8d50e2870da27ca383d59cbf96af Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 26 Jan 2022 11:48:43 -0800 Subject: [PATCH 193/585] ref impl: Use make to generate contract bindings This allows more complex setups to be ran than with go generate. --- opnode/contracts/Makefile | 45 ++++++++ opnode/contracts/abis/DepositFeed.json | 92 ++++++++++++++++ opnode/contracts/abis/L1Block.json | 103 ++++++++++++++++++ opnode/contracts/deposit/deposit_feed_raw.go | 22 ++++ opnode/contracts/doc.go | 8 +- opnode/contracts/l1block/l1_block_info_raw.go | 22 ++++ 6 files changed, 286 insertions(+), 6 deletions(-) create mode 100644 opnode/contracts/Makefile create mode 100644 opnode/contracts/abis/DepositFeed.json create mode 100644 opnode/contracts/abis/L1Block.json diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile new file mode 100644 index 000000000000..6a9bbab02f7b --- /dev/null +++ b/opnode/contracts/Makefile @@ -0,0 +1,45 @@ +SHELL := /bin/bash + + +CONTRACTS_PATH := "../../packages/contracts/artifacts/contracts" + + + +binding: abi + $(eval temp := $(shell mktemp)) + + cat abis/DepositFeed.json \ + | jq -r .bytecode > $(temp) + + cat abis/DepositFeed.json \ + | jq .abi \ + | abigen --pkg deposit \ + --abi - \ + --out deposit/deposit_feed_raw.go \ + --type deposit \ + --bin $(temp) + + rm $(temp) + + $(eval temp := $(shell mktemp)) + + cat abis/L1Block.json \ + | jq -r .bytecode > $(temp) + + cat abis/L1Block.json \ + | jq .abi \ + | abigen --pkg l1block \ + --abi - \ + --out l1block/l1_block_info_raw.go \ + --type l1block \ + --bin $(temp) + + rm $(temp) + +abi: + cat $(CONTRACTS_PATH)/L1/DepositFeed.sol/DepositFeed.json \ + | jq '{abi,bytecode}' \ + > abis/DepositFeed.json + cat $(CONTRACTS_PATH)/L2/L1Block.sol/L1Block.json \ + | jq '{abi,bytecode}' \ + > abis/L1Block.json \ No newline at end of file diff --git a/opnode/contracts/abis/DepositFeed.json b/opnode/contracts/abis/DepositFeed.json new file mode 100644 index 000000000000..d8f38e6b47ed --- /dev/null +++ b/opnode/contracts/abis/DepositFeed.json @@ -0,0 +1,92 @@ +{ + "abi": [ + { + "inputs": [], + "name": "NonZeroCreationTarget", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mint", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isCreation", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "TransactionDeposited", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_isCreation", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "depositTransaction", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b5061056a806100206000396000f3fe60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" +} diff --git a/opnode/contracts/abis/L1Block.json b/opnode/contracts/abis/L1Block.json new file mode 100644 index 000000000000..8c48c0eb72ea --- /dev/null +++ b/opnode/contracts/abis/L1Block.json @@ -0,0 +1,103 @@ +{ + "abi": [ + { + "inputs": [], + "name": "OnlyDepositor", + "type": "error" + }, + { + "inputs": [], + "name": "DEPOSITOR_ACCOUNT", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "basefee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "number", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_basefee", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_hash", + "type": "bytes32" + } + ], + "name": "setL1BlockValues", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "timestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033" +} diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/opnode/contracts/deposit/deposit_feed_raw.go index c6a34dd23863..076a59adca75 100644 --- a/opnode/contracts/deposit/deposit_feed_raw.go +++ b/opnode/contracts/deposit/deposit_feed_raw.go @@ -31,12 +31,34 @@ var ( // DepositMetaData contains all meta data concerning the Deposit contract. var DepositMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061056a806100206000396000f3fe60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033", } // DepositABI is the input ABI used to generate the binding from. // Deprecated: Use DepositMetaData.ABI instead. var DepositABI = DepositMetaData.ABI +// DepositBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use DepositMetaData.Bin instead. +var DepositBin = DepositMetaData.Bin + +// DeployDeposit deploys a new Ethereum contract, binding an instance of Deposit to it. +func DeployDeposit(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Deposit, error) { + parsed, err := DepositMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(DepositBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Deposit{DepositCaller: DepositCaller{contract: contract}, DepositTransactor: DepositTransactor{contract: contract}, DepositFilterer: DepositFilterer{contract: contract}}, nil +} + // Deposit is an auto generated Go binding around an Ethereum contract. type Deposit struct { DepositCaller // Read-only binding to the contract diff --git a/opnode/contracts/doc.go b/opnode/contracts/doc.go index d8a255b530f4..015f3d8b65e9 100644 --- a/opnode/contracts/doc.go +++ b/opnode/contracts/doc.go @@ -3,12 +3,8 @@ The contracts package provides Go bindings for our contracts. -The bindings are generated with `abigen`. `jq` is required to parse out the ABI section -from the hardhat artifacts. - +To regenerate the bindings, run `make` +The following programs are required: `jq`, `abigen`, and having run `yarn build` in the contracts directory. */ package contracts - -//go:generate sh -c "jq .abi ../../packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | abigen --pkg deposit --out deposit/deposit_feed_raw.go --abi -" -//go:generate sh -c "jq .abi ../../packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | abigen --pkg l1block --out l1block/l1_block_info_raw.go --abi -" diff --git a/opnode/contracts/l1block/l1_block_info_raw.go b/opnode/contracts/l1block/l1_block_info_raw.go index d1151840b516..6653114f45bd 100644 --- a/opnode/contracts/l1block/l1_block_info_raw.go +++ b/opnode/contracts/l1block/l1_block_info_raw.go @@ -31,12 +31,34 @@ var ( // L1blockMetaData contains all meta data concerning the L1block contract. var L1blockMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033", } // L1blockABI is the input ABI used to generate the binding from. // Deprecated: Use L1blockMetaData.ABI instead. var L1blockABI = L1blockMetaData.ABI +// L1blockBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use L1blockMetaData.Bin instead. +var L1blockBin = L1blockMetaData.Bin + +// DeployL1block deploys a new Ethereum contract, binding an instance of L1block to it. +func DeployL1block(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *L1block, error) { + parsed, err := L1blockMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L1blockBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &L1block{L1blockCaller: L1blockCaller{contract: contract}, L1blockTransactor: L1blockTransactor{contract: contract}, L1blockFilterer: L1blockFilterer{contract: contract}}, nil +} + // L1block is an auto generated Go binding around an Ethereum contract. type L1block struct { L1blockCaller // Read-only binding to the contract From 90fa7768ee2d540dd6f3b25f83bda3d453d8abed Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 26 Jan 2022 11:50:35 -0800 Subject: [PATCH 194/585] ref impl: Use auto-generated bytecode This removes the hardcoded bytecode for dealing with the deposit and L1 block info contracts. --- opnode/test/setup.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 126b5576c26d..cb2e3f6882cf 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -5,6 +5,8 @@ import ( "math/big" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -15,10 +17,6 @@ import ( hdwallet "github.com/miguelmota/go-ethereum-hdwallet" ) -// TODO: Make sure these stay up to date -var depositContractByteCode = "0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea2646970667358221220267a1955ffafb2cf1004819eb2b511ad2922e2ca0436708e171243ac92ac637e64736f6c634300080b0033" -var l1InfoContractByteCode = "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220ef072e1b541577d5392b0cc2b83515eee307c6b7483589377f51e691ef42552e64736f6c634300080b0033" - // deriveAddress returns the address associated derivation path for the wallet. // It will panic if the derivation path is not correctly formatted. func deriveAddress(w accounts.Wallet, path string) common.Address { @@ -100,8 +98,8 @@ func initializeGenesis(cfg *systemConfig) { l2Alloc[addr] = core.GenesisAccount{Balance: balance} } - l1Alloc[common.HexToAddress(cfg.depositContractAddress)] = core.GenesisAccount{Code: common.FromHex(depositContractByteCode), Balance: common.Big0} - l2Alloc[common.HexToAddress(cfg.l1InforPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1InfoContractByteCode), Balance: common.Big0} + l1Alloc[common.HexToAddress(cfg.depositContractAddress)] = core.GenesisAccount{Code: common.FromHex(deposit.DepositBin), Balance: common.Big0} + l2Alloc[common.HexToAddress(cfg.l1InforPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockBin), Balance: common.Big0} genesisTimestamp := uint64(time.Now().Unix()) From 73ae913c8554b9fcd54031f5530cbd25dc1d3298 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 26 Jan 2022 12:09:41 -0800 Subject: [PATCH 195/585] ref impl: Increase L1 timeout to match block time Well, it's slightly higher than the block time, but it needs to be increased with the block time increase. --- opnode/test/system_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index a8ce9614961c..34c6e4ca5a6e 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -190,7 +190,7 @@ func TestSystemE2E(t *testing.T) { } // Get the L1 Block of the tx - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second) defer cancel() receipt, err := l1Client.TransactionReceipt(ctx, tx.Hash()) if err != nil { From 340b52d6f5709ba384ab390b39d00a78eeba9afa Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 26 Jan 2022 15:15:29 -0800 Subject: [PATCH 196/585] ref impl: Save deployed bytecode The deployed bytecode is different than the bytecode in that it is the result of running the bytecode as a transaction and is saved in the code storage. The deployed bytecode is used to enable contracts to be initialized at genesis to pre-determined addresses. --- opnode/contracts/Makefile | 18 ++++++++++++++++-- opnode/contracts/abis/DepositFeed.json | 3 ++- opnode/contracts/abis/L1Block.json | 3 ++- .../contracts/deposit/deposit_feed_deployed.go | 5 +++++ .../l1block/l1_block_info_deployed.go | 5 +++++ 5 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 opnode/contracts/deposit/deposit_feed_deployed.go create mode 100644 opnode/contracts/l1block/l1_block_info_deployed.go diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index 6a9bbab02f7b..31380a19718c 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -19,6 +19,13 @@ binding: abi --type deposit \ --bin $(temp) + $(eval deployedBytecode := $(shell cat abis/DepositFeed.json | jq -r .deployedBytecode)) + echo "// Code generated - DO NOT EDIT." > deposit/deposit_feed_deployed.go + echo "// This file is a generated binding and any manual changes will be lost." >> deposit/deposit_feed_deployed.go + echo "package deposit" >> deposit/deposit_feed_deployed.go + echo "var DepositDeployedBin = \"$(deployedBytecode)\"" >> deposit/deposit_feed_deployed.go + gofmt -s -w deposit/deposit_feed_deployed.go + rm $(temp) $(eval temp := $(shell mktemp)) @@ -34,12 +41,19 @@ binding: abi --type l1block \ --bin $(temp) + $(eval deployedBytecode := $(shell cat abis/L1Block.json | jq -r .deployedBytecode)) + echo "// Code generated - DO NOT EDIT." > l1block/l1_block_info_deployed.go + echo "// This file is a generated binding and any manual changes will be lost." >> l1block/l1_block_info_deployed.go + echo "package l1block" >> l1block/l1_block_info_deployed.go + echo "var L1blockDeployedBin = \"$(deployedBytecode)\"" >> l1block/l1_block_info_deployed.go + gofmt -s -w l1block/l1_block_info_deployed.go + rm $(temp) abi: cat $(CONTRACTS_PATH)/L1/DepositFeed.sol/DepositFeed.json \ - | jq '{abi,bytecode}' \ + | jq '{abi,bytecode,deployedBytecode}' \ > abis/DepositFeed.json cat $(CONTRACTS_PATH)/L2/L1Block.sol/L1Block.json \ - | jq '{abi,bytecode}' \ + | jq '{abi,bytecode,deployedBytecode}' \ > abis/L1Block.json \ No newline at end of file diff --git a/opnode/contracts/abis/DepositFeed.json b/opnode/contracts/abis/DepositFeed.json index d8f38e6b47ed..8208be7f61fc 100644 --- a/opnode/contracts/abis/DepositFeed.json +++ b/opnode/contracts/abis/DepositFeed.json @@ -88,5 +88,6 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b5061056a806100206000396000f3fe60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" + "bytecode": "0x608060405234801561001057600080fd5b5061056a806100206000396000f3fe60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033", + "deployedBytecode": "0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" } diff --git a/opnode/contracts/abis/L1Block.json b/opnode/contracts/abis/L1Block.json index 8c48c0eb72ea..9460fc2c628b 100644 --- a/opnode/contracts/abis/L1Block.json +++ b/opnode/contracts/abis/L1Block.json @@ -99,5 +99,6 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033" + "bytecode": "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033" } diff --git a/opnode/contracts/deposit/deposit_feed_deployed.go b/opnode/contracts/deposit/deposit_feed_deployed.go new file mode 100644 index 000000000000..61f7cf8246bf --- /dev/null +++ b/opnode/contracts/deposit/deposit_feed_deployed.go @@ -0,0 +1,5 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. +package deposit + +var DepositDeployedBin = "0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" diff --git a/opnode/contracts/l1block/l1_block_info_deployed.go b/opnode/contracts/l1block/l1_block_info_deployed.go new file mode 100644 index 000000000000..32b797d19171 --- /dev/null +++ b/opnode/contracts/l1block/l1_block_info_deployed.go @@ -0,0 +1,5 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. +package l1block + +var L1blockDeployedBin = "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033" From 4f1b73e15009586d738727d90bdcc64a619f4a21 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 26 Jan 2022 15:18:39 -0800 Subject: [PATCH 197/585] ref impl: Use deployed bytecode in e2e test --- opnode/test/setup.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index cb2e3f6882cf..c94474eeb071 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -98,8 +98,8 @@ func initializeGenesis(cfg *systemConfig) { l2Alloc[addr] = core.GenesisAccount{Balance: balance} } - l1Alloc[common.HexToAddress(cfg.depositContractAddress)] = core.GenesisAccount{Code: common.FromHex(deposit.DepositBin), Balance: common.Big0} - l2Alloc[common.HexToAddress(cfg.l1InforPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockBin), Balance: common.Big0} + l1Alloc[common.HexToAddress(cfg.depositContractAddress)] = core.GenesisAccount{Code: common.FromHex(deposit.DepositDeployedBin), Balance: common.Big0} + l2Alloc[common.HexToAddress(cfg.l1InforPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} genesisTimestamp := uint64(time.Now().Unix()) From 6265b9983671c8dc0014cf3b0806f7151cea325a Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Thu, 27 Jan 2022 17:33:07 +0100 Subject: [PATCH 198/585] add instructions for running go tests --- opnode/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opnode/README.md b/opnode/README.md index d93e12510d03..309c99ce512c 100644 --- a/opnode/README.md +++ b/opnode/README.md @@ -4,8 +4,11 @@ This is the reference implementation of the [rollup-node spec](../specs/rollup-n ## Compiling +From the repository root: + ```shell go build -o op ./opnode/cmd +go test ./opnode/... ``` ## Running From 4500ed5c08dd575cc5c00cc421a6160db5e8932b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 27 Jan 2022 08:59:24 -0800 Subject: [PATCH 199/585] ref impl: Small cleanups --- opnode/contracts/Makefile | 5 +---- opnode/test/geth.go | 5 +++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index 31380a19718c..ed6700cd96a6 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -1,10 +1,7 @@ SHELL := /bin/bash - CONTRACTS_PATH := "../../packages/contracts/artifacts/contracts" - - binding: abi $(eval temp := $(shell mktemp)) @@ -56,4 +53,4 @@ abi: > abis/DepositFeed.json cat $(CONTRACTS_PATH)/L2/L1Block.sol/L1Block.json \ | jq '{abi,bytecode,deployedBytecode}' \ - > abis/L1Block.json \ No newline at end of file + > abis/L1Block.json diff --git a/opnode/test/geth.go b/opnode/test/geth.go index 223b1d901893..822c3f6f81b0 100644 --- a/opnode/test/geth.go +++ b/opnode/test/geth.go @@ -30,13 +30,14 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri 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, "foobar") + act, err := ks.ImportECDSA(pk, password) if err != nil { n.Close() return nil, nil, err } - err = ks.Unlock(act, "foobar") + err = ks.Unlock(act, password) if err != nil { n.Close() return nil, nil, err From 310ff922df375c8006b3c571df4d7a4c7ce82be4 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Fri, 28 Jan 2022 01:11:38 +0100 Subject: [PATCH 200/585] terminology quickfix Co-authored-by: Maurelian --- specs/deposits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index 6c375535bb09..e57c48947c3c 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -155,7 +155,7 @@ The L1 attributes deposit transaction involves two special purpose accounts: The depositor account is an [EOA][g-eoa] with no known private key. It has the address `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value is returned by the `CALLER` and `ORIGIN` -opcodes during execution of the L1 attributes deposit transaction. +opcodes during execution of the L1 attributes deposited transaction. ### L1 Attributes Predeployed Contract From 04309c99d6514c96a4380717cca43f2364f2d2af Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 28 Jan 2022 01:16:50 +0100 Subject: [PATCH 201/585] add precisions regarding the re-org past genesis scenario --- specs/rollup-node.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 41a817e61ab8..b9f8ad294ea4 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -298,7 +298,8 @@ This re-derivation starting point can be found by applying the following algorit - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the process. - Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that - requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration). + requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis + configuration) (\*) - Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this algorithm from step 2. - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. @@ -308,4 +309,8 @@ This re-derivation starting point can be found by applying the following algorit Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, approximately 12 minutes). +(\*) Post-merge, this is only possible for 12 minutes. In practice, we'll pick an already-finalized L1 block as L2 +inception point to preclude the possibility of a re-org past genesis, at the cost of a few empty blocks at the start of +the L2 chain. + [merge]: https://ethereum.org/en/eth2/merge/ From 59c9554084e9294bb0690000884ec760c3038bba Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 28 Jan 2022 22:38:55 +0100 Subject: [PATCH 202/585] Document release process --- meta/README.md | 2 ++ meta/releases.md | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 meta/releases.md diff --git a/meta/README.md b/meta/README.md index 5329ee3c3b65..4422908123a4 100644 --- a/meta/README.md +++ b/meta/README.md @@ -4,3 +4,5 @@ This directory describes processes that we use to build the specification. - [Linting](linting.md): how to lint source files. - [Markdown Style Guide](markdown-style.md): how to format and structure Markdown files. +- [Release process](releases.md): how to create releases. + diff --git a/meta/releases.md b/meta/releases.md new file mode 100644 index 000000000000..53bff5b3a9c5 --- /dev/null +++ b/meta/releases.md @@ -0,0 +1,35 @@ +# Release process + +1. Confirm all release features are completed +2. Run tests and verify build outputs + ```shell + # 2.0: Verify linting + yarn + yarn lint + yarn lint:links + + # 2.1: Confirm contracts pass tests and compile + cd packages/contracts + yarn + yarn build + yarn test + cd ../.. + + # 2.2: Confirm contract bindings are up-to-date + cd opnode/contracts + make abi + make binding + cd ../.. + + # 2.3: Run Go tests (including end-to-end tests) + go test -v ../.. + ``` +3. Sign an annotated release tag (make sure to prefix with `v` and follow [semantic versioning](https://semver.org/)) + ```shell + # Opens editor for annotating the tag, give it a release title + git tag -s -a v0.1.0 + # Push the tag + git push origin v0.1.0 + ``` +4. Create a release on GitHub with the tag, provide a description of features and usage + From 2338a62aca2cf62bb3df47ea9394d27b74862e15 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Sat, 29 Jan 2022 02:10:22 +0100 Subject: [PATCH 203/585] add syntax highlighting to pseudocode I forgot to do this when updating the rollup node spec PR. --- specs/rollup-node.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index b9f8ad294ea4..38a91681c27c 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -150,20 +150,20 @@ Let Then we can apply the following pseudocode logic to update the state of both the rollup driver and execution engine: -```pseudocode +```javascript // request a new execution payload forkChoiceState = { headBlockHash: refL2, safeBlockHash: refL2, finalizedBlockHash: l2BlockHashAt(l2Number(refL2) - FINALIZATION_DELAY_BLOCKS) } -(status, payloadID) = engine_forkchoiceUpdatedV1(forkChoiceState, payloadAttributes) +[status, payloadID] = engine_forkchoiceUpdatedV1(forkChoiceState, payloadAttributes) if (status != "SUCCESS") error() // retrieve and execute the execution payload -(executionPayload, error) = engine_getPayloadV1(payloadID) +[executionPayload, error] = engine_getPayloadV1(payloadID) if (error != null) error() -(status, latestValidHash, validationError) = engine_executePayloadV1(executionPayload) +[status, latestValidHash, validationError] = engine_executePayloadV1(executionPayload) if (status != "VALID" || validationError != null) error() refL2 = latestValidHash @@ -175,7 +175,7 @@ forkChoiceState = { safeBlockHash: refL2, finalizedBlockHash: l2BlockHashAt(l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS) } -(status, payloadID) = engine_forkchoiceUpdatedV1(refL2, null) +[status, payloadID] = engine_forkchoiceUpdatedV1(refL2, null) if (status != "SUCCESS") error() ``` From c5a52a50f957bfa67778d253b2e812f627c7ae37 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Feb 2022 12:38:16 -0800 Subject: [PATCH 204/585] Move most of the l2 package to rollup This is the start of the package cleanup. The L1 and L2 packages are for connecting to the L1 and L2 nodes while the rollup package depends on the L1/L2 packages and drives the rollup. --- opnode/node/node.go | 15 ++++++------- opnode/{l2 => rollup}/driver.go | 2 +- opnode/{l2 => rollup}/driver_loop.go | 2 +- opnode/{l2 => rollup}/driver_state.go | 2 +- opnode/{l2 => rollup}/driver_state_test.go | 2 +- opnode/{l2 => rollup}/driver_step.go | 21 ++++++++++--------- opnode/{l2 => rollup}/input_derivation.go | 13 ++++++------ .../{l2 => rollup}/input_derivation_test.go | 2 +- opnode/{l2 => rollup}/output_derivation.go | 13 ++++++------ opnode/{l2 => rollup}/reading.go | 2 +- opnode/{l2 => rollup}/reading_test.go | 2 +- opnode/{l2 => rollup}/sync_reference.go | 2 +- opnode/{l2 => rollup}/sync_start.go | 2 +- opnode/{l2 => rollup}/sync_start_test.go | 2 +- 14 files changed, 43 insertions(+), 39 deletions(-) rename opnode/{l2 => rollup}/driver.go (99%) rename opnode/{l2 => rollup}/driver_loop.go (99%) rename opnode/{l2 => rollup}/driver_state.go (99%) rename opnode/{l2 => rollup}/driver_state_test.go (99%) rename opnode/{l2 => rollup}/driver_step.go (90%) rename opnode/{l2 => rollup}/input_derivation.go (95%) rename opnode/{l2 => rollup}/input_derivation_test.go (99%) rename opnode/{l2 => rollup}/output_derivation.go (67%) rename opnode/{l2 => rollup}/reading.go (99%) rename opnode/{l2 => rollup}/reading_test.go (99%) rename opnode/{l2 => rollup}/sync_reference.go (99%) rename opnode/{l2 => rollup}/sync_start.go (99%) rename opnode/{l2 => rollup}/sync_start_test.go (99%) diff --git a/opnode/node/node.go b/opnode/node/node.go index 43d108b5f664..65e159079f3c 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -9,9 +9,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" @@ -27,8 +28,8 @@ type GenesisConf struct { L1Num uint64 `ask:"--l1-num" help:"Block number of L1 matching the l1-hash"` } -func (conf *GenesisConf) GetGenesis() l2.Genesis { - return l2.Genesis{ +func (conf *GenesisConf) GetGenesis() rollup.Genesis { + return rollup.Genesis{ L1: eth.BlockID{Hash: conf.L1Hash, Number: conf.L1Num}, // TODO: if we start from a squashed snapshot we might have a non-zero L2 genesis number L2: eth.BlockID{Hash: conf.L2Hash, Number: 0}, @@ -53,7 +54,7 @@ type OpNodeCmd struct { l1Source eth.L1Source // engines to keep synced - l2Engines []*l2.EngineDriver + l2Engines []*rollup.EngineDriver l1Downloader l1.Downloader @@ -122,15 +123,15 @@ func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { EthBackend: ethclient.NewClient(backend), Log: c.log.New("engine_client", i), } - engine := &l2.EngineDriver{ + engine := &rollup.EngineDriver{ Log: c.log.New("engine", i), RPC: client, DL: c.l1Downloader, - SyncRef: l2.SyncSource{ + SyncRef: rollup.SyncSource{ L1: l1CanonicalChain, L2: client, }, - EngineDriverState: l2.EngineDriverState{Genesis: genesis}, + EngineDriverState: rollup.EngineDriverState{Genesis: genesis}, } c.l2Engines = append(c.l2Engines, engine) } diff --git a/opnode/l2/driver.go b/opnode/rollup/driver.go similarity index 99% rename from opnode/l2/driver.go rename to opnode/rollup/driver.go index d6ed5ea8ef57..527384d21ccb 100644 --- a/opnode/l2/driver.go +++ b/opnode/rollup/driver.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" diff --git a/opnode/l2/driver_loop.go b/opnode/rollup/driver_loop.go similarity index 99% rename from opnode/l2/driver_loop.go rename to opnode/rollup/driver_loop.go index 3dd4b46a3c8c..1b1881cddff2 100644 --- a/opnode/l2/driver_loop.go +++ b/opnode/rollup/driver_loop.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" diff --git a/opnode/l2/driver_state.go b/opnode/rollup/driver_state.go similarity index 99% rename from opnode/l2/driver_state.go rename to opnode/rollup/driver_state.go index 35c511838da2..38d18be36591 100644 --- a/opnode/l2/driver_state.go +++ b/opnode/rollup/driver_state.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" diff --git a/opnode/l2/driver_state_test.go b/opnode/rollup/driver_state_test.go similarity index 99% rename from opnode/l2/driver_state_test.go rename to opnode/rollup/driver_state_test.go index b2be025e6ff9..1ce659d6d3c8 100644 --- a/opnode/l2/driver_state_test.go +++ b/opnode/rollup/driver_state_test.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" diff --git a/opnode/l2/driver_step.go b/opnode/rollup/driver_step.go similarity index 90% rename from opnode/l2/driver_step.go rename to opnode/rollup/driver_step.go index d01db44af9a0..d8dd882bbafa 100644 --- a/opnode/l2/driver_step.go +++ b/opnode/rollup/driver_step.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" @@ -8,16 +8,17 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) type DriverAPI interface { - EngineAPI - EthBackend + l2.EngineAPI + l2.EthBackend } -func Execute(ctx context.Context, rpc DriverAPI, payload *ExecutionPayload) error { +func Execute(ctx context.Context, rpc DriverAPI, payload *l2.ExecutionPayload) error { execCtx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() execRes, err := rpc.ExecutePayload(execCtx, payload) @@ -25,11 +26,11 @@ func Execute(ctx context.Context, rpc DriverAPI, payload *ExecutionPayload) erro return fmt.Errorf("failed to execute payload: %v", err) } switch execRes.Status { - case ExecutionValid: + case l2.ExecutionValid: return nil - case ExecutionSyncing: + case l2.ExecutionSyncing: return fmt.Errorf("failed to execute payload %s, node is syncing, latest valid hash is %s", payload.ID(), execRes.LatestValidHash) - case ExecutionInvalid: + case l2.ExecutionInvalid: return fmt.Errorf("execution payload %s was INVALID! Latest valid hash is %s, ignoring bad block: %q", payload.ID(), execRes.LatestValidHash, execRes.ValidationError) default: return fmt.Errorf("unknown execution status on %s: %q, ", payload.ID(), string(execRes.Status)) @@ -37,7 +38,7 @@ func Execute(ctx context.Context, rpc DriverAPI, payload *ExecutionPayload) erro } func ForkchoiceUpdate(ctx context.Context, rpc DriverAPI, l2BlockHash common.Hash, l2Finalized common.Hash) error { - postState := &ForkchoiceState{ + postState := &l2.ForkchoiceState{ HeadBlockHash: l2BlockHash, // no difference yet between Head and Safe, no data ahead of L1 yet. SafeBlockHash: l2BlockHash, FinalizedBlockHash: l2Finalized, @@ -50,9 +51,9 @@ func ForkchoiceUpdate(ctx context.Context, rpc DriverAPI, l2BlockHash common.Has return fmt.Errorf("failed to update forkchoice: %v", err) } switch fcRes.Status { - case UpdateSyncing: + case l2.UpdateSyncing: return fmt.Errorf("updated forkchoice, but node is syncing: %v", err) - case UpdateSuccess: + case l2.UpdateSuccess: return nil default: return fmt.Errorf("unknown forkchoice status on %s: %q, ", l2BlockHash, string(fcRes.Status)) diff --git a/opnode/l2/input_derivation.go b/opnode/rollup/input_derivation.go similarity index 95% rename from opnode/l2/input_derivation.go rename to opnode/rollup/input_derivation.go index ed4f01e05e97..0e45090b3741 100644 --- a/opnode/l2/input_derivation.go +++ b/opnode/rollup/input_derivation.go @@ -1,10 +1,11 @@ -package l2 +package rollup import ( "encoding/binary" "fmt" "math/big" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -180,7 +181,7 @@ type BlockInput interface { MixDigest() common.Hash } -func DeriveBlockInputs(block BlockInput, receipts []*types.Receipt) (*PayloadAttributes, error) { +func DeriveBlockInputs(block BlockInput, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { if !CheckReceipts(block, receipts) { return nil, fmt.Errorf("receipts are not consistent with the block's receipts root: %s", block.ReceiptHash()) } @@ -196,7 +197,7 @@ func DeriveBlockInputs(block BlockInput, receipts []*types.Receipt) (*PayloadAtt return nil, fmt.Errorf("failed to derive user deposits: %v", err) } - encodedTxs := make([]Data, 0, len(userDeposits)+1) + encodedTxs := make([]l2.Data, 0, len(userDeposits)+1) encodedTxs = append(encodedTxs, opaqueL1Tx) for i, tx := range userDeposits { @@ -207,9 +208,9 @@ func DeriveBlockInputs(block BlockInput, receipts []*types.Receipt) (*PayloadAtt encodedTxs = append(encodedTxs, opaqueTx) } - return &PayloadAttributes{ - Timestamp: Uint64Quantity(block.Time()), - Random: Bytes32(block.MixDigest()), + return &l2.PayloadAttributes{ + Timestamp: l2.Uint64Quantity(block.Time()), + Random: l2.Bytes32(block.MixDigest()), SuggestedFeeRecipient: common.Address{}, // nobody gets tx fees for deposits Transactions: encodedTxs, }, nil diff --git a/opnode/l2/input_derivation_test.go b/opnode/rollup/input_derivation_test.go similarity index 99% rename from opnode/l2/input_derivation_test.go rename to opnode/rollup/input_derivation_test.go index 325b7d467640..cde5b29a4cfe 100644 --- a/opnode/l2/input_derivation_test.go +++ b/opnode/rollup/input_derivation_test.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "encoding/binary" diff --git a/opnode/l2/output_derivation.go b/opnode/rollup/output_derivation.go similarity index 67% rename from opnode/l2/output_derivation.go rename to opnode/rollup/output_derivation.go index f36d2c9cdf1e..c373807fe58f 100644 --- a/opnode/l2/output_derivation.go +++ b/opnode/rollup/output_derivation.go @@ -1,21 +1,22 @@ -package l2 +package rollup import ( "context" "fmt" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/common" ) type BlockPreparer interface { - GetPayload(ctx context.Context, payloadId PayloadID) (*ExecutionPayload, error) - ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) + GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) + ForkchoiceUpdated(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (l2.ForkchoiceUpdatedResult, error) } // DeriveBlockOutputs uses the engine API to derive a full L2 block from the block inputs. // The fcState does not affect the block production, but may inform the engine of finality and head changes to sync towards before block computation. -func DeriveBlockOutputs(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *PayloadAttributes) (*ExecutionPayload, error) { - fcState := &ForkchoiceState{ +func DeriveBlockOutputs(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { + fcState := &l2.ForkchoiceState{ HeadBlockHash: l2Parent, // no difference yet between Head and Safe, no data ahead of L1 yet. SafeBlockHash: l2Parent, FinalizedBlockHash: l2Finalized, @@ -23,7 +24,7 @@ func DeriveBlockOutputs(ctx context.Context, engine BlockPreparer, l2Parent comm fcResult, err := engine.ForkchoiceUpdated(ctx, fcState, attributes) if err != nil { return nil, fmt.Errorf("engine failed to process forkchoice update for block derivation: %v", err) - } else if fcResult.Status != UpdateSuccess { + } else if fcResult.Status != l2.UpdateSuccess { return nil, fmt.Errorf("engine not in sync, failed to derive block, status: %s", fcResult.Status) } diff --git a/opnode/l2/reading.go b/opnode/rollup/reading.go similarity index 99% rename from opnode/l2/reading.go rename to opnode/rollup/reading.go index bcb55b83bab1..2da44363bd88 100644 --- a/opnode/l2/reading.go +++ b/opnode/rollup/reading.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "encoding/binary" diff --git a/opnode/l2/reading_test.go b/opnode/rollup/reading_test.go similarity index 99% rename from opnode/l2/reading_test.go rename to opnode/rollup/reading_test.go index 857c27a0ccc2..0d2543586521 100644 --- a/opnode/l2/reading_test.go +++ b/opnode/rollup/reading_test.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "math/big" diff --git a/opnode/l2/sync_reference.go b/opnode/rollup/sync_reference.go similarity index 99% rename from opnode/l2/sync_reference.go rename to opnode/rollup/sync_reference.go index 583e955e394a..c50a514604b7 100644 --- a/opnode/l2/sync_reference.go +++ b/opnode/rollup/sync_reference.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" diff --git a/opnode/l2/sync_start.go b/opnode/rollup/sync_start.go similarity index 99% rename from opnode/l2/sync_start.go rename to opnode/rollup/sync_start.go index 546fc055ac02..cbcc729d667c 100644 --- a/opnode/l2/sync_start.go +++ b/opnode/rollup/sync_start.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" diff --git a/opnode/l2/sync_start_test.go b/opnode/rollup/sync_start_test.go similarity index 99% rename from opnode/l2/sync_start_test.go rename to opnode/rollup/sync_start_test.go index a0d8f2668ba7..195cb7302778 100644 --- a/opnode/l2/sync_start_test.go +++ b/opnode/rollup/sync_start_test.go @@ -1,4 +1,4 @@ -package l2 +package rollup import ( "context" From ad996415ed596e313cf61c096846bfded293229f Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Feb 2022 13:32:52 -0800 Subject: [PATCH 205/585] Subdivide the rollup package The rollup package is split into three components that are seperate and do not have circular dependencies: * Derive * Driver * Sync --- opnode/node/node.go | 10 ++++++---- opnode/rollup/derive/doc.go | 16 ++++++++++++++++ .../{input_derivation.go => derive/input.go} | 15 ++++++++------- .../input_test.go} | 4 ++-- opnode/rollup/{reading.go => derive/invert.go} | 18 +++++++----------- .../{reading_test.go => derive/invert_test.go} | 12 ++++++------ .../{output_derivation.go => derive/output.go} | 6 +++--- opnode/rollup/{ => driver}/driver.go | 7 ++++--- .../rollup/{driver_loop.go => driver/loop.go} | 2 +- .../{driver_state.go => driver/state.go} | 5 +++-- .../state_test.go} | 5 +++-- .../rollup/{driver_step.go => driver/step.go} | 7 ++++--- .../{sync_reference.go => sync/reference.go} | 16 +++++++++------- opnode/rollup/{sync_start.go => sync/start.go} | 5 +++-- .../{sync_start_test.go => sync/start_test.go} | 9 +++++---- opnode/rollup/types.go | 8 ++++++++ 16 files changed, 88 insertions(+), 57 deletions(-) create mode 100644 opnode/rollup/derive/doc.go rename opnode/rollup/{input_derivation.go => derive/input.go} (91%) rename opnode/rollup/{input_derivation_test.go => derive/input_test.go} (98%) rename opnode/rollup/{reading.go => derive/invert.go} (69%) rename opnode/rollup/{reading_test.go => derive/invert_test.go} (87%) rename opnode/rollup/{output_derivation.go => derive/output.go} (81%) rename opnode/rollup/{ => driver}/driver.go (93%) rename opnode/rollup/{driver_loop.go => driver/loop.go} (99%) rename opnode/rollup/{driver_state.go => driver/state.go} (98%) rename opnode/rollup/{driver_state_test.go => driver/state_test.go} (96%) rename opnode/rollup/{driver_step.go => driver/step.go} (94%) rename opnode/rollup/{sync_reference.go => sync/reference.go} (70%) rename opnode/rollup/{sync_start.go => sync/start.go} (96%) rename opnode/rollup/{sync_start_test.go => sync/start_test.go} (95%) create mode 100644 opnode/rollup/types.go diff --git a/opnode/node/node.go b/opnode/node/node.go index 65e159079f3c..a0e8515b154b 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -12,6 +12,8 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/driver" + rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/event" @@ -54,7 +56,7 @@ type OpNodeCmd struct { l1Source eth.L1Source // engines to keep synced - l2Engines []*rollup.EngineDriver + l2Engines []*driver.EngineDriver l1Downloader l1.Downloader @@ -123,15 +125,15 @@ func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { EthBackend: ethclient.NewClient(backend), Log: c.log.New("engine_client", i), } - engine := &rollup.EngineDriver{ + engine := &driver.EngineDriver{ Log: c.log.New("engine", i), RPC: client, DL: c.l1Downloader, - SyncRef: rollup.SyncSource{ + SyncRef: rollupSync.SyncSource{ L1: l1CanonicalChain, L2: client, }, - EngineDriverState: rollup.EngineDriverState{Genesis: genesis}, + EngineDriverState: driver.EngineDriverState{Genesis: genesis}, } c.l2Engines = append(c.l2Engines, engine) } diff --git a/opnode/rollup/derive/doc.go b/opnode/rollup/derive/doc.go new file mode 100644 index 000000000000..f46f6c990016 --- /dev/null +++ b/opnode/rollup/derive/doc.go @@ -0,0 +1,16 @@ +// Package derive provides the data transformation functions that take L1 data +// and turn it into L2 blocks and results. Certian L2 data is also able to +// turned back into L1 data. +// +// The flow is data is as follows +// receipts -> l2.PayloadAttributes with `input.go` +// l2.PayloadAttributes -> l2.ExecutionPayload with `output.go` +// L2 block -> Corresponding L1 block with `invert.go` +// +// The input derivation stage is a pure function. +// The output derivation stage relies on the L2 execution engine to perform the +// state update. +// The inversion step is a pure function. +// +// The steps should be keep separate to enable easier testing. +package derive diff --git a/opnode/rollup/input_derivation.go b/opnode/rollup/derive/input.go similarity index 91% rename from opnode/rollup/input_derivation.go rename to opnode/rollup/derive/input.go index 0e45090b3741..c33fc6adbe8f 100644 --- a/opnode/rollup/input_derivation.go +++ b/opnode/rollup/derive/input.go @@ -1,4 +1,4 @@ -package rollup +package derive import ( "encoding/binary" @@ -117,7 +117,8 @@ type L1Info interface { BaseFee() *big.Int } -func DeriveL1InfoDeposit(block L1Info) *types.DepositTx { +// L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block +func L1InfoDeposit(block L1Info) *types.DepositTx { data := make([]byte, 4+8+8+32+32) offset := 0 copy(data[offset:4], L1InfoFuncBytes4) @@ -153,8 +154,8 @@ func CheckReceipts(block ReceiptHash, receipts []*types.Receipt) bool { return block.ReceiptHash() == computed } -// DeriveL2Transactions transforms a L1 block and corresponding receipts into the transaction inputs for a full L2 block -func DeriveUserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, error) { +// UserDeposits transforms a L1 block and corresponding receipts into the transaction inputs for a full L2 block +func UserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, error) { var out []*types.DepositTx for _, rec := range receipts { @@ -181,18 +182,18 @@ type BlockInput interface { MixDigest() common.Hash } -func DeriveBlockInputs(block BlockInput, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { +func BlockInputs(block BlockInput, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { if !CheckReceipts(block, receipts) { return nil, fmt.Errorf("receipts are not consistent with the block's receipts root: %s", block.ReceiptHash()) } - l1Tx := types.NewTx(DeriveL1InfoDeposit(block)) + l1Tx := types.NewTx(L1InfoDeposit(block)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { return nil, fmt.Errorf("failed to encode L1 info tx") } - userDeposits, err := DeriveUserDeposits(block.NumberU64(), receipts) + userDeposits, err := UserDeposits(block.NumberU64(), receipts) if err != nil { return nil, fmt.Errorf("failed to derive user deposits: %v", err) } diff --git a/opnode/rollup/input_derivation_test.go b/opnode/rollup/derive/input_test.go similarity index 98% rename from opnode/rollup/input_derivation_test.go rename to opnode/rollup/derive/input_test.go index cde5b29a4cfe..75afbb503b43 100644 --- a/opnode/rollup/input_derivation_test.go +++ b/opnode/rollup/derive/input_test.go @@ -1,4 +1,4 @@ -package rollup +package derive import ( "encoding/binary" @@ -186,7 +186,7 @@ func TestDeriveUserDeposits(t *testing.T) { Logs: logs, }) } - got, err := DeriveUserDeposits(testCase.height, receipts) + got, err := UserDeposits(testCase.height, receipts) assert.NoError(t, err) assert.Equal(t, len(got), len(expectedDeposits)) for d, depTx := range got { diff --git a/opnode/rollup/reading.go b/opnode/rollup/derive/invert.go similarity index 69% rename from opnode/rollup/reading.go rename to opnode/rollup/derive/invert.go index 2da44363bd88..df666bd27ede 100644 --- a/opnode/rollup/reading.go +++ b/opnode/rollup/derive/invert.go @@ -1,4 +1,4 @@ -package rollup +package derive import ( "encoding/binary" @@ -6,12 +6,13 @@ import ( "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) -// ParseL1InfoDepositTxData is the inverse of DeriveL1InfoDeposit, to see where the L2 chain is derived from -func ParseL1InfoDepositTxData(data []byte) (nr uint64, time uint64, baseFee *big.Int, blockHash common.Hash, err error) { +// L1InfoDepositTxData is the inverse of L1InfoDeposit, to see where the L2 chain is derived from +func L1InfoDepositTxData(data []byte) (nr uint64, time uint64, baseFee *big.Int, blockHash common.Hash, err error) { if len(data) != 4+8+8+32+32 { err = fmt.Errorf("data is unexpected length: %d", len(data)) return @@ -34,13 +35,8 @@ type Block interface { Transactions() types.Transactions } -type Genesis struct { - L1 eth.BlockID - L2 eth.BlockID -} - -// ParseBlockReferences takes a L2 block and determines which L1 block it was derived from, and the L2 self and parent id. -func ParseBlockReferences(refL2Block Block, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { +// BlockReferences takes a L2 block and determines which L1 block it was derived from, and the L2 self and parent id. +func BlockReferences(refL2Block Block, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { refL2 = eth.BlockID{Hash: refL2Block.Hash(), Number: refL2Block.NumberU64()} if refL2.Number <= genesis.L2.Number { if refL2.Hash != genesis.L2.Hash { @@ -59,7 +55,7 @@ func ParseBlockReferences(refL2Block Block, genesis *Genesis) (refL1 eth.BlockID err = fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", refL2Block.Hash()) return } - refL1Nr, _, _, refL1Hash, err := ParseL1InfoDepositTxData(txs[0].Data()) + refL1Nr, _, _, refL1Hash, err := L1InfoDepositTxData(txs[0].Data()) if err != nil { err = fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) return diff --git a/opnode/rollup/reading_test.go b/opnode/rollup/derive/invert_test.go similarity index 87% rename from opnode/rollup/reading_test.go rename to opnode/rollup/derive/invert_test.go index 0d2543586521..bb713a4aa9b7 100644 --- a/opnode/rollup/reading_test.go +++ b/opnode/rollup/derive/invert_test.go @@ -1,4 +1,4 @@ -package rollup +package derive import ( "math/big" @@ -83,8 +83,8 @@ func TestParseL1InfoDepositTxData(t *testing.T) { for i, testCase := range cases { t.Run(testCase.name, func(t *testing.T) { info := testCase.mkInfo(rand.New(rand.NewSource(int64(1234 + i)))) - depTx := DeriveL1InfoDeposit(info) - nr, time, baseFee, h, err := ParseL1InfoDepositTxData(depTx.Data) + depTx := L1InfoDeposit(info) + nr, time, baseFee, h, err := L1InfoDepositTxData(depTx.Data) assert.NoError(t, err, "expected valid deposit info") assert.Equal(t, nr, info.num) assert.Equal(t, time, info.time) @@ -94,15 +94,15 @@ func TestParseL1InfoDepositTxData(t *testing.T) { }) } t.Run("no data", func(t *testing.T) { - _, _, _, _, err := ParseL1InfoDepositTxData(nil) + _, _, _, _, err := L1InfoDepositTxData(nil) assert.Error(t, err) }) t.Run("not enough data", func(t *testing.T) { - _, _, _, _, err := ParseL1InfoDepositTxData([]byte{1, 2, 3, 4}) + _, _, _, _, err := L1InfoDepositTxData([]byte{1, 2, 3, 4}) assert.Error(t, err) }) t.Run("too much data", func(t *testing.T) { - _, _, _, _, err := ParseL1InfoDepositTxData(make([]byte, 4+8+8+32+32+1)) + _, _, _, _, err := L1InfoDepositTxData(make([]byte, 4+8+8+32+32+1)) assert.Error(t, err) }) } diff --git a/opnode/rollup/output_derivation.go b/opnode/rollup/derive/output.go similarity index 81% rename from opnode/rollup/output_derivation.go rename to opnode/rollup/derive/output.go index c373807fe58f..13fb907e35bf 100644 --- a/opnode/rollup/output_derivation.go +++ b/opnode/rollup/derive/output.go @@ -1,4 +1,4 @@ -package rollup +package derive import ( "context" @@ -13,9 +13,9 @@ type BlockPreparer interface { ForkchoiceUpdated(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (l2.ForkchoiceUpdatedResult, error) } -// DeriveBlockOutputs uses the engine API to derive a full L2 block from the block inputs. +// BlockOutputs uses the engine API to derive a full L2 block from the block inputs. // The fcState does not affect the block production, but may inform the engine of finality and head changes to sync towards before block computation. -func DeriveBlockOutputs(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { +func BlockOutputs(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { fcState := &l2.ForkchoiceState{ HeadBlockHash: l2Parent, // no difference yet between Head and Safe, no data ahead of L1 yet. SafeBlockHash: l2Parent, diff --git a/opnode/rollup/driver.go b/opnode/rollup/driver/driver.go similarity index 93% rename from opnode/rollup/driver.go rename to opnode/rollup/driver/driver.go index 527384d21ccb..64a9c290d541 100644 --- a/opnode/rollup/driver.go +++ b/opnode/rollup/driver/driver.go @@ -1,4 +1,4 @@ -package rollup +package driver import ( "context" @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum/log" ) @@ -32,7 +33,7 @@ type EngineDriver struct { // API bindings to execution engine RPC DriverAPI DL Downloader - SyncRef SyncReference + SyncRef rollupSync.SyncReference // The current driving force, to shutdown before closing the engine. driveSub ethereum.Subscription @@ -59,7 +60,7 @@ func (e *EngineDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID } func (e *EngineDriver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - return FindSyncStart(ctx, e.SyncRef, &e.Genesis) + return rollupSync.FindSyncStart(ctx, e.SyncRef, &e.Genesis) } func (e *EngineDriver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { diff --git a/opnode/rollup/driver_loop.go b/opnode/rollup/driver/loop.go similarity index 99% rename from opnode/rollup/driver_loop.go rename to opnode/rollup/driver/loop.go index 1b1881cddff2..0f9b6f162135 100644 --- a/opnode/rollup/driver_loop.go +++ b/opnode/rollup/driver/loop.go @@ -1,4 +1,4 @@ -package rollup +package driver import ( "context" diff --git a/opnode/rollup/driver_state.go b/opnode/rollup/driver/state.go similarity index 98% rename from opnode/rollup/driver_state.go rename to opnode/rollup/driver/state.go index 38d18be36591..e6a9ed36f8cf 100644 --- a/opnode/rollup/driver_state.go +++ b/opnode/rollup/driver/state.go @@ -1,10 +1,11 @@ -package rollup +package driver import ( "context" "sync" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/log" ) @@ -40,7 +41,7 @@ type EngineDriverState struct { l1Target eth.BlockID // Genesis starting point - Genesis Genesis + Genesis rollup.Genesis } // L1Head returns the block-id (hash and number) of the last L1 block that was derived into the L2 block diff --git a/opnode/rollup/driver_state_test.go b/opnode/rollup/driver/state_test.go similarity index 96% rename from opnode/rollup/driver_state_test.go rename to opnode/rollup/driver/state_test.go index 1ce659d6d3c8..d1a63cdf00de 100644 --- a/opnode/rollup/driver_state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -1,4 +1,4 @@ -package rollup +package driver import ( "context" @@ -8,6 +8,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" @@ -51,7 +52,7 @@ func makeState(st testState) *EngineDriverState { l2Head: st.l2Head.ID(), l2Finalized: st.l2Finalized.ID(), l1Target: st.l1Target.ID(), - Genesis: Genesis{ + Genesis: rollup.Genesis{ L1: st.genesisL1.ID(), L2: st.genesisL2.ID(), }, diff --git a/opnode/rollup/driver_step.go b/opnode/rollup/driver/step.go similarity index 94% rename from opnode/rollup/driver_step.go rename to opnode/rollup/driver/step.go index d8dd882bbafa..a0ed822f419b 100644 --- a/opnode/rollup/driver_step.go +++ b/opnode/rollup/driver/step.go @@ -1,4 +1,4 @@ -package rollup +package driver import ( "context" @@ -9,6 +9,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -77,13 +78,13 @@ func DriverStep(ctx context.Context, log log.Logger, rpc DriverAPI, } logger.Debug("fetched L1 data for driver") - attrs, err := DeriveBlockInputs(bl, receipts) + attrs, err := derive.BlockInputs(bl, receipts) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to derive execution payload inputs: %v", err) } logger.Debug("derived L2 block inputs") - payload, err := DeriveBlockOutputs(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) + payload, err := derive.BlockOutputs(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to derive execution payload: %v", err) } diff --git a/opnode/rollup/sync_reference.go b/opnode/rollup/sync/reference.go similarity index 70% rename from opnode/rollup/sync_reference.go rename to opnode/rollup/sync/reference.go index c50a514604b7..2b0adf14a4e0 100644 --- a/opnode/rollup/sync_reference.go +++ b/opnode/rollup/sync/reference.go @@ -1,4 +1,4 @@ -package rollup +package sync import ( "context" @@ -6,6 +6,8 @@ import ( "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" ) @@ -22,23 +24,23 @@ func (src SyncSource) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.Bl // RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. // Use a nil height to fetch the head. -func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { +func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { refL2Block, err2 := src.L2.BlockByNumber(ctx, l2Num) // nil for latest block if err2 != nil { err = fmt.Errorf("failed to retrieve L2 block: %v", err2) return } - return ParseBlockReferences(refL2Block, genesis) + return derive.BlockReferences(refL2Block, genesis) } // RefByL2Hash fetches the L1 and L2 block IDs from the engine for the given L2 block hash. -func (src SyncSource) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { +func (src SyncSource) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { refL2Block, err2 := src.L2.BlockByHash(ctx, l2Hash) if err2 != nil { err = fmt.Errorf("failed to retrieve L2 block: %v", err2) return } - return ParseBlockReferences(refL2Block, genesis) + return derive.BlockReferences(refL2Block, genesis) } // SyncReference helps inform the sync algorithm of the L2 sync-state and L1 canonical chain @@ -48,8 +50,8 @@ type SyncReference interface { // RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. // Use a nil height to fetch the head. - RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) + RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) // RefByL2Hash fetches the L1 and L2 block IDs from the engine for the given L2 block hash. - RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) + RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) } diff --git a/opnode/rollup/sync_start.go b/opnode/rollup/sync/start.go similarity index 96% rename from opnode/rollup/sync_start.go rename to opnode/rollup/sync/start.go index cbcc729d667c..352f9a2312e4 100644 --- a/opnode/rollup/sync_start.go +++ b/opnode/rollup/sync/start.go @@ -1,4 +1,4 @@ -package rollup +package sync import ( "context" @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" ) @@ -15,7 +16,7 @@ var WrongChainErr = errors.New("wrong chain") // FindSyncStart finds nextRefL1: the L1 block needed next for sync, to derive into a L2 block on top of refL2. // If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. -func FindSyncStart(ctx context.Context, reference SyncReference, genesis *Genesis) (nextRefL1, refL2 eth.BlockID, err error) { +func FindSyncStart(ctx context.Context, reference SyncReference, genesis *rollup.Genesis) (nextRefL1, refL2 eth.BlockID, err error) { var refL1 eth.BlockID // the L1 block the refL2 was derived from var parentL2 common.Hash // the parent of refL2 // Start at L2 head diff --git a/opnode/rollup/sync_start_test.go b/opnode/rollup/sync/start_test.go similarity index 95% rename from opnode/rollup/sync_start_test.go rename to opnode/rollup/sync/start_test.go index 195cb7302778..3923f5b4d4fd 100644 --- a/opnode/rollup/sync_start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -1,4 +1,4 @@ -package rollup +package sync import ( "context" @@ -6,6 +6,7 @@ import ( "testing" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" @@ -33,7 +34,7 @@ func (m *mockSyncReference) RefByL1Num(ctx context.Context, l1Num uint64) (self return } -func (m *mockSyncReference) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { +func (m *mockSyncReference) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { if len(m.L2) == 0 { panic("bad test, no l2 chain") } @@ -50,7 +51,7 @@ func (m *mockSyncReference) RefByL2Num(ctx context.Context, l2Num *big.Int, gene return } -func (m *mockSyncReference) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { +func (m *mockSyncReference) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { for i, bl := range m.L2 { if bl.Self.Hash == l2Hash { return m.RefByL2Num(ctx, big.NewInt(int64(i)), genesis) @@ -112,7 +113,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { L1: actL1, } - genesis := &Genesis{ + genesis := &rollup.Genesis{ L1: mockID(c.GenesisL1, c.OffsetL2), L2: mockID(c.GenesisL2, 0), } diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go new file mode 100644 index 000000000000..6ba0e6caf11d --- /dev/null +++ b/opnode/rollup/types.go @@ -0,0 +1,8 @@ +package rollup + +import "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + +type Genesis struct { + L1 eth.BlockID + L2 eth.BlockID +} From 3b44d88833602d91149a5e8088586046c2c9c6c8 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Feb 2022 13:55:55 -0800 Subject: [PATCH 206/585] l2: Add short godoc to package --- opnode/l2/api.go | 1 + 1 file changed, 1 insertion(+) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 9f5a827de1d4..988bae531196 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -1,3 +1,4 @@ +// Package l2 connects to the L2 execution engine over the Catalyst API. package l2 import ( From cf8d3a032e3ba274b4eeca68dab8dc173f9a2904 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 4 Feb 2022 08:59:28 -0800 Subject: [PATCH 207/585] Rename Catalyst -> Engine API Co-authored-by: Diederik Loerakker --- opnode/l2/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 988bae531196..3de4081753cb 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -1,4 +1,4 @@ -// Package l2 connects to the L2 execution engine over the Catalyst API. +// Package l2 connects to the L2 execution engine over the Engine API. package l2 import ( From 1ca7b4abcd40dadeb55446ec27831c94780c3836 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 4 Feb 2022 10:03:54 -0800 Subject: [PATCH 208/585] Rename input/output to Payload Attributes/Execution The new names are in line with the Engine API and are no longer trivial to confuse with other input/output portions of the rollup system. --- opnode/rollup/derive/doc.go | 8 ++++---- opnode/rollup/derive/{output.go => execution_payload.go} | 4 ++-- opnode/rollup/derive/{input.go => payload_attributes.go} | 4 +++- .../derive/{input_test.go => payload_attributes_test.go} | 0 opnode/rollup/driver/step.go | 4 ++-- 5 files changed, 11 insertions(+), 9 deletions(-) rename opnode/rollup/derive/{output.go => execution_payload.go} (82%) rename opnode/rollup/derive/{input.go => payload_attributes.go} (96%) rename opnode/rollup/derive/{input_test.go => payload_attributes_test.go} (100%) diff --git a/opnode/rollup/derive/doc.go b/opnode/rollup/derive/doc.go index f46f6c990016..e0b46265c0cd 100644 --- a/opnode/rollup/derive/doc.go +++ b/opnode/rollup/derive/doc.go @@ -3,12 +3,12 @@ // turned back into L1 data. // // The flow is data is as follows -// receipts -> l2.PayloadAttributes with `input.go` -// l2.PayloadAttributes -> l2.ExecutionPayload with `output.go` +// receipts -> l2.PayloadAttributes with `payload_attributes.go` +// l2.PayloadAttributes -> l2.ExecutionPayload with `execution_payload.go` // L2 block -> Corresponding L1 block with `invert.go` // -// The input derivation stage is a pure function. -// The output derivation stage relies on the L2 execution engine to perform the +// The Payload Atrribute derivation stage is a pure function. +// The Execution Payload derivation stage relies on the L2 execution engine to perform the // state update. // The inversion step is a pure function. // diff --git a/opnode/rollup/derive/output.go b/opnode/rollup/derive/execution_payload.go similarity index 82% rename from opnode/rollup/derive/output.go rename to opnode/rollup/derive/execution_payload.go index 13fb907e35bf..0e2b37c373c3 100644 --- a/opnode/rollup/derive/output.go +++ b/opnode/rollup/derive/execution_payload.go @@ -13,9 +13,9 @@ type BlockPreparer interface { ForkchoiceUpdated(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (l2.ForkchoiceUpdatedResult, error) } -// BlockOutputs uses the engine API to derive a full L2 block from the block inputs. +// ExecutionPayload uses the engine API to derive a full L2 block from the payload attributes. // The fcState does not affect the block production, but may inform the engine of finality and head changes to sync towards before block computation. -func BlockOutputs(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { +func ExecutionPayload(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { fcState := &l2.ForkchoiceState{ HeadBlockHash: l2Parent, // no difference yet between Head and Safe, no data ahead of L1 yet. SafeBlockHash: l2Parent, diff --git a/opnode/rollup/derive/input.go b/opnode/rollup/derive/payload_attributes.go similarity index 96% rename from opnode/rollup/derive/input.go rename to opnode/rollup/derive/payload_attributes.go index c33fc6adbe8f..c7dc7690e23e 100644 --- a/opnode/rollup/derive/input.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -182,7 +182,9 @@ type BlockInput interface { MixDigest() common.Hash } -func BlockInputs(block BlockInput, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { +// PayloadAttributes derives the pre-execution payload from the L1 block info and deposit receipts. +// This is a pure function. +func PayloadAttributes(block BlockInput, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { if !CheckReceipts(block, receipts) { return nil, fmt.Errorf("receipts are not consistent with the block's receipts root: %s", block.ReceiptHash()) } diff --git a/opnode/rollup/derive/input_test.go b/opnode/rollup/derive/payload_attributes_test.go similarity index 100% rename from opnode/rollup/derive/input_test.go rename to opnode/rollup/derive/payload_attributes_test.go diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index a0ed822f419b..67f769ed5900 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -78,13 +78,13 @@ func DriverStep(ctx context.Context, log log.Logger, rpc DriverAPI, } logger.Debug("fetched L1 data for driver") - attrs, err := derive.BlockInputs(bl, receipts) + attrs, err := derive.PayloadAttributes(bl, receipts) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to derive execution payload inputs: %v", err) } logger.Debug("derived L2 block inputs") - payload, err := derive.BlockOutputs(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) + payload, err := derive.ExecutionPayload(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to derive execution payload: %v", err) } From 2a1266a96803758c57b976d4dfd91d9d88885828 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Thu, 3 Feb 2022 17:43:58 -0700 Subject: [PATCH 209/585] opnode: Add Dockerfile/Makefile - Adds a Dockerfile so that we can build opnode images - Adds a Makefile to make building the opnode easier --- .gitignore | 3 +++ Dockerfile.opnode | 16 ++++++++++++++++ Makefile | 7 +++++++ 3 files changed, 26 insertions(+) create mode 100644 Dockerfile.opnode create mode 100644 Makefile diff --git a/.gitignore b/.gitignore index 070c04688e8f..a6cdcec18194 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ coverage.out # hardhat automatically puts console.sol in here when you use it .deps + +# built binaries +bin \ No newline at end of file diff --git a/Dockerfile.opnode b/Dockerfile.opnode new file mode 100644 index 000000000000..f308e25d1410 --- /dev/null +++ b/Dockerfile.opnode @@ -0,0 +1,16 @@ +FROM golang:1.17.3-alpine3.13 as builder + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +COPY Makefile /app/Makefile +COPY go.mod /app/go.mod +COPY go.sum /app/go.sum + +WORKDIR /app +COPY ./opnode /app/opnode +RUN make + +FROM alpine:3.13 + +COPY --from=builder /app/bin/op /usr/local/bin +CMD ["op"] diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..b229a53e5bfe --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +opnode: + go build -o ./bin/op ./opnode/cmd +.PHONY: opnode + +clean: + rm -rf ./bin +.PHONY: clean \ No newline at end of file From d100e42cb25df0eab37cce25f8cc6c4b5bef7c59 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 7 Feb 2022 11:20:47 -0800 Subject: [PATCH 210/585] Ref impl: Remove OpNodeCmd This removes OpNodeCmd in favor of a separate configuration and node struct. Command line flag parsing is also done with urfave/cli. --- go.mod | 5 +- go.sum | 7 +- opnode/cmd/main.go | 210 ++++++++++++++++++++++++++++++++++--- opnode/node/log.go | 96 +++++++---------- opnode/node/node.go | 189 ++++++++++++++++----------------- opnode/test/system_test.go | 26 ++--- 6 files changed, 346 insertions(+), 187 deletions(-) diff --git a/go.mod b/go.mod index 95ddb8d9ca90..a7e07db97e91 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.0 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 - github.com/protolambda/ask v0.1.3 github.com/stretchr/testify v1.7.0 + github.com/urfave/cli v1.22.5 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 ) @@ -18,6 +18,7 @@ require ( github.com/btcsuite/btcd v0.21.0-beta // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect @@ -43,7 +44,9 @@ require ( github.com/prometheus/tsdb v0.7.1 // indirect github.com/rjeczalik/notify v0.9.1 // indirect github.com/rs/cors v1.7.0 // indirect + github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect github.com/stretchr/objx v0.1.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect diff --git a/go.sum b/go.sum index c471f1f28b1a..ccc1a2014340 100644 --- a/go.sum +++ b/go.sum @@ -91,6 +91,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= 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 h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= 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= @@ -350,20 +351,20 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/protolambda/ask v0.1.3 h1:DhROikobv9hgj6zUh9svByFvzvsAHvDSzjwsGDMYAu8= -github.com/protolambda/ask v0.1.3/go.mod h1:7WB3T4BXZhKUaDcEjF7Ksgi7HCrBDxM37gyM1EhwkmM= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= 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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= 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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -394,6 +395,8 @@ github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefld github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 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= diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 3ca05227d73d..45e8b90dfabc 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -1,31 +1,211 @@ package main import ( + "context" + "encoding/hex" + "errors" + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/urfave/cli" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/protolambda/ask" ) -type MainCmd struct { +var ( + Version = "" + GitCommit = "" + GitDate = "" +) + +func main() { + // Set up logger with a default INFO level in case we fail to parse flags, + // otherwise the final critical log won't show what the parsing error was. + log.Root().SetHandler( + log.LvlFilterHandler( + log.LvlInfo, + log.StreamHandler(os.Stdout, log.TerminalFormat(true)), + ), + ) + + app := cli.NewApp() + app.Flags = Flags + app.Version = fmt.Sprintf("%s-%s", Version, params.VersionWithCommit(GitCommit, GitDate)) // TODO: Don't use Geth's hardcoded versions + app.Name = "opnode" + app.Usage = "Optimism Rollup Node" + app.Description = "The deposit only rollup node drives the L2 execution engine based on L1 deposits." + + app.Action = RollupNodeMain + err := app.Run(os.Args) + if err != nil { + log.Crit("Application failed", "message", err) + } +} + +func RollupNodeMain(ctx *cli.Context) error { + log.Info("Initializing Rollup Node") + cfg, err := NewConfig(ctx) + if err != nil { + log.Error("Unable to create the rollup node config", "error", err) + return err + } + n, err := node.New(context.Background(), cfg) + if err != nil { + log.Error("Unable to create the rollup node", "error", err) + return err + } + log.Info("Starting rollup node") + + if err := n.Start(); err != nil { + log.Error("Unable to start L2 Output Submitter", "error", err) + return err + } + defer n.Stop() + + log.Info("Rollup node started") + + interruptChannel := make(chan os.Signal, 1) + signal.Notify(interruptChannel, []os.Signal{ + os.Interrupt, + os.Kill, + syscall.SIGTERM, + syscall.SIGQUIT, + }...) + <-interruptChannel + + return nil + +} + +// has0xPrefix validates str begins with '0x' or '0X'. +// Copied from geth +func has0xPrefix(str string) bool { + return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') +} + +// HexToHash is copied from Geth, but does not supress the error +func HexToHash(s string) (common.Hash, error) { + if has0xPrefix(s) { + s = s[2:] + } + bytes, err := hex.DecodeString(s) + if err != nil { + return common.Hash{}, fmt.Errorf("Could not decode hex hash: %w", err) + } + if len(bytes) != common.HashLength { + return common.Hash{}, errors.New("Invalid length for Hash") + } + return common.BytesToHash(bytes), nil } -func (c *MainCmd) Help() string { - return "Run Optimism rollup node." +// NewConfig creates a Config from the provided flags or environment variables. +func NewConfig(ctx *cli.Context) (*node.Config, error) { + L2Hash, err := HexToHash(ctx.GlobalString(GenesisL2Hash.Name)) + if err != nil { + return nil, fmt.Errorf("Could not decode L2Hash: %w", err) + } + L1Hash, err := HexToHash(ctx.GlobalString(GenesisL1Hash.Name)) + if err != nil { + return nil, fmt.Errorf("Could not decode L1Hash: %w", err) + } + logCfg, err := NewLogConfig(ctx) + if err != nil { + return nil, err + } + + return &node.Config{ + /* Required Flags */ + L1NodeAddrs: ctx.GlobalStringSlice(L1NodeAddrs.Name), + L2EngineAddrs: ctx.GlobalStringSlice(L2EngineAddrs.Name), + L2Hash: L2Hash, + L1Hash: L1Hash, + L1Num: ctx.GlobalUint64(GenesisL2Hash.Name), + /* Optional Flags */ + LogCfg: logCfg, + }, nil } -func (c *MainCmd) Cmd(route string) (cmd interface{}, err error) { - switch route { - case "run": - return &node.OpNodeCmd{}, nil - default: - return nil, ask.UnrecognizedErr +// NewLogConfig creates a log config from the provided flags or environment variables. +func NewLogConfig(ctx *cli.Context) (node.LogConfig, error) { + logCfg := node.DefaultLogConfig() // Done to set color based on terminal type + logCfg.Level = ctx.GlobalString(LogLevelFlag.Name) + logCfg.Format = ctx.GlobalString(LogFormatFlag.Name) + if ctx.IsSet(LogColorFlag.Name) { + logCfg.Color = ctx.GlobalBool(LogColorFlag.Name) } + + if err := logCfg.Check(); err != nil { + return logCfg, err + } + return logCfg, nil } -// TODO: we can support additional utils etc. -func (c *MainCmd) Routes() []string { - return []string{"run"} +// Flags + +const envVarPrefix = "ROLLUP_NODE_" + +func prefixEnvVar(name string) string { + return envVarPrefix + name } -func main() { - ask.Run(new(MainCmd)) +var Flags = []cli.Flag{ + L1NodeAddrs, + L2EngineAddrs, + GenesisL2Hash, + GenesisL1Hash, + GenesisL1Num, + LogLevelFlag, + LogFormatFlag, + LogColorFlag, } + +var ( + /* Required Flags */ + L1NodeAddrs = cli.StringSliceFlag{ + Name: "l1", + Usage: "Addresses of L1 User JSON-RPC endpoints to use (eth namespace required)", + Required: true, + } + L2EngineAddrs = cli.StringSliceFlag{ + Name: "l2", + Usage: "Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)", + Required: true, + } + GenesisL2Hash = cli.StringFlag{ + Name: "genesis.l2-hash", + Usage: "Genesis block hash of L2", + Required: true, + } + GenesisL1Hash = cli.StringFlag{ + Name: "genesis.l1-hash", + Usage: "Block hash of L1 after (not incl.) which L1 starts deriving blocks", + Required: true, + } + GenesisL1Num = cli.Uint64Flag{ + Name: "genesis.l1-num", + Usage: "Block number of L1 matching the l1-hash", + Required: true, + } + + /* Optional Flags */ + + LogLevelFlag = cli.StringFlag{ + Name: "log.level", + Usage: "The lowest log level that will be output", + Value: "info", + } + LogFormatFlag = cli.StringFlag{ + Name: "log.format", + Usage: "Format the log output. Supported formats: 'text', 'json'", + Value: "text", + } + LogColorFlag = cli.BoolFlag{ + Name: "log.color", + Usage: "Color the log output", + } +) diff --git a/opnode/node/log.go b/opnode/node/log.go index 52a976fddccf..7cc5fdecadcb 100644 --- a/opnode/node/log.go +++ b/opnode/node/log.go @@ -9,55 +9,50 @@ import ( "golang.org/x/term" ) -type LogLvl string +type LogConfig struct { + Level string // Log level: trace, debug, info, warn, error, crit. Capitals are accepted too. + Color bool // Color the log output. Defaults to true if terminal is detected. + Format string // Format the log output. Supported formats: 'text', 'json' -func (lvl LogLvl) String() string { - return string(lvl) } -func (lvl *LogLvl) Set(v string) error { - v = strings.ToLower(v) // ignore case - _, err := log.LvlFromString(v) - if err != nil { - return err - } - *lvl = LogLvl(v) - return nil -} - -func (lvl *LogLvl) Type() string { - return "log-level" -} - -func (lvl LogLvl) Lvl() log.Lvl { - out, err := log.LvlFromString(string(lvl)) - if err != nil { - panic("lvl.Set failed") +func DefaultLogConfig() LogConfig { + return LogConfig{ + Level: "info", + Format: "text", + Color: term.IsTerminal(int(os.Stdout.Fd())), } - return out } -type LogFormat string - -func (lf LogFormat) String() string { - return string(lf) -} - -func (lf *LogFormat) Set(v string) error { - switch v { +// Check verifes that the LogConfig is valid. Calls to `NewLogger` may fail if this +// returns an error. +func (cfg *LogConfig) Check() error { + switch cfg.Format { case "json", "json-pretty", "terminal", "text": - *lf = LogFormat(v) - return nil default: - return fmt.Errorf("unrecognized log format: %s", v) + return fmt.Errorf("unrecognized log format: %s", cfg.Format) } + level := strings.ToLower(cfg.Level) // ignore case + _, err := log.LvlFromString(level) + if err != nil { + return fmt.Errorf("unrecognized log level: %w", err) + } + return nil } -func (lf *LogFormat) Type() string { - return "log-format" +// NewLogger creates a logger based on the supplied configuration +func (cfg *LogConfig) NewLogger() log.Logger { + handler := log.StreamHandler(os.Stdout, format(cfg.Format, cfg.Color)) + handler = log.SyncHandler(handler) + log.LvlFilterHandler(level(cfg.Level), handler) + logger := log.New() + logger.SetHandler(handler) + return logger + } -func (lf LogFormat) Format(color bool) log.Format { +// format turns a string and color into a structured Format object +func format(lf string, color bool) log.Format { switch lf { case "json": return log.JSONFormat() @@ -66,27 +61,16 @@ func (lf LogFormat) Format(color bool) log.Format { case "text", "terminal": return log.TerminalFormat(color) default: - panic("lf.Set failed") + panic("Failed to create `log.Format` from options") } } -type LogCmd struct { - LogLvl LogLvl `ask:"--level" help:"Log level: trace, debug, info, warn, error, crit. Capitals are accepted too."` - Color bool `ask:"--color" help:"Color the log output. Defaults to true if terminal is detected."` - Format LogFormat `ask:"--format" help:"Format the log output. Supported formats: 'text', 'json'"` -} - -func (c *LogCmd) Default() { - c.LogLvl = "info" - c.Color = term.IsTerminal(int(os.Stdout.Fd())) - c.Format = "text" -} - -func (c *LogCmd) Create() log.Logger { - handler := log.StreamHandler(os.Stdout, c.Format.Format(c.Color)) - handler = log.SyncHandler(handler) - log.LvlFilterHandler(c.LogLvl.Lvl(), handler) - logger := log.New() - logger.SetHandler(handler) - return logger +// level parses the level string into an appropriate object +func level(s string) log.Lvl { + s = strings.ToLower(s) // ignore case + l, err := log.LvlFromString(s) + if err != nil { + panic(fmt.Sprintf("Could not parse log level: %v", err)) + } + return l } diff --git a/opnode/node/node.go b/opnode/node/node.go index a0e8515b154b..8a4b77cd9a26 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -2,12 +2,9 @@ package node import ( "context" - "errors" "fmt" "time" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" @@ -16,82 +13,67 @@ import ( rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" - - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rpc" ) -type GenesisConf struct { - L2Hash common.Hash `ask:"--l2-hash" help:"Genesis block hash of L2"` - L1Hash common.Hash `ask:"--l1-hash" help:"Block hash of L1 after (not incl.) which L1 starts deriving blocks"` - L1Num uint64 `ask:"--l1-num" help:"Block number of L1 matching the l1-hash"` -} - -func (conf *GenesisConf) GetGenesis() rollup.Genesis { - return rollup.Genesis{ - L1: eth.BlockID{Hash: conf.L1Hash, Number: conf.L1Num}, - // TODO: if we start from a squashed snapshot we might have a non-zero L2 genesis number - L2: eth.BlockID{Hash: conf.L2Hash, Number: 0}, - } -} - -type OpNodeCmd struct { - L1NodeAddrs []string `ask:"--l1" help:"Addresses of L1 User JSON-RPC endpoints to use (eth namespace required)"` - L2EngineAddrs []string `ask:"--l2" help:"Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)"` - - LogCmd `ask:".log" help:"Log configuration"` - - Genesis GenesisConf `ask:".genesis" help:"Genesis anchor point"` - - // during later sequencer rollup implementation: - // TODO: multi-addrs option (static peers) - // TODO: bootnodes option (bootstrap discovery of more peers) - - log log.Logger +type Config struct { + // L1 and L2 nodes + L1NodeAddrs []string // Addresses of L1 User JSON-RPC endpoints to use (eth namespace required) + L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required) - // (combined) source to fetch data from - l1Source eth.L1Source + // Genesis Information + L2Hash common.Hash // Genesis block hash of L2 + L1Hash common.Hash // Block hash of L1 after (not incl.) which L1 starts deriving blocks + L1Num uint64 // Block number of L1 matching the l1-hash - // engines to keep synced - l2Engines []*driver.EngineDriver - - l1Downloader l1.Downloader - - ctx context.Context - close chan chan error + LogCfg LogConfig } -func (c *OpNodeCmd) Default() { - c.L1NodeAddrs = []string{"http://127.0.0.1:8545"} - c.L2EngineAddrs = []string{"http://127.0.0.1:8551"} +// Check verifies that the given configuration makes sense +func (cfg *Config) Check() error { + err := cfg.LogCfg.Check() + if err != nil { + return fmt.Errorf("Error checking log sub-config: %w", err) + } + return nil } -func (c *OpNodeCmd) Help() string { - return "Run optimism node" +type OpNode struct { + log log.Logger + l1Source eth.L1Source // (combined) source to fetch data from + l1Downloader l1.Downloader // actual downloader + l2Engines []*driver.EngineDriver // engines to keep synced + ctx context.Context // Embeded CTX to be removed + close chan chan error // Why chan of chans? } -func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { - logger := c.LogCmd.Create() - c.log = logger - c.ctx = ctx - - if c.Genesis == (GenesisConf{}) { - return errors.New("genesis configuration required") +func (conf *Config) GetGenesis() rollup.Genesis { + return rollup.Genesis{ + L1: eth.BlockID{Hash: conf.L1Hash, Number: conf.L1Num}, + // TODO: if we start from a squashed snapshot we might have a non-zero L2 genesis number + L2: eth.BlockID{Hash: conf.L2Hash, Number: 0}, } +} - l1Sources := make([]eth.L1Source, 0, len(c.L1NodeAddrs)) - for i, addr := range c.L1NodeAddrs { +func New(ctx context.Context, cfg *Config) (*OpNode, error) { + if err := cfg.Check(); err != nil { + return nil, err + } + log := cfg.LogCfg.NewLogger() + l1Sources := make([]eth.L1Source, 0, len(cfg.L1NodeAddrs)) + for i, addr := range cfg.L1NodeAddrs { // L1 exec engine: read-only, to update L2 consensus with l1Node, err := rpc.DialContext(ctx, addr) if err != nil { // HTTP or WS RPC may create a disconnected client, RPC over IPC may fail directly if l1Node == nil { - return fmt.Errorf("failed to dial L1 address %d (%s): %v", i, addr, err) + return nil, fmt.Errorf("failed to dial L1 address %d (%s): %v", i, addr, err) } - c.log.Warn("failed to dial L1 address, but may connect later", "i", i, "addr", addr, "err", err) + log.Warn("failed to dial L1 address, but may connect later", "i", i, "addr", addr, "err", err) } // TODO: we may need to authenticate the connection with L1 // l1Node.SetHeader() @@ -99,56 +81,58 @@ func (c *OpNodeCmd) Run(ctx context.Context, args ...string) error { l1Sources = append(l1Sources, cl) } if len(l1Sources) == 0 { - return fmt.Errorf("need at least one L1 source endpoint, see --l1") + return nil, fmt.Errorf("need at least one L1 source endpoint, see --l1") } - // Combine L1 sources, so work can be balanced between them - c.l1Source = eth.NewCombinedL1Source(l1Sources) - l1CanonicalChain := eth.CanonicalChain(c.l1Source) + l1Source := eth.NewCombinedL1Source(l1Sources) + l1CanonicalChain := eth.CanonicalChain(l1Source) - c.l1Downloader = l1.NewDownloader(c.l1Source) - genesis := c.Genesis.GetGenesis() + l1Downloader := l1.NewDownloader(l1Source) + genesis := cfg.GetGenesis() + var l2Engines []*driver.EngineDriver - for i, addr := range c.L2EngineAddrs { + for i, addr := range cfg.L2EngineAddrs { // L2 exec engine: updated by this OpNode (L2 consensus layer node) backend, err := rpc.DialContext(ctx, addr) if err != nil { if backend == nil { - return fmt.Errorf("failed to dial L2 address %d (%s): %v", i, addr, err) + return nil, fmt.Errorf("failed to dial L2 address %d (%s): %v", i, addr, err) } - c.log.Warn("failed to dial L2 address, but may connect later", "i", i, "addr", addr, "err", err) + log.Warn("failed to dial L2 address, but may connect later", "i", i, "addr", addr, "err", err) } // TODO: we may need to authenticate the connection with L2 // backend.SetHeader() client := &l2.EngineClient{ RPCBackend: backend, EthBackend: ethclient.NewClient(backend), - Log: c.log.New("engine_client", i), + Log: log.New("engine_client", i), } engine := &driver.EngineDriver{ - Log: c.log.New("engine", i), + Log: log.New("engine", i), RPC: client, - DL: c.l1Downloader, + DL: l1Downloader, SyncRef: rollupSync.SyncSource{ L1: l1CanonicalChain, L2: client, }, EngineDriverState: driver.EngineDriverState{Genesis: genesis}, } - c.l2Engines = append(c.l2Engines, engine) + l2Engines = append(l2Engines, engine) } - // TODO: maybe spin up an API server - // (to get debug data, change runtime settings like logging, serve pprof, get peering info, node health, etc.) - - c.close = make(chan chan error) - - go c.RunNode() + n := &OpNode{ + log: log, + l1Source: l1Source, + l1Downloader: l1Downloader, + l2Engines: l2Engines, + ctx: ctx, + close: make(chan chan error), + } - return nil + return n, nil } -func (c *OpNodeCmd) RunNode() { +func (c *OpNode) Start() error { c.log.Info("Starting OpNode") var unsub []func() @@ -205,32 +189,35 @@ func (c *OpNodeCmd) RunNode() { l1HeadsFeed.Subscribe(l1Heads) c.log.Info("Start-up complete!") - - for { - select { - case l1Head := <-l1Heads: - c.log.Info("New L1 head", "head", l1Head.Self, "parent", l1Head.Parent) - // TODO: maybe log other info on interval or other chain events (individual engines also log things) - case done := <-c.close: - c.log.Info("Closing OpNode") - // close all tasks - for _, f := range unsub { - f() - } - // close L1 data source - c.l1Source.Close() - // close L2 engines - for _, eng := range c.l2Engines { - eng.Close() + go func() { + + for { + select { + case l1Head := <-l1Heads: + c.log.Info("New L1 head", "head", l1Head.Self, "parent", l1Head.Parent) + // TODO: maybe log other info on interval or other chain events (individual engines also log things) + case done := <-c.close: + c.log.Info("Closing OpNode") + // close all tasks + for _, f := range unsub { + f() + } + // close L1 data source + c.l1Source.Close() + // close L2 engines + for _, eng := range c.l2Engines { + eng.Close() + } + // signal back everything closed without error + done <- nil + return } - // signal back everything closed without error - done <- nil - return } - } + }() + return nil } -func (c *OpNodeCmd) Close() error { +func (c *OpNode) Stop() error { if c.close != nil { done := make(chan error) c.close <- done diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 34c6e4ca5a6e..01cda256bdfa 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -110,22 +110,24 @@ func TestSystemE2E(t *testing.T) { l2GenesisHash := getGenesisHash(l2Client) // Rollup Node - node := rollupNode.OpNodeCmd{ - Genesis: rollupNode.GenesisConf{ - L2Hash: l2GenesisHash, - L1Hash: l1GenesisHash, - L1Num: 0, - }, - LogCmd: rollupNode.LogCmd{ - LogLvl: "warn", + nodeCfg := &rollupNode.Config{ + L2Hash: l2GenesisHash, + L1Hash: l1GenesisHash, + L1Num: 0, + L1NodeAddrs: []string{endpoint(cfg.l1.nodeConfig)}, + L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, + LogCfg: rollupNode.LogConfig{ + Level: "warn", Color: true, Format: "text", }, - L1NodeAddrs: []string{endpoint(cfg.l1.nodeConfig)}, - L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, } - err = node.Run(context.Background()) - defer node.Close() + node, err := rollupNode.New(context.Background(), nodeCfg) + if err != nil { + t.Fatalf("Failed to create the new node: %v", err) + } + err = node.Start() + defer node.Stop() if err != nil { t.Fatal(err) } From 43bab34c5dca9551ed314a05b1f02dbb8452fe79 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 7 Feb 2022 21:17:13 -0500 Subject: [PATCH 211/585] chore: add basic editorconfig file --- .editorconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000000..bfaafc5d2614 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +root = true + +# defaults +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.go] +indent_style = tab + +[*.{ts,js}] +indent_size = 2 From 86c7053c7f74d8668c0246df75c1000a178394b6 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Feb 2022 11:50:31 -0800 Subject: [PATCH 212/585] Update documentation to correct commands --- opnode/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opnode/README.md b/opnode/README.md index 309c99ce512c..c3a98f4420c5 100644 --- a/opnode/README.md +++ b/opnode/README.md @@ -16,7 +16,7 @@ go test ./opnode/... Options can be reviewed with: ```shell -./op run --help +./op --help ``` To start syncing the rollup: @@ -35,7 +35,7 @@ Specify genesis details: ```shell # websockets or IPC preferred for event notifications to improve sync, http RPC works with adaptive polling. -op node run \ +op \ --l1=ws://localhost:8546 --l2=ws//localhost:9001 \ --genesis.l1-num=.... --genesis.l1-hash=..... --genesis.l2-hash=.... ``` From fa3ab678ea39b5bb4fe51db8c1234321cda5d3a4 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Feb 2022 11:51:02 -0800 Subject: [PATCH 213/585] ref impl: Return node.Stop() error This fixes a lint. --- opnode/cmd/main.go | 3 +-- opnode/node/node.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 45e8b90dfabc..85bc1206e039 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -65,7 +65,6 @@ func RollupNodeMain(ctx *cli.Context) error { log.Error("Unable to start L2 Output Submitter", "error", err) return err } - defer n.Stop() log.Info("Rollup node started") @@ -78,7 +77,7 @@ func RollupNodeMain(ctx *cli.Context) error { }...) <-interruptChannel - return nil + return n.Stop() } diff --git a/opnode/node/node.go b/opnode/node/node.go index 8a4b77cd9a26..d4700f4d0ebf 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -48,7 +48,7 @@ type OpNode struct { l1Downloader l1.Downloader // actual downloader l2Engines []*driver.EngineDriver // engines to keep synced ctx context.Context // Embeded CTX to be removed - close chan chan error // Why chan of chans? + close chan chan error // Used to pass back the final error condition. } func (conf *Config) GetGenesis() rollup.Genesis { From 2deaf12a1128ea6529187dad38a19c027ab8ffa8 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Feb 2022 12:03:04 -0800 Subject: [PATCH 214/585] ref impl: Fix lint This makes a small change to how the node is stopped to no longer return and error. This also comments out some dead code (that will likely be added in later). --- opnode/cmd/main.go | 13 +++++++------ opnode/node/node.go | 18 ++++++------------ 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 85bc1206e039..f8b5d77acaf8 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -65,6 +65,7 @@ func RollupNodeMain(ctx *cli.Context) error { log.Error("Unable to start L2 Output Submitter", "error", err) return err } + defer n.Stop() log.Info("Rollup node started") @@ -77,7 +78,7 @@ func RollupNodeMain(ctx *cli.Context) error { }...) <-interruptChannel - return n.Stop() + return nil } @@ -146,11 +147,11 @@ func NewLogConfig(ctx *cli.Context) (node.LogConfig, error) { // Flags -const envVarPrefix = "ROLLUP_NODE_" - -func prefixEnvVar(name string) string { - return envVarPrefix + name -} +// Commented out for deadcode lint +// const envVarPrefix = "ROLLUP_NODE_" +// func prefixEnvVar(name string) string { +// return envVarPrefix + name +// } var Flags = []cli.Flag{ L1NodeAddrs, diff --git a/opnode/node/node.go b/opnode/node/node.go index d4700f4d0ebf..99b5f50ac90e 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -48,7 +48,7 @@ type OpNode struct { l1Downloader l1.Downloader // actual downloader l2Engines []*driver.EngineDriver // engines to keep synced ctx context.Context // Embeded CTX to be removed - close chan chan error // Used to pass back the final error condition. + done chan struct{} } func (conf *Config) GetGenesis() rollup.Genesis { @@ -126,7 +126,7 @@ func New(ctx context.Context, cfg *Config) (*OpNode, error) { l1Downloader: l1Downloader, l2Engines: l2Engines, ctx: ctx, - close: make(chan chan error), + done: make(chan struct{}), } return n, nil @@ -196,7 +196,7 @@ func (c *OpNode) Start() error { case l1Head := <-l1Heads: c.log.Info("New L1 head", "head", l1Head.Self, "parent", l1Head.Parent) // TODO: maybe log other info on interval or other chain events (individual engines also log things) - case done := <-c.close: + case <-c.done: c.log.Info("Closing OpNode") // close all tasks for _, f := range unsub { @@ -208,8 +208,6 @@ func (c *OpNode) Start() error { for _, eng := range c.l2Engines { eng.Close() } - // signal back everything closed without error - done <- nil return } } @@ -217,12 +215,8 @@ func (c *OpNode) Start() error { return nil } -func (c *OpNode) Stop() error { - if c.close != nil { - done := make(chan error) - c.close <- done - err := <-done - return err +func (c *OpNode) Stop() { + if c.done != nil { + close(c.done) } - return nil } From 5df588b5d5ed52d769c4446fd7044c1f641aed5e Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 8 Feb 2022 13:18:53 -0700 Subject: [PATCH 215/585] automate toc building --- meta/README.md | 1 + meta/linting.md | 10 ++ meta/markdown-style.md | 11 ++ meta/releases.md | 1 + package.json | 6 +- specs/README.md | 1 + specs/deposits.md | 15 +- specs/exec-engine.md | 18 ++ specs/glossary.md | 6 +- specs/rollup-node.md | 10 +- yarn.lock | 382 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 449 insertions(+), 12 deletions(-) diff --git a/meta/README.md b/meta/README.md index 4422908123a4..8a9f9f9d9d09 100644 --- a/meta/README.md +++ b/meta/README.md @@ -1,3 +1,4 @@ + # Meta Processes This directory describes processes that we use to build the specification. diff --git a/meta/linting.md b/meta/linting.md index 1645d61af596..a6bd46f77966 100644 --- a/meta/linting.md +++ b/meta/linting.md @@ -1,5 +1,14 @@ # Linting + + +**Table of Contents** + +- [Markdown](#markdown) +- [Go](#go) + + + ## Markdown See @@ -18,6 +27,7 @@ Justification for linting rules in [.markdownlint.json](/.markdownlint.json): yarn # Install dependencies yarn lint # Run linter yarn lint:links # Check links +yarn lint:toc # Update TOC docs ``` To check links, you'll need to install [lychee]. The [version ran in CI][lychee-ci] is 0.8.1, but diff --git a/meta/markdown-style.md b/meta/markdown-style.md index af0998f72ada..e6a40443bade 100644 --- a/meta/markdown-style.md +++ b/meta/markdown-style.md @@ -1,5 +1,16 @@ # Markdown Style Guide + + +**Table of Contents** + +- [Linting](#linting) +- [Links](#links) + - [Glossary](#glossary) +- [Internal (In-File) Links](#internal-in-file-links) + + + ## Linting Respect the [linting rules] (you can run the linter with `yarn lint`). diff --git a/meta/releases.md b/meta/releases.md index 53bff5b3a9c5..0167d8fe25c1 100644 --- a/meta/releases.md +++ b/meta/releases.md @@ -1,3 +1,4 @@ + # Release process 1. Confirm all release features are completed diff --git a/package.json b/package.json index 1e5e8808b0d5..0516385ed758 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,15 @@ "devDependencies": { "lint-staged": "11.0.0", "markdownlint": "^0.24.0", - "markdownlint-cli2": "^0.3.2" + "markdownlint-cli2": "^0.3.2", + "doctoc": "2.1.0" }, "scripts": { "setup": "yarn install && cargo install lychee", "lint": "yarn lint:fix && yarn lint:check", "lint:fix": "markdownlint-cli2-fix \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", "lint:check": "markdownlint-cli2 \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", - "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./opnode/README.md\" \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"" + "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./opnode/README.md\" \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"", + "lint:toc": "yarn doctoc --title=\"**Table of Contents**\" ./specs ./meta" } } diff --git a/specs/README.md b/specs/README.md index a7f9b96fc08e..e42866b75cc7 100644 --- a/specs/README.md +++ b/specs/README.md @@ -1,3 +1,4 @@ + # Optimism specs This directory contains the plain english specs for Optimism, an minimal optimistic rollup protocol diff --git a/specs/deposits.md b/specs/deposits.md index e57c48947c3c..bbcc6f1bd644 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -18,23 +18,26 @@ with the authorization and validation conditions on L2. **Vocabulary note**: *deposited transaction* refers specifically to an L2 transaction, while *deposit* can refer to the transaction at various stages (for instance when it is deposited on L1). -## Table of Contents + + +**Table of Contents** - [The Deposited Transaction Type](#the-deposited-transaction-type) - [Kinds of Deposited Transactions](#kinds-of-deposited-transactions) - - [Validation and Authorization of Deposited - Transaction](#validation-and-authorization-of-deposit-transaction-types) + - [Validation and Authorization of Deposited Transactions](#validation-and-authorization-of-deposited-transactions) - [Execution](#execution) - [Nonce Handling](#nonce-handling) - [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) - [Special Accounts on L2](#special-accounts-on-l2) - [L1 Attributes Depositor Account](#l1-attributes-depositor-account) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - - [L1 Attributes Predeployed Contract: Reference Implementation](#l1-attributes-predeployed-contract--reference-implementation) + - [L1 Attributes Predeployed Contract: Reference Implementation](#l1-attributes-predeployed-contract-reference-implementation) - [User-Deposited Transactions](#user-deposited-transactions) - - [Deposit Feed Contract](#deposit-feed-contract) + - [Deposit Contract](#deposit-contract) - [Address Aliasing](#address-aliasing) - - [Deposit Feed Contract: Reference Implementation](#deposit-feed-contract--reference-implementation) + - [Deposit Feed Contract: Reference Implementation](#deposit-feed-contract-reference-implementation) + + ## The Deposited Transaction Type diff --git a/specs/exec-engine.md b/specs/exec-engine.md index c668c42b8317..f2faa59b96df 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -1,5 +1,23 @@ # L2 Execution Engine + + +**Table of Contents** + +- [Depositited transaction processing](#depositited-transaction-processing) + - [Deposited transaction boundaries](#deposited-transaction-boundaries) +- [Engine API](#engine-api) + - [`engine_forkchoiceUpdatedV1`](#engine_forkchoiceupdatedv1) + - [Extended PayloadAttributesV1](#extended-payloadattributesv1) + - [`engine_executePayloadV1`](#engine_executepayloadv1) + - [`engine_getPayloadV1`](#engine_getpayloadv1) +- [Networking](#networking) +- [Sync](#sync) + - [Happy-path sync](#happy-path-sync) + - [Worst-case sync](#worst-case-sync) + + + This document outlines the modifications, configuration and usage of a L1 execution engine for L2. ## Depositited transaction processing diff --git a/specs/glossary.md b/specs/glossary.md index 08315a2b5ccd..0c03d015498a 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -1,6 +1,8 @@ # Glossary -## Table of Contents + + +**Table of Contents** - [General Terms](#general-terms) - [Layer 1 (L1)](#layer-1-l1) @@ -35,6 +37,8 @@ - [Execution Engine Concepts](#execution-engine-concepts) - [Execution Engine](#execution-engine) + + ------------------------------------------------------------------------------------------------------------------------ # General Terms diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 38a91681c27c..8f0934dd6e43 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -35,21 +35,25 @@ L1 chain [re-organizes][g-reorg]. The part of the rollup node that derives the L2 chain is called the [rollup driver][g-rollup-driver]. This document is currently only concerned with the specification of the rollup driver. -## Table of Contents + + +**Table of Contents** - [L2 Chain Derivation](#l2-chain-derivation) - [From L1 Blocks to Payload Attributes](#from-l1-blocks-to-payload-attributes) - - [Reading L1 Inputs](#reading-l1-inputs) + - [Reading L1 inputs](#reading-l1-inputs) - [Encoding the L1 Attributes Deposited Transaction](#encoding-the-l1-attributes-deposited-transaction) - [Encoding User-Deposited Transactions](#encoding-user-deposited-transactions) - [Building the Payload Attributes](#building-the-payload-attributes) - - [From Payload Attributes to L2 Block](#from-payload-attributes-to-L2-block) + - [From Payload Attributes to L2 Block](#from-payload-attributes-to-l2-block) - [Inductive Derivation Step](#inductive-derivation-step) - [Engine API Error Handling](#engine-api-error-handling) - [Finalization Guarantees](#finalization-guarantees) - [Whole L2 Chain Derivation](#whole-l2-chain-derivation) - [Handling L1 Re-Orgs](#handling-l1-re-orgs) + + # L2 Chain Derivation [l2-chain-derivation]: #l2-chain-derivation diff --git a/yarn.lock b/yarn.lock index 26571ba6f50a..de6f8ceb9ac5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -44,6 +44,24 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@textlint/ast-node-types@^4.2.5": + version "4.4.3" + resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-4.4.3.tgz#fdba16e8126cddc50f45433ce7f6c55e7829566c" + integrity sha512-qi2jjgO6Tn3KNPGnm6B7p6QTEPvY95NFsIAaJuwbulur8iJUEenp1OnoUfiDaC/g2WPPEFkcfXpmnu8XEMFo2A== + +"@textlint/markdown-to-ast@~6.1.7": + version "6.1.7" + resolved "https://registry.yarnpkg.com/@textlint/markdown-to-ast/-/markdown-to-ast-6.1.7.tgz#7ed9561b577bcd5307c8ef82660bc568ce31647e" + integrity sha512-B0QtokeQR4a9+4q0NQr8T9l7A1fFihTN5Ze57tVgqW+3ymzXEouh8DvPHeNQ4T6jEkAThvdjk95mxAMpGRJ79w== + dependencies: + "@textlint/ast-node-types" "^4.2.5" + debug "^4.1.1" + remark-frontmatter "^1.2.0" + remark-parse "^5.0.0" + structured-source "^3.0.2" + traverse "^0.6.6" + unified "^6.1.6" + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -57,6 +75,13 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +anchor-markdown-header@~0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz#045063d76e6a1f9cd327a57a0126aa0fdec371a7" + integrity sha1-BFBj125qH5zTJ6V6ASaqD97Dcac= + dependencies: + emoji-regex "~6.1.0" + ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -103,6 +128,16 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + +boundary@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/boundary/-/boundary-1.0.1.tgz#4d67dc2602c0cc16dd9bce7ebf87e948290f5812" + integrity sha1-TWfcJgLAzBbdm85+v4fpSCkPWBI= + braces@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -132,6 +167,21 @@ chalk@^4.1.0, chalk@^4.1.1: ansi-styles "^4.1.0" supports-color "^7.1.0" +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -157,6 +207,11 @@ clone@^2.1.2: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= +collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" + integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -211,6 +266,13 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +debug@^4.1.1: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" @@ -230,11 +292,65 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +doctoc@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctoc/-/doctoc-2.1.0.tgz#e7cbcd1f9e65519c295461423b2e7195d9e0d7ab" + integrity sha512-0darEVEuWKLyIlpGOzE5cILf/pgUu25qUs6YwCqLqfxb8+3b9Cl4iakA8vwYrBQOkJ5SwpHKEPVMu2KOMrTA7A== + dependencies: + "@textlint/markdown-to-ast" "~6.1.7" + anchor-markdown-header "~0.5.7" + htmlparser2 "~4.1.0" + minimist "~1.2.5" + underscore "~1.12.1" + update-section "~0.3.3" + +dom-serializer@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" + integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== + +domhandler@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" + integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== + dependencies: + domelementtype "^2.0.1" + +domhandler@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" + integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.0.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@~6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.3.tgz#ec79a3969b02d2ecf2b72254279bf99bc7a83932" + integrity sha1-7HmjlpsC0uzytyJUJ5v5m8eoOTI= + enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -242,6 +358,11 @@ enquirer@^2.3.6: dependencies: ansi-colors "^4.1.1" +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + entities@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" @@ -274,6 +395,11 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + fast-glob@^3.1.1: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" @@ -292,6 +418,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fault@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -299,6 +432,11 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -338,6 +476,16 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +htmlparser2@~4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" + integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + domutils "^2.0.0" + entities "^2.0.0" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -361,11 +509,39 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== +inherits@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-buffer@^1.1.4: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -383,6 +559,11 @@ is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -393,6 +574,11 @@ is-obj@^1.0.1: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -408,6 +594,16 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" + integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== + +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -488,6 +684,11 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" + integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== + markdown-it@12.2.0: version "12.2.0" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.2.0.tgz#091f720fd5db206f80de7a8d1f1a7035fd0d38db" @@ -557,6 +758,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +minimist@~1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -595,6 +801,18 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-entities@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" + integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -632,6 +850,45 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +remark-frontmatter@^1.2.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-1.3.3.tgz#67ec63c89da5a84bb793ecec166e11b4eb47af10" + integrity sha512-fM5eZPBvu2pVNoq3ZPW22q+5Ativ1oLozq2qYt9I2oNyxiUd/tDl0iLLntEVAegpZIslPWg1brhcP1VsaSVUag== + dependencies: + fault "^1.0.1" + xtend "^4.0.1" + +remark-parse@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" + integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA== + dependencies: + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^1.1.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^1.0.0" + vfile-location "^2.0.0" + xtend "^4.0.1" + +repeat-string@^1.5.4: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +replace-ext@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -709,6 +966,11 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" + integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== + string-argv@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -749,6 +1011,13 @@ strip-json-comments@~3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +structured-source@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/structured-source/-/structured-source-3.0.2.tgz#dd802425e0f53dc4a6e7aca3752901a1ccda7af5" + integrity sha1-3YAkJeD1PcSm56yjdSkBoczaevU= + dependencies: + boundary "^1.0.1" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -775,6 +1044,26 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +traverse@^0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= + +trim-trailing-lines@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" + integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + tslib@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" @@ -790,6 +1079,89 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== +underscore@~1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" + integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== + +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" + integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== + dependencies: + inherits "^2.0.0" + xtend "^4.0.0" + +unified@^6.1.6: + version "6.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" + integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^1.1.0" + trough "^1.0.0" + vfile "^2.0.0" + x-is-string "^0.1.0" + +unist-util-is@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" + integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== + +unist-util-remove-position@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz#ec037348b6102c897703eee6d0294ca4755a2020" + integrity sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A== + dependencies: + unist-util-visit "^1.1.0" + +unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" + integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== + +unist-util-visit-parents@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" + integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== + dependencies: + unist-util-is "^3.0.0" + +unist-util-visit@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" + integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== + dependencies: + unist-util-visit-parents "^2.0.0" + +update-section@~0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/update-section/-/update-section-0.3.3.tgz#458f17820d37820dc60e20b86d94391b00123158" + integrity sha1-RY8Xgg03gg3GDiC4bZQ5GwASMVg= + +vfile-location@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" + integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== + +vfile-message@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1" + integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA== + dependencies: + unist-util-stringify-position "^1.1.1" + +vfile@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" + integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== + dependencies: + is-buffer "^1.1.4" + replace-ext "1.0.0" + unist-util-stringify-position "^1.0.0" + vfile-message "^1.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -815,6 +1187,16 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +x-is-string@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" + integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= + +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + yaml@^1.10.0, yaml@~1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" From ab10a96f0ab62b9fa8785cd2e5e42750930ba4cf Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 8 Feb 2022 13:31:31 -0700 Subject: [PATCH 216/585] CI: enforce TOC to be up to date --- .github/workflows/lint.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 05107451c23e..1ca984e0debf 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -40,6 +40,10 @@ jobs: - name: Lint run: yarn lint:check + - name: Toc check + # exit if there are changes (i.e. if the TOC changed) + run: "yarn lint:toc && if [[ `git status --porcelain` ]]; then exit 1; else exit 0; fi" + linkChecker: runs-on: ubuntu-latest steps: From fbd5714654613dfe2e683ea4bf5133ece490d2e7 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 8 Feb 2022 13:40:14 -0700 Subject: [PATCH 217/585] meta: update lint docs with doctoc link --- meta/linting.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meta/linting.md b/meta/linting.md index a6bd46f77966..45e7779829b9 100644 --- a/meta/linting.md +++ b/meta/linting.md @@ -40,6 +40,10 @@ You can install cargo (the Rust package manager) via [rustup]. [lychee-ci]: https://github.com/lycheeverse/lychee-action/blob/f76b8412c668f78311212d16d33c4784a7d8762c/Dockerfile [rustup]: https://www.rust-lang.org/tools/install +To update the TOC, we run [doctoc], installed through the dev-dependencies in `package.json`. + +[doctoc]: https://github.com/thlorenz/doctoc + ## Go See From 3a2e1889dc96aa1e510e5519a9e3d37a727c56c5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 8 Feb 2022 15:58:47 -0500 Subject: [PATCH 218/585] chore: newline and end of makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b229a53e5bfe..e3b2003d0419 100644 --- a/Makefile +++ b/Makefile @@ -4,4 +4,4 @@ opnode: clean: rm -rf ./bin -.PHONY: clean \ No newline at end of file +.PHONY: clean From 6cf504bca3077ee94abb896e9b6e0481fc0b5c3b Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 8 Feb 2022 15:12:04 -0700 Subject: [PATCH 219/585] meta: clean up toc script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0516385ed758..dbc93d2248db 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,6 @@ "lint:fix": "markdownlint-cli2-fix \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", "lint:check": "markdownlint-cli2 \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./opnode/README.md\" \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"", - "lint:toc": "yarn doctoc --title=\"**Table of Contents**\" ./specs ./meta" + "lint:toc": "doctoc --title=\"**Table of Contents**\" ./specs ./meta" } } From 594558074c460305e8bc969ff23ca10bca01bf5b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 9 Feb 2022 11:31:48 -0800 Subject: [PATCH 220/585] ref impl: Hardcode own version Set the vesion to 0.0.0-dev. Better version handling to come. --- opnode/cmd/main.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index f8b5d77acaf8..2d211dd1da78 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -9,20 +9,29 @@ import ( "os/signal" "syscall" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" "github.com/urfave/cli" - - "github.com/ethereum-optimism/optimistic-specs/opnode/node" ) var ( - Version = "" - GitCommit = "" - GitDate = "" + Version = "0.0.0" + // GitCommit = "" + // GitDate = "" + VersionMeta = "dev" ) +// VersionWithMeta holds the textual version string including the metadata. +var VersionWithMeta = func() string { + v := Version + if VersionMeta != "" { + v += "-" + VersionMeta + } + return v +}() + func main() { // Set up logger with a default INFO level in case we fail to parse flags, // otherwise the final critical log won't show what the parsing error was. @@ -35,7 +44,7 @@ func main() { app := cli.NewApp() app.Flags = Flags - app.Version = fmt.Sprintf("%s-%s", Version, params.VersionWithCommit(GitCommit, GitDate)) // TODO: Don't use Geth's hardcoded versions + app.Version = VersionWithMeta app.Name = "opnode" app.Usage = "Optimism Rollup Node" app.Description = "The deposit only rollup node drives the L2 execution engine based on L1 deposits." From 49171509808abaeba711cd2299005c8a191ef2c1 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 9 Feb 2022 11:53:47 -0800 Subject: [PATCH 221/585] ref impl: Provide logger to Node This enables test loggers and easier log management in the node. --- opnode/cmd/main.go | 37 ++++++++++++++++++++----------------- opnode/node/node.go | 9 +-------- opnode/test/geth.go | 1 - opnode/test/system_test.go | 10 ++++------ 4 files changed, 25 insertions(+), 32 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 2d211dd1da78..0753260811da 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -63,7 +63,13 @@ func RollupNodeMain(ctx *cli.Context) error { log.Error("Unable to create the rollup node config", "error", err) return err } - n, err := node.New(context.Background(), cfg) + logCfg, err := NewLogConfig(ctx) + if err != nil { + log.Error("Unable to create the log config", "error", err) + return err + } + + n, err := node.New(context.Background(), cfg, logCfg.NewLogger()) if err != nil { log.Error("Unable to create the rollup node", "error", err) return err @@ -122,36 +128,33 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) { if err != nil { return nil, fmt.Errorf("Could not decode L1Hash: %w", err) } - logCfg, err := NewLogConfig(ctx) - if err != nil { - return nil, err - } - - return &node.Config{ + cfg := &node.Config{ /* Required Flags */ L1NodeAddrs: ctx.GlobalStringSlice(L1NodeAddrs.Name), L2EngineAddrs: ctx.GlobalStringSlice(L2EngineAddrs.Name), L2Hash: L2Hash, L1Hash: L1Hash, L1Num: ctx.GlobalUint64(GenesisL2Hash.Name), - /* Optional Flags */ - LogCfg: logCfg, - }, nil + } + if err := cfg.Check(); err != nil { + return nil, err + } + return cfg, nil } // NewLogConfig creates a log config from the provided flags or environment variables. func NewLogConfig(ctx *cli.Context) (node.LogConfig, error) { - logCfg := node.DefaultLogConfig() // Done to set color based on terminal type - logCfg.Level = ctx.GlobalString(LogLevelFlag.Name) - logCfg.Format = ctx.GlobalString(LogFormatFlag.Name) + cfg := node.DefaultLogConfig() // Done to set color based on terminal type + cfg.Level = ctx.GlobalString(LogLevelFlag.Name) + cfg.Format = ctx.GlobalString(LogFormatFlag.Name) if ctx.IsSet(LogColorFlag.Name) { - logCfg.Color = ctx.GlobalBool(LogColorFlag.Name) + cfg.Color = ctx.GlobalBool(LogColorFlag.Name) } - if err := logCfg.Check(); err != nil { - return logCfg, err + if err := cfg.Check(); err != nil { + return cfg, err } - return logCfg, nil + return cfg, nil } // Flags diff --git a/opnode/node/node.go b/opnode/node/node.go index 99b5f50ac90e..6b5b0aa24469 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -29,16 +29,10 @@ type Config struct { L2Hash common.Hash // Genesis block hash of L2 L1Hash common.Hash // Block hash of L1 after (not incl.) which L1 starts deriving blocks L1Num uint64 // Block number of L1 matching the l1-hash - - LogCfg LogConfig } // Check verifies that the given configuration makes sense func (cfg *Config) Check() error { - err := cfg.LogCfg.Check() - if err != nil { - return fmt.Errorf("Error checking log sub-config: %w", err) - } return nil } @@ -59,11 +53,10 @@ func (conf *Config) GetGenesis() rollup.Genesis { } } -func New(ctx context.Context, cfg *Config) (*OpNode, error) { +func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { if err := cfg.Check(); err != nil { return nil, err } - log := cfg.LogCfg.NewLogger() l1Sources := make([]eth.L1Source, 0, len(cfg.L1NodeAddrs)) for i, addr := range cfg.L1NodeAddrs { // L1 exec engine: read-only, to update L2 consensus with diff --git a/opnode/test/geth.go b/opnode/test/geth.go index 822c3f6f81b0..746be4d11391 100644 --- a/opnode/test/geth.go +++ b/opnode/test/geth.go @@ -17,7 +17,6 @@ import ( // 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) (*node.Node, *eth.Ethereum, error) { - n, err := node.New(nodeCfg) if err != nil { n.Close() diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 01cda256bdfa..3c2de588b512 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -16,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" ) @@ -36,6 +38,7 @@ func endpoint(cfg *node.Config) string { // TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. // All nodes are run in process (but are the full nodes, not mocked or stubbed). func TestSystemE2E(t *testing.T) { + log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs // System Config cfg := &systemConfig{ mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness", @@ -116,13 +119,8 @@ func TestSystemE2E(t *testing.T) { L1Num: 0, L1NodeAddrs: []string{endpoint(cfg.l1.nodeConfig)}, L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, - LogCfg: rollupNode.LogConfig{ - Level: "warn", - Color: true, - Format: "text", - }, } - node, err := rollupNode.New(context.Background(), nodeCfg) + node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlTrace)) if err != nil { t.Fatalf("Failed to create the new node: %v", err) } From a1f270faab9c7ba870fe5dbb54bceceaa0aec082 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 9 Feb 2022 13:05:25 -0800 Subject: [PATCH 222/585] ref impl: Better Hex2Hash Function This uses the `UnmarshalText` method on common.Hash which does not supress errors. --- opnode/cmd/main.go | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 0753260811da..b876480598bb 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -2,8 +2,6 @@ package main import ( "context" - "encoding/hex" - "errors" "fmt" "os" "os/signal" @@ -97,25 +95,12 @@ func RollupNodeMain(ctx *cli.Context) error { } -// has0xPrefix validates str begins with '0x' or '0X'. -// Copied from geth -func has0xPrefix(str string) bool { - return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') -} - -// HexToHash is copied from Geth, but does not supress the error +// HexToHash takes a `0x` prefixed hex hash string and turns it into a hash. +// Errors are reported. func HexToHash(s string) (common.Hash, error) { - if has0xPrefix(s) { - s = s[2:] - } - bytes, err := hex.DecodeString(s) - if err != nil { - return common.Hash{}, fmt.Errorf("Could not decode hex hash: %w", err) - } - if len(bytes) != common.HashLength { - return common.Hash{}, errors.New("Invalid length for Hash") - } - return common.BytesToHash(bytes), nil + var x common.Hash + err := x.UnmarshalText([]byte(s)) + return x, err } // NewConfig creates a Config from the provided flags or environment variables. From cf5e1d720fbce81cdb865e9f8859782369f59c6b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Feb 2022 14:49:36 -0800 Subject: [PATCH 223/585] ref impl: Remove combined L1 sources L1 Sources are not guaranteed to synchronized with one another and the rollup node code is not built to re-synchronized the underlying nodes. --- opnode/cmd/main.go | 9 ++++---- opnode/eth/source.go | 46 -------------------------------------- opnode/node/node.go | 31 ++++++++++--------------- opnode/test/system_test.go | 2 +- 4 files changed, 18 insertions(+), 70 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index b876480598bb..efa60d325615 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -115,7 +115,7 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) { } cfg := &node.Config{ /* Required Flags */ - L1NodeAddrs: ctx.GlobalStringSlice(L1NodeAddrs.Name), + L1NodeAddr: ctx.GlobalString(L1NodeAddr.Name), L2EngineAddrs: ctx.GlobalStringSlice(L2EngineAddrs.Name), L2Hash: L2Hash, L1Hash: L1Hash, @@ -151,7 +151,7 @@ func NewLogConfig(ctx *cli.Context) (node.LogConfig, error) { // } var Flags = []cli.Flag{ - L1NodeAddrs, + L1NodeAddr, L2EngineAddrs, GenesisL2Hash, GenesisL1Hash, @@ -163,10 +163,11 @@ var Flags = []cli.Flag{ var ( /* Required Flags */ - L1NodeAddrs = cli.StringSliceFlag{ + L1NodeAddr = cli.StringFlag{ Name: "l1", - Usage: "Addresses of L1 User JSON-RPC endpoints to use (eth namespace required)", + Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)", Required: true, + Value: "http://127.0.0.1:8545", } L2EngineAddrs = cli.StringSliceFlag{ Name: "l2", diff --git a/opnode/eth/source.go b/opnode/eth/source.go index 368b2d5020af..4a92c47525ab 100644 --- a/opnode/eth/source.go +++ b/opnode/eth/source.go @@ -3,7 +3,6 @@ package eth import ( "context" "math/big" - "sync/atomic" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -88,48 +87,3 @@ type BlockByNumFn func(ctx context.Context, number *big.Int) (*types.Block, erro func (fn BlockByNumFn) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { return fn(ctx, number) } - -// CombinedL1Source implements round-robin between multiple L1 sources, -// to divide concurrent requests to multiple endpoints -type CombinedL1Source struct { - i uint32 // track the last used source - sources []L1Source -} - -func NewCombinedL1Source(sources []L1Source) L1Source { - if len(sources) == 0 { - panic("need at least 1 source") - } - return &CombinedL1Source{i: 0, sources: sources} -} - -func (cs *CombinedL1Source) nextSource() L1Source { - return cs.sources[atomic.AddUint32(&cs.i, 1)%uint32(len(cs.sources))] -} - -func (cs *CombinedL1Source) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return cs.nextSource().HeaderByHash(ctx, hash) -} - -func (cs *CombinedL1Source) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return cs.nextSource().HeaderByNumber(ctx, number) -} - -func (cs *CombinedL1Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { - // TODO: can't use multiple sources as consensus, or head may be conflicting too much - return cs.sources[0].SubscribeNewHead(ctx, ch) -} - -func (cs *CombinedL1Source) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - return cs.nextSource().TransactionReceipt(ctx, txHash) -} - -func (cs *CombinedL1Source) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return cs.nextSource().BlockByHash(ctx, hash) -} - -func (cs *CombinedL1Source) Close() { - for _, src := range cs.sources { - src.Close() - } -} diff --git a/opnode/node/node.go b/opnode/node/node.go index 6b5b0aa24469..84b9744f10a4 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -22,7 +22,7 @@ import ( type Config struct { // L1 and L2 nodes - L1NodeAddrs []string // Addresses of L1 User JSON-RPC endpoints to use (eth namespace required) + L1NodeAddr string // Address of L1 User JSON-RPC endpoint to use (eth namespace required) L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required) // Genesis Information @@ -57,27 +57,20 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { if err := cfg.Check(); err != nil { return nil, err } - l1Sources := make([]eth.L1Source, 0, len(cfg.L1NodeAddrs)) - for i, addr := range cfg.L1NodeAddrs { - // L1 exec engine: read-only, to update L2 consensus with - l1Node, err := rpc.DialContext(ctx, addr) - if err != nil { - // HTTP or WS RPC may create a disconnected client, RPC over IPC may fail directly - if l1Node == nil { - return nil, fmt.Errorf("failed to dial L1 address %d (%s): %v", i, addr, err) - } - log.Warn("failed to dial L1 address, but may connect later", "i", i, "addr", addr, "err", err) + + // L1 exec engine: read-only, to update L2 consensus with + l1Node, err := rpc.DialContext(ctx, cfg.L1NodeAddr) + if err != nil { + // HTTP or WS RPC may create a disconnected client, RPC over IPC may fail directly + if l1Node == nil { + return nil, fmt.Errorf("failed to dial L1 addres (%s): %v", cfg.L1NodeAddr, err) } - // TODO: we may need to authenticate the connection with L1 - // l1Node.SetHeader() - cl := ethclient.NewClient(l1Node) - l1Sources = append(l1Sources, cl) - } - if len(l1Sources) == 0 { - return nil, fmt.Errorf("need at least one L1 source endpoint, see --l1") + log.Warn("failed to dial L1 address, but may connect later", "addr", cfg.L1NodeAddr, "err", err) } - l1Source := eth.NewCombinedL1Source(l1Sources) + // TODO: we may need to authenticate the connection with L1 + // l1Node.SetHeader() + l1Source := ethclient.NewClient(l1Node) l1CanonicalChain := eth.CanonicalChain(l1Source) l1Downloader := l1.NewDownloader(l1Source) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 3c2de588b512..bc43ec170d8c 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -117,7 +117,7 @@ func TestSystemE2E(t *testing.T) { L2Hash: l2GenesisHash, L1Hash: l1GenesisHash, L1Num: 0, - L1NodeAddrs: []string{endpoint(cfg.l1.nodeConfig)}, + L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, } node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlTrace)) From 04b554237db5b5c04cc8a861212e647ac24dc330 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 1 Feb 2022 12:01:41 -0700 Subject: [PATCH 224/585] glossary: update Merkle Patricia Trie definition --- specs/glossary.md | 8 ++++---- specs/rollup-node.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index 0c03d015498a..7ac30c4a335d 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -9,7 +9,7 @@ - [Layer 2 (L2)](#layer-2-l2) - [Block](#block) - [EOA](#eoa) - - [Merkle Root](#merkle-root) + - [Merkle Patricia Trie](#merkle-patricia-trie) - [Chain Re-Organization](#chain-re-organization) - [Predeployed Contract ("Predeploy")](#predeployed-contract-predeploy) - [Receipt](#receipt) @@ -76,11 +76,11 @@ block, and output block properties, which are derived after executing the block' "Externally Owned Account", an Ethereum term to designate addresses operated by users, as opposed to contract addresses. -## Merkle Root +## Merkle Patricia Trie -[Merkle root]: glossary.md#merkle-roots +[mpt]: glossary.md#merkle-patricia-trie -The Merkle root is the root hash of a [Merkle Patricia tree] (MPT). A MPT is a sparse [trie], which is a tree-like +A [Merkle Patricia tree] (MPT) is a sparse [trie], which is a tree-like structure that maps keys to values. The root hash of a MPT is a commitment to the contents of the tree, which allows a proof to be constructed for any key-value mapping encoded in the tree. Such a proof is called a Merkle proof, and can be verified against the Merkle root. diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 8f0934dd6e43..b4cec17907ff 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -19,6 +19,7 @@ [g-l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract [g-depositing-call]: glossary.md#depositing-call [g-depositing-transaction]: glossary.md#depositing-transaction +[g-mpt]: glossary.md#merkle-patricia-trie The [rollup node][g-rollup-node] is the component responsible for [deriving the L2 chain][g-derivation] from L1 blocks (and their associated [receipts][g-receipts]). This process happens in two steps: @@ -49,6 +50,7 @@ currently only concerned with the specification of the rollup driver. - [Inductive Derivation Step](#inductive-derivation-step) - [Engine API Error Handling](#engine-api-error-handling) - [Finalization Guarantees](#finalization-guarantees) + - [From L2 Block to L2 Output Root](#from-l2-block-to-l2-output-root) - [Whole L2 Chain Derivation](#whole-l2-chain-derivation) - [Handling L1 Re-Orgs](#handling-l1-re-orgs) @@ -255,6 +257,46 @@ However, they can still be challenged by a fault proof until the end of the faul > **TODO** the spec doesn't encode the notion of fault proof yet, revisit this (and include links) when it does +## From L2 Block to L2 Output Root + +After processing a block the resulting outputs will need to be synchronized with L1 for trustless execution of +L2-to-L1 messaging, such as withdrawals. To synchronize outputs are merkleized: hashed in a structured form for minimal +proof cost to any piece of data. The merkle-structure is defined with [SSZ], a type system for merkleization and +serialization, used in L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. + +[SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md + +```python +class L2Output(Container): + state_root: Bytes32 + withdrawal_storage_root: Bytes32 + latest_block: ExecutionPayload # includes block-hash + history_accumulator_root: Bytes32 # Not functional yet + extension: Bytes32 +``` + +The `state_root` is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts, +also found in `latest_block.state_root`: this field is frequently used and thus elevated closer to the L2 output root, +reducing the merkle proof depth and thus the cost of usage. + +The `withdrawal_storage_root` elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of L2 Withdrawal contract storage. +Instead of a MPT proof to the Withdrawal contract account in the account trie, +one can directly access the MPT storage trie root, thus reducing the verification cost of withdrawals on L1. + +The `latest_block` is an execution-layer block of L2, represented as the [`ExecutionPayload`][ExecutionPayload] SSZ type +defined in L1. There may be multiple blocks per L2 output root, only the latest is presented. + +[ExecutionPayload]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayload + +The `history_accumulator_root` is a reserved field, elevating a storage variable of the L2 chain that maintains +the SSZ merkle root of an append-only `List[Bytes32, MAX_ITEM_COUNT]` (`keccak256` SSZ), +where each item is defined as `keccak256(l2_block_hash ++ l2_state_root)`, one per block of the L2 chain. +While reserved, a zeroed `Bytes32` is used instead. +This is a work-in-progress, see [issue 181](https://github.com/ethereum-optimism/optimistic-specs/issues/181). + +The `extension` is a zeroed `Bytes32`, to be substituted with a SSZ container to extend merkleized information in future +upgrades. This keeps the static merkle structure forwards-compatible. + ## Whole L2 Chain Derivation The previous two sections presents an inductive process: given that we know the "current" L2 block, well as the next L1 From bea0e8e5e66852133283f885781321409d868cb8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 4 Feb 2022 10:17:36 -0700 Subject: [PATCH 225/585] specs: l2 output root / merkle root wording fixes --- specs/glossary.md | 4 ++-- specs/rollup-node.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index 7ac30c4a335d..943dfe8bebf3 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -80,8 +80,8 @@ block, and output block properties, which are derived after executing the block' [mpt]: glossary.md#merkle-patricia-trie -A [Merkle Patricia tree] (MPT) is a sparse [trie], which is a tree-like -structure that maps keys to values. The root hash of a MPT is a commitment to the contents of the tree, which allows a +A [Merkle Patricia tree] (MPT) is a sparse trie, which is a tree-like structure that maps keys to values. +The root hash of a MPT is a commitment to the contents of the tree, which allows a proof to be constructed for any key-value mapping encoded in the tree. Such a proof is called a Merkle proof, and can be verified against the Merkle root. diff --git a/specs/rollup-node.md b/specs/rollup-node.md index b4cec17907ff..f91998268e9f 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -260,9 +260,9 @@ However, they can still be challenged by a fault proof until the end of the faul ## From L2 Block to L2 Output Root After processing a block the resulting outputs will need to be synchronized with L1 for trustless execution of -L2-to-L1 messaging, such as withdrawals. To synchronize outputs are merkleized: hashed in a structured form for minimal -proof cost to any piece of data. The merkle-structure is defined with [SSZ], a type system for merkleization and -serialization, used in L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. +L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree structured form for minimal proof cost to any +piece of data. This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in +L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. [SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md From 1e06ec633bf6ddbca2b9b8e8d2eb51c329f73057 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 9 Feb 2022 16:38:39 -0700 Subject: [PATCH 226/585] glossary: update merkle patricia trie references --- specs/glossary.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index 943dfe8bebf3..ac2cf8a0ffb6 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -68,7 +68,7 @@ description of these properties can be found in code comments [here][nano-header It is useful to distinguish between input block properties, which are known before executing the transactions in the block, and output block properties, which are derived after executing the block's transactions. These include various -[Merkle roots][Merkle root] that notably commit to the L2 state and to the log events emitted during the execution. +[Merkle Patricia Trie roots][mpt] that notably commit to the L2 state and to the log events emitted during the execution. ## EOA @@ -80,7 +80,7 @@ block, and output block properties, which are derived after executing the block' [mpt]: glossary.md#merkle-patricia-trie -A [Merkle Patricia tree] (MPT) is a sparse trie, which is a tree-like structure that maps keys to values. +A [Merkle Patricia Trie (MPT)][mpt-details] is a sparse trie, which is a tree-like structure that maps keys to values. The root hash of a MPT is a commitment to the contents of the tree, which allows a proof to be constructed for any key-value mapping encoded in the tree. Such a proof is called a Merkle proof, and can be verified against the Merkle root. @@ -112,8 +112,8 @@ Optimism has the following predeploys: A receipt is an output generated by a transaction, comprising a status code, the amount of gas used, a list of log entries, and a [bloom filter] indexing these entries. Log entries are most notably used to encode [Solidity events]. -Receipts are not stored in blocks, but blocks store a [Merkle root] for a tree containing the receipt for every -transaction in the block. +Receipts are not stored in blocks, but blocks store a [Merkle Patricia Trie root][mpt] for a tree containing the receipt +for every transaction in the block. Receipts are specified in the [yellow paper (pdf)][yellow] section 4.3.1. @@ -250,8 +250,8 @@ The *deposit contract* is qn [L1] contract to which [EOAs][EOA] and contracts ma emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. Advanced note: the deposits are not stored in calldata because they can be sent by contracts, in which case the calldata -is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 -block. +is part of the *internal* execution between contracts, and this intermediate calldata is not captured in one of the +[Merkle Patricia Trie roots][mpt] included in the L1 block. cf. [Deposits Specification](deposits.md) @@ -362,7 +362,7 @@ In these specifications, "execution engine" always refer to the L2 execution eng - cf. [Execution Engine Specification](exec-engine.md) -[Merkle Patricia tree]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md +[mpt-details]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md [trie]: https://en.wikipedia.org/wiki/Trie [bloom filter]: https://en.wikipedia.org/wiki/Bloom_filter [Solidity events]: https://docs.soliditylang.org/en/latest/contracts.html?highlight=events#events From 0d795abb0904184467ed319525de3500a87dab60 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 9 Feb 2022 16:54:06 -0700 Subject: [PATCH 227/585] rollup node spec: update l2 output root specs with review suggestions from @norswap --- specs/rollup-node.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index f91998268e9f..fa093437265a 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -260,8 +260,9 @@ However, they can still be challenged by a fault proof until the end of the faul ## From L2 Block to L2 Output Root After processing a block the resulting outputs will need to be synchronized with L1 for trustless execution of -L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree structured form for minimal proof cost to any -piece of data. This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in +L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree-structured form which minimizes the cost of +proving any piece of data captured by the outputs. +This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. [SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md @@ -269,14 +270,15 @@ L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas cos ```python class L2Output(Container): state_root: Bytes32 - withdrawal_storage_root: Bytes32 - latest_block: ExecutionPayload # includes block-hash + withdrawal_storage_root: Bytes32 # TODO: withdrawals specifcation work-in-progress + latest_block: ExecutionPayload # includes block hash history_accumulator_root: Bytes32 # Not functional yet extension: Bytes32 ``` The `state_root` is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts, also found in `latest_block.state_root`: this field is frequently used and thus elevated closer to the L2 output root, +as opposed to retrieving it from the pre-image of the block in `latest_block`, reducing the merkle proof depth and thus the cost of usage. The `withdrawal_storage_root` elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of L2 Withdrawal contract storage. @@ -289,17 +291,18 @@ defined in L1. There may be multiple blocks per L2 output root, only the latest [ExecutionPayload]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayload The `history_accumulator_root` is a reserved field, elevating a storage variable of the L2 chain that maintains -the SSZ merkle root of an append-only `List[Bytes32, MAX_ITEM_COUNT]` (`keccak256` SSZ), +the [SSZ] merkle root of an append-only `List[Bytes32, MAX_ITEM_COUNT]` (`keccak256` [SSZ] hash-tree-root), where each item is defined as `keccak256(l2_block_hash ++ l2_state_root)`, one per block of the L2 chain. While reserved, a zeroed `Bytes32` is used instead. This is a work-in-progress, see [issue 181](https://github.com/ethereum-optimism/optimistic-specs/issues/181). +`MAX_ITEM_COUNT` and/or other parameters will be defined in the withdrawals milestone. The `extension` is a zeroed `Bytes32`, to be substituted with a SSZ container to extend merkleized information in future upgrades. This keeps the static merkle structure forwards-compatible. ## Whole L2 Chain Derivation -The previous two sections presents an inductive process: given that we know the "current" L2 block, well as the next L1 +The previous two sections present an inductive process: given that we know the "current" L2 block, well as the next L1 block, then we can derive [payload attributes] for the next L1 block, and from that the next L2 block. To derive the whole L2 chain from scratch, we simply start with the L2 genesis block as the current L2 block, and the From ba8d44cb776322aadb95f9ffecd939f271896383 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 9 Feb 2022 17:12:39 -0700 Subject: [PATCH 228/585] proposals: separate l2 output root proposals section --- specs/README.md | 1 + specs/proposals.md | 65 ++++++++++++++++++++++++++++++++++++++++++++ specs/rollup-node.md | 48 ++------------------------------ 3 files changed, 69 insertions(+), 45 deletions(-) create mode 100644 specs/proposals.md diff --git a/specs/README.md b/specs/README.md index e42866b75cc7..1d38e5d7cffe 100644 --- a/specs/README.md +++ b/specs/README.md @@ -9,6 +9,7 @@ that maintains 1:1 compatibility with Ethereum. - [Glossary](glossary.md) - [Deposits](deposits.md) - [Execution Engine](exec-engine.md) +- [L2 output root Proposals](proposals.md) - [Rollup Node](rollup-node.md) ## Design Goals diff --git a/specs/proposals.md b/specs/proposals.md new file mode 100644 index 000000000000..e51540b47de6 --- /dev/null +++ b/specs/proposals.md @@ -0,0 +1,65 @@ +# L2 output root Proposals Specification + + +[g-rollup-node]: glossary.md#rollup-node + + +After processing one or more blocks the outputs will need to be synchronized with L1 for trustless execution of +L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree-structured form which minimizes the cost of +proving any piece of data captured by the outputs. +Proposers submit the output roots to L1 and can be contested with a fault proof, +with a bond at stake if the proof is wrong. + +*Note*: Although fault proof construction and verification [is implemented in Cannon][cannon], +the fault proof game specification and integration of a output-root challenger into the [rollup-node][g-rollup-node] +are part of later specification milestones. + +[cannon]: https://github.com/ethereum-optimism/cannon + +## Proposing output commitments + +The proposer's role is to construct and submit output commitments on a configurable interval to a contract on L1. + +TODO: describe integration with rollup node and L2 execution engine (see PR #179). + +TODO: link to contract specification/source of L2 Output oracle on L1. + +## L2 Output commitment construction + +This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in +L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. + +[SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md + +```python +class L2Output(Container): + state_root: Bytes32 + withdrawal_storage_root: Bytes32 # TODO: withdrawals specifcation work-in-progress + latest_block: ExecutionPayload # includes block hash + history_accumulator_root: Bytes32 # Not functional yet + extension: Bytes32 +``` + +The `state_root` is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts, +also found in `latest_block.state_root`: this field is frequently used and thus elevated closer to the L2 output root, +as opposed to retrieving it from the pre-image of the block in `latest_block`, +reducing the merkle proof depth and thus the cost of usage. + +The `withdrawal_storage_root` elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of L2 Withdrawal contract storage. +Instead of a MPT proof to the Withdrawal contract account in the account trie, +one can directly access the MPT storage trie root, thus reducing the verification cost of withdrawals on L1. + +The `latest_block` is an execution-layer block of L2, represented as the [`ExecutionPayload`][ExecutionPayload] SSZ type +defined in L1. There may be multiple blocks per L2 output root, only the latest is presented. + +[ExecutionPayload]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayload + +The `history_accumulator_root` is a reserved field, elevating a storage variable of the L2 chain that maintains +the [SSZ] merkle root of an append-only `List[Bytes32, MAX_ITEM_COUNT]` (`keccak256` [SSZ] hash-tree-root), +where each item is defined as `keccak256(l2_block_hash ++ l2_state_root)`, one per block of the L2 chain. +While reserved, a zeroed `Bytes32` is used instead. +This is a work-in-progress, see [issue 181](https://github.com/ethereum-optimism/optimistic-specs/issues/181). +`MAX_ITEM_COUNT` and/or other parameters will be defined in the withdrawals milestone. + +The `extension` is a zeroed `Bytes32`, to be substituted with a SSZ container to extend merkleized information in future +upgrades. This keeps the static merkle structure forwards-compatible. diff --git a/specs/rollup-node.md b/specs/rollup-node.md index fa093437265a..9b76ceceb71b 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -257,53 +257,11 @@ However, they can still be challenged by a fault proof until the end of the faul > **TODO** the spec doesn't encode the notion of fault proof yet, revisit this (and include links) when it does -## From L2 Block to L2 Output Root - -After processing a block the resulting outputs will need to be synchronized with L1 for trustless execution of -L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree-structured form which minimizes the cost of -proving any piece of data captured by the outputs. -This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in -L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. - -[SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md - -```python -class L2Output(Container): - state_root: Bytes32 - withdrawal_storage_root: Bytes32 # TODO: withdrawals specifcation work-in-progress - latest_block: ExecutionPayload # includes block hash - history_accumulator_root: Bytes32 # Not functional yet - extension: Bytes32 -``` - -The `state_root` is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts, -also found in `latest_block.state_root`: this field is frequently used and thus elevated closer to the L2 output root, -as opposed to retrieving it from the pre-image of the block in `latest_block`, -reducing the merkle proof depth and thus the cost of usage. - -The `withdrawal_storage_root` elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of L2 Withdrawal contract storage. -Instead of a MPT proof to the Withdrawal contract account in the account trie, -one can directly access the MPT storage trie root, thus reducing the verification cost of withdrawals on L1. - -The `latest_block` is an execution-layer block of L2, represented as the [`ExecutionPayload`][ExecutionPayload] SSZ type -defined in L1. There may be multiple blocks per L2 output root, only the latest is presented. - -[ExecutionPayload]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayload - -The `history_accumulator_root` is a reserved field, elevating a storage variable of the L2 chain that maintains -the [SSZ] merkle root of an append-only `List[Bytes32, MAX_ITEM_COUNT]` (`keccak256` [SSZ] hash-tree-root), -where each item is defined as `keccak256(l2_block_hash ++ l2_state_root)`, one per block of the L2 chain. -While reserved, a zeroed `Bytes32` is used instead. -This is a work-in-progress, see [issue 181](https://github.com/ethereum-optimism/optimistic-specs/issues/181). -`MAX_ITEM_COUNT` and/or other parameters will be defined in the withdrawals milestone. - -The `extension` is a zeroed `Bytes32`, to be substituted with a SSZ container to extend merkleized information in future -upgrades. This keeps the static merkle structure forwards-compatible. - ## Whole L2 Chain Derivation -The previous two sections present an inductive process: given that we know the "current" L2 block, well as the next L1 -block, then we can derive [payload attributes] for the next L1 block, and from that the next L2 block. +The [block derivation](#from-l1-blocks-to-payload-attributes) presents an inductive process: +given that we know the "current" L2 block, well as the next L1 block, +then we can derive [payload attributes] for the next L1 block, and from that the next L2 block. To derive the whole L2 chain from scratch, we simply start with the L2 genesis block as the current L2 block, and the block at height `L2_CHAIN_INCEPTION + 1` as the next L1 block. Then we iteratively apply the derivation process from the From f179fc85d3f5968e3172778c6fda553d0953f4fa Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 9 Feb 2022 17:17:27 -0700 Subject: [PATCH 229/585] rollup-node/proposals/glossary: linting fixes, add TOC --- specs/glossary.md | 4 ++-- specs/proposals.md | 12 ++++++++++-- specs/rollup-node.md | 1 - 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index ac2cf8a0ffb6..7e7da6abb60f 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -68,7 +68,7 @@ description of these properties can be found in code comments [here][nano-header It is useful to distinguish between input block properties, which are known before executing the transactions in the block, and output block properties, which are derived after executing the block's transactions. These include various -[Merkle Patricia Trie roots][mpt] that notably commit to the L2 state and to the log events emitted during the execution. +[Merkle Patricia Trie roots][mpt] that notably commit to the L2 state and to the log events emitted during execution. ## EOA @@ -250,7 +250,7 @@ The *deposit contract* is qn [L1] contract to which [EOAs][EOA] and contracts ma emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. Advanced note: the deposits are not stored in calldata because they can be sent by contracts, in which case the calldata -is part of the *internal* execution between contracts, and this intermediate calldata is not captured in one of the +is part of the *internal* execution between contracts, and this intermediate calldata is not captured in one of the [Merkle Patricia Trie roots][mpt] included in the L1 block. cf. [Deposits Specification](deposits.md) diff --git a/specs/proposals.md b/specs/proposals.md index e51540b47de6..d3a4866fedd1 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -3,6 +3,14 @@ [g-rollup-node]: glossary.md#rollup-node + + +**Table of Contents** + +- [Proposing L2 output commitments](#proposing-l2-output-commitments) +- [L2 output commitment construction](#l2-output-commitment-construction) + + After processing one or more blocks the outputs will need to be synchronized with L1 for trustless execution of L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree-structured form which minimizes the cost of @@ -16,7 +24,7 @@ are part of later specification milestones. [cannon]: https://github.com/ethereum-optimism/cannon -## Proposing output commitments +## Proposing L2 output commitments The proposer's role is to construct and submit output commitments on a configurable interval to a contract on L1. @@ -24,7 +32,7 @@ TODO: describe integration with rollup node and L2 execution engine (see PR #179 TODO: link to contract specification/source of L2 Output oracle on L1. -## L2 Output commitment construction +## L2 output commitment construction This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 9b76ceceb71b..8ce612f1fffc 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -50,7 +50,6 @@ currently only concerned with the specification of the rollup driver. - [Inductive Derivation Step](#inductive-derivation-step) - [Engine API Error Handling](#engine-api-error-handling) - [Finalization Guarantees](#finalization-guarantees) - - [From L2 Block to L2 Output Root](#from-l2-block-to-l2-output-root) - [Whole L2 Chain Derivation](#whole-l2-chain-derivation) - [Handling L1 Re-Orgs](#handling-l1-re-orgs) From 07b504b2ca7f71555808e61d6020874a694cab1c Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Feb 2022 15:21:39 -0800 Subject: [PATCH 230/585] ref impl: Cleanup driver package This is simplifying the entrypoints and number of structs. --- opnode/node/node.go | 29 +++------ opnode/rollup/driver/driver.go | 110 ++++++++++++++++++++++++++++++++- opnode/rollup/driver/loop.go | 2 +- opnode/rollup/driver/state.go | 4 +- 4 files changed, 122 insertions(+), 23 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index 3b8f04bfa5af..bbdc306ba877 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/driver" - rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -38,9 +37,9 @@ func (cfg *Config) Check() error { type OpNode struct { log log.Logger - l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) - l2Engines []*driver.EngineDriver // engines to keep synced - ctx context.Context // Embeded CTX to be removed + l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) + l2Engines []*driver.DriverV2 // engines to keep synced + ctx context.Context // Embeded CTX to be removed done chan struct{} } @@ -71,7 +70,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { // l1Node.SetHeader() l1Source := l1.NewSource(ethclient.NewClient(l1Node)) genesis := cfg.GetGenesis() - var l2Engines []*driver.EngineDriver + var l2Engines []*driver.DriverV2 for i, addr := range cfg.L2EngineAddrs { // L2 exec engine: updated by this OpNode (L2 consensus layer node) backend, err := rpc.DialContext(ctx, addr) @@ -88,16 +87,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { EthBackend: ethclient.NewClient(backend), Log: log.New("engine_client", i), } - engine := &driver.EngineDriver{ - Log: log.New("engine", i), - RPC: client, - DL: l1Source, - SyncRef: rollupSync.SyncSource{ - L1: l1Source, - L2: client, - }, - EngineDriverState: driver.EngineDriverState{Genesis: genesis}, - } + engine := driver.NewDriver(client, l1Source, log.New("engine", i), genesis) l2Engines = append(l2Engines, engine) } @@ -139,8 +129,8 @@ func (c *OpNode) Start() error { for _, eng := range c.l2Engines { // Request initial head update, default to genesis otherwise reqCtx, reqCancel := context.WithTimeout(c.ctx, time.Second*10) - if !eng.RequestUpdate(reqCtx, eng.Log, eng) { - eng.Log.Error("failed to fetch engine head, defaulting to genesis") + if !eng.RequestUpdate(reqCtx, c.log, eng) { + c.log.Error("failed to fetch engine head, defaulting to genesis") eng.UpdateHead(eng.Genesis.L1, eng.Genesis.L2) } reqCancel() @@ -149,8 +139,9 @@ func (c *OpNode) Start() error { l1SubCh := make(chan eth.HeadSignal, 10) l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine - engDriveSub := eng.Drive(c.ctx, l1SubCh) - handleUnsubscribe(engDriveSub, "engine driver unexpectedly failed") + eng.Start(context.TODO(), l1SubCh) + // engDriveSub := eng.Drive(c.ctx, l1SubCh) + // handleUnsubscribe(engDriveSub, "engine driver unexpectedly failed") } // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 64a9c290d541..4cf920225b0e 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -3,11 +3,14 @@ package driver import ( "context" "sync" + "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/event" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l1" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum/log" @@ -43,6 +46,7 @@ type EngineDriver struct { EngineDriverState } +// ENTRYPOINT func (e *EngineDriver) Drive(ctx context.Context, l1Heads <-chan eth.HeadSignal) ethereum.Subscription { e.driveLock.Lock() defer e.driveLock.Unlock() @@ -50,7 +54,7 @@ func (e *EngineDriver) Drive(ctx context.Context, l1Heads <-chan eth.HeadSignal) return e.driveSub } - e.driveSub = event.NewSubscription(NewDriverLoop(ctx, &e.EngineDriverState, e.Log, l1Heads, e)) + e.driveSub = event.NewSubscription(newDriverLoop(ctx, &e.EngineDriverState, e.Log, l1Heads, e)) return e.driveSub } @@ -70,3 +74,107 @@ func (e *EngineDriver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, re func (e *EngineDriver) Close() { e.driveSub.Unsubscribe() } + +func (e *DriverV2) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { + refL1, refL2, _, err = e.syncRef.RefByL2Num(ctx, nil, &e.genesis) + return +} + +func (e *DriverV2) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { + return rollupSync.FindSyncStart(ctx, e.syncRef, &e.genesis) +} + +func (e *DriverV2) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { + return DriverStep(ctx, e.log, e.rpc, e.dl, nextRefL1, refL2, finalized.Hash) +} + +type DriverV2 struct { + log log.Logger + rpc DriverAPI + syncRef rollupSync.SyncReference + dl Downloader + l1Heads <-chan eth.HeadSignal + done chan chan error + genesis rollup.Genesis + EngineDriverState +} + +func NewDriver(l2 DriverAPI, l1 l1.Source, log log.Logger, genesis rollup.Genesis) *DriverV2 { + return &DriverV2{ + log: log, + rpc: l2, + syncRef: rollupSync.SyncSource{L1: l1, L2: l2}, + dl: l1, + done: make(chan chan error), + genesis: genesis, + EngineDriverState: EngineDriverState{Genesis: genesis}, + } +} + +func (d *DriverV2) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error { + d.l1Heads = l1Heads + go d.loop(ctx) + return nil +} +func (d *DriverV2) Close() error { + ec := make(chan error) + d.done <- ec + err := <-ec + return err +} + +func (d *DriverV2) loop(ctx context.Context) error { + backoff := cold + syncTicker := time.NewTicker(cold) + l2HeadPoll := time.NewTicker(time.Second * 14) + + // exponential backoff, add 10% each step, up to max. + syncBackoff := func() { + backoff += backoff / 10 + if backoff > max { + backoff = max + } + syncTicker.Reset(backoff) + } + syncQuickly := func() { + syncTicker.Reset(hot) + backoff = cold + } + onL2Update := func() { + // And we want to slow down requesting the L2 engine for its head (we just changed it ourselves) + // Request head if we don't successfully change it in the next 14 seconds. + l2HeadPoll.Reset(time.Second * 14) + } + defer syncTicker.Stop() + defer l2HeadPoll.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-d.done: + return nil + case <-l2HeadPoll.C: + ctx, cancel := context.WithTimeout(ctx, time.Second*4) + if d.RequestUpdate(ctx, d.log, d) { + onL2Update() + } + cancel() + continue + case l1HeadSig := <-d.l1Heads: + if d.NotifyL1Head(ctx, d.log, l1HeadSig, d) { + syncQuickly() + } + continue + case <-syncTicker.C: + // If already synced, or in case of failure, we slow down + syncBackoff() + if d.RequestSync(ctx, d.log, d) { + // Successfully stepped toward target. Continue quickly if we are not there yet + syncQuickly() + onL2Update() + } + } + } + +} diff --git a/opnode/rollup/driver/loop.go b/opnode/rollup/driver/loop.go index 0f9b6f162135..8356db2a7336 100644 --- a/opnode/rollup/driver/loop.go +++ b/opnode/rollup/driver/loop.go @@ -17,7 +17,7 @@ const cold = time.Second * 8 // at least try every minute to sync, even if things are going well const max = time.Minute -func NewDriverLoop(ctx context.Context, state StateMachine, log log.Logger, l1Heads <-chan eth.HeadSignal, driver Driver) func(quit <-chan struct{}) error { +func newDriverLoop(ctx context.Context, state stateMachine, log log.Logger, l1Heads <-chan eth.HeadSignal, driver Driver) func(quit <-chan struct{}) error { backoff := cold syncTicker := time.NewTicker(cold) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index e6a9ed36f8cf..6e37f2d97652 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -9,8 +9,8 @@ import ( "github.com/ethereum/go-ethereum/log" ) -// StateMachine provides control over the driver state, when given control over the Driver actions. -type StateMachine interface { +// stateMachine provides control over the driver state, when given control over the Driver actions. +type stateMachine interface { // RequestUpdate tries to update the state-machine with the driver head information. // If the state-machine changed, considering the engine L1 and L2 head, it will return true. False otherwise. RequestUpdate(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) From 4224e0fbb916a49eb472521482ee35e2f75a964b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Feb 2022 15:03:46 -0800 Subject: [PATCH 231/585] Remove function adapter for CanonicalChain --- opnode/eth/canonical.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/opnode/eth/canonical.go b/opnode/eth/canonical.go index 2a2e88d2e67e..2ec870df7bd6 100644 --- a/opnode/eth/canonical.go +++ b/opnode/eth/canonical.go @@ -12,26 +12,26 @@ type BlockLinkByNumber interface { BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) } -// BlockLinkByNumberFn implements BlockLinkByNumber to implement the interface as anonymous function -type BlockLinkByNumberFn func(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) +type blockLink struct { + l1Src HeaderByNumberSource +} + +func (b *blockLink) BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) { + header, err := b.l1Src.HeaderByNumber(ctx, big.NewInt(int64(num))) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return BlockID{}, BlockID{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", num, err) + } + parentNum := num + if parentNum > 0 { + parentNum -= 1 + } + return BlockID{Hash: header.Hash(), Number: num}, BlockID{Hash: header.ParentHash, Number: parentNum}, nil -func (fn BlockLinkByNumberFn) BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) { - return fn(ctx, num) } // CanonicalChain presents the block-hashes by height by wrapping a header-source // (useful due to lack of a direct JSON RPC endpoint) func CanonicalChain(l1Src HeaderByNumberSource) BlockLinkByNumber { - return BlockLinkByNumberFn(func(ctx context.Context, num uint64) (BlockID, BlockID, error) { - header, err := l1Src.HeaderByNumber(ctx, big.NewInt(int64(num))) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return BlockID{}, BlockID{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", num, err) - } - parentNum := num - if parentNum > 0 { - parentNum -= 1 - } - return BlockID{Hash: header.Hash(), Number: num}, BlockID{Hash: header.ParentHash, Number: parentNum}, nil - }) + return &blockLink{l1Src: l1Src} } From b6371bcbbd01f9bba24a02edbdb55a035c0ccc09 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Feb 2022 16:52:27 -0800 Subject: [PATCH 232/585] ref impl: More driver cleanup This removes most of the public APIs from the driver package. The internal package could be a little cleaner, but with a more limited API, making those changes will be easier. No functionality should be changed. Misc. Changes - The execute payload and forck choice update functions where moved to the L2 package. They simply wrapped the functions of the same name, but with more idiomatic golang error handling and parsing - Turn the driver struct to be an opaque type with a simplified lifecycle management (New, Start, Stop). --- opnode/l2/source.go | 58 ++++++++++++ opnode/node/node.go | 16 ++-- opnode/rollup/driver/driver.go | 141 ++++++++++------------------- opnode/rollup/driver/loop.go | 76 ---------------- opnode/rollup/driver/state.go | 69 ++++++-------- opnode/rollup/driver/state_test.go | 8 +- opnode/rollup/driver/step.go | 65 ++----------- 7 files changed, 153 insertions(+), 280 deletions(-) create mode 100644 opnode/l2/source.go delete mode 100644 opnode/rollup/driver/loop.go diff --git a/opnode/l2/source.go b/opnode/l2/source.go new file mode 100644 index 000000000000..22c00e442f55 --- /dev/null +++ b/opnode/l2/source.go @@ -0,0 +1,58 @@ +package l2 + +import ( + "context" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/common" +) + +type RPC interface { + ExecutePayload(ctx context.Context, payload *ExecutionPayload) (*ExecutePayloadResult, error) + ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) +} + +// ExecutePayload executes the payload and parses the return status into a useful error code +func ExecutePayload(ctx context.Context, rpc RPC, payload *ExecutionPayload) error { + execCtx, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() + execRes, err := rpc.ExecutePayload(execCtx, payload) + if err != nil { + return fmt.Errorf("failed to execute payload: %v", err) + } + switch execRes.Status { + case ExecutionValid: + return nil + case ExecutionSyncing: + return fmt.Errorf("failed to execute payload %s, node is syncing, latest valid hash is %s", payload.ID(), execRes.LatestValidHash) + case ExecutionInvalid: + return fmt.Errorf("execution payload %s was INVALID! Latest valid hash is %s, ignoring bad block: %q", payload.ID(), execRes.LatestValidHash, execRes.ValidationError) + default: + return fmt.Errorf("unknown execution status on %s: %q, ", payload.ID(), string(execRes.Status)) + } +} + +// ForkchoiceUpdate updates the forkchoive for L2 and parses the return status into a useful error code +func ForkchoiceUpdate(ctx context.Context, rpc RPC, l2BlockHash common.Hash, l2Finalized common.Hash) error { + postState := &ForkchoiceState{ + HeadBlockHash: l2BlockHash, // no difference yet between Head and Safe, no data ahead of L1 yet. + SafeBlockHash: l2BlockHash, + FinalizedBlockHash: l2Finalized, + } + + fcCtx, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() + fcRes, err := rpc.ForkchoiceUpdated(fcCtx, postState, nil) + if err != nil { + return fmt.Errorf("failed to update forkchoice: %v", err) + } + switch fcRes.Status { + case UpdateSyncing: + return fmt.Errorf("updated forkchoice, but node is syncing: %v", err) + case UpdateSuccess: + return nil + default: + return fmt.Errorf("unknown forkchoice status on %s: %q, ", l2BlockHash, string(fcRes.Status)) + } +} diff --git a/opnode/node/node.go b/opnode/node/node.go index bbdc306ba877..c4dae0c479e4 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -37,9 +37,9 @@ func (cfg *Config) Check() error { type OpNode struct { log log.Logger - l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) - l2Engines []*driver.DriverV2 // engines to keep synced - ctx context.Context // Embeded CTX to be removed + l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) + l2Engines []*driver.Driver // engines to keep synced + ctx context.Context // Embeded CTX to be removed done chan struct{} } @@ -70,7 +70,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { // l1Node.SetHeader() l1Source := l1.NewSource(ethclient.NewClient(l1Node)) genesis := cfg.GetGenesis() - var l2Engines []*driver.DriverV2 + var l2Engines []*driver.Driver for i, addr := range cfg.L2EngineAddrs { // L2 exec engine: updated by this OpNode (L2 consensus layer node) backend, err := rpc.DialContext(ctx, addr) @@ -129,19 +129,15 @@ func (c *OpNode) Start() error { for _, eng := range c.l2Engines { // Request initial head update, default to genesis otherwise reqCtx, reqCancel := context.WithTimeout(c.ctx, time.Second*10) - if !eng.RequestUpdate(reqCtx, c.log, eng) { - c.log.Error("failed to fetch engine head, defaulting to genesis") - eng.UpdateHead(eng.Genesis.L1, eng.Genesis.L2) - } - reqCancel() // driver subscribes to L1 head changes l1SubCh := make(chan eth.HeadSignal, 10) l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine - eng.Start(context.TODO(), l1SubCh) + eng.Start(reqCtx, l1SubCh) // engDriveSub := eng.Drive(c.ctx, l1SubCh) // handleUnsubscribe(engDriveSub, "engine driver unexpectedly failed") + reqCancel() } // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 4cf920225b0e..fc950c0ae9bd 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -2,93 +2,31 @@ package driver import ( "context" - "sync" "time" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) -// Driver exposes the driver functionality that maintains the external execution-engine. -type Driver interface { - // requestEngineHead retrieves the L2 head reference of the engine, as well as the L1 reference it was derived from. - // An error is returned when the L2 head information could not be retrieved (timeout or connection issue) - requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) - // findSyncStart statelessly finds the next L1 block to derive, and on which L2 block it applies. - // If the engine is fully synced, then the last derived L1 block, and parent L2 block, is repeated. - // An error is returned if the sync starting point could not be determined (due to timeouts, wrong-chain, etc.) - findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) - // driverStep explicitly calls the engine to derive a L1 block into a L2 block, and apply it on top of the given L2 block. - // The finalized L2 block is provided to update the engine with finality, but does not affect the derivation step itself. - // The resulting L2 block ID is returned, or an error if the derivation fails. - driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) -} - -type EngineDriver struct { - Log log.Logger - // API bindings to execution engine - RPC DriverAPI - DL Downloader - SyncRef rollupSync.SyncReference - - // The current driving force, to shutdown before closing the engine. - driveSub ethereum.Subscription - // There may only be 1 driver at a time - driveLock sync.Mutex - - EngineDriverState -} - -// ENTRYPOINT -func (e *EngineDriver) Drive(ctx context.Context, l1Heads <-chan eth.HeadSignal) ethereum.Subscription { - e.driveLock.Lock() - defer e.driveLock.Unlock() - if e.driveSub != nil { - return e.driveSub - } - - e.driveSub = event.NewSubscription(newDriverLoop(ctx, &e.EngineDriverState, e.Log, l1Heads, e)) - return e.driveSub -} - -func (e *EngineDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { - refL1, refL2, _, err = e.SyncRef.RefByL2Num(ctx, nil, &e.Genesis) - return -} - -func (e *EngineDriver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - return rollupSync.FindSyncStart(ctx, e.SyncRef, &e.Genesis) -} - -func (e *EngineDriver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { - return DriverStep(ctx, e.Log, e.RPC, e.DL, nextRefL1, refL2, finalized.Hash) -} - -func (e *EngineDriver) Close() { - e.driveSub.Unsubscribe() -} +// keep making many sync steps if we can make sync progress +const hot = time.Millisecond * 30 -func (e *DriverV2) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { - refL1, refL2, _, err = e.syncRef.RefByL2Num(ctx, nil, &e.genesis) - return -} +// check on sync regularly, but prioritize sync triggers with head updates etc. +const cold = time.Second * 8 -func (e *DriverV2) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - return rollupSync.FindSyncStart(ctx, e.syncRef, &e.genesis) -} +// at least try every minute to sync, even if things are going well +const max = time.Minute -func (e *DriverV2) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { - return DriverStep(ctx, e.log, e.rpc, e.dl, nextRefL1, refL2, finalized.Hash) +type Downloader interface { + Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) } -type DriverV2 struct { +type Driver struct { log log.Logger rpc DriverAPI syncRef rollupSync.SyncReference @@ -96,34 +34,39 @@ type DriverV2 struct { l1Heads <-chan eth.HeadSignal done chan chan error genesis rollup.Genesis - EngineDriverState + state // embedded engine state } -func NewDriver(l2 DriverAPI, l1 l1.Source, log log.Logger, genesis rollup.Genesis) *DriverV2 { - return &DriverV2{ - log: log, - rpc: l2, - syncRef: rollupSync.SyncSource{L1: l1, L2: l2}, - dl: l1, - done: make(chan chan error), - genesis: genesis, - EngineDriverState: EngineDriverState{Genesis: genesis}, +func NewDriver(l2 DriverAPI, l1 l1.Source, log log.Logger, genesis rollup.Genesis) *Driver { + return &Driver{ + log: log, + rpc: l2, + syncRef: rollupSync.SyncSource{L1: l1, L2: l2}, + dl: l1, + done: make(chan chan error), + genesis: genesis, + state: state{Genesis: genesis}, } } -func (d *DriverV2) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error { +func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error { d.l1Heads = l1Heads - go d.loop(ctx) + if !d.requestUpdate(ctx, d.log, d) { + d.log.Error("failed to fetch engine head, defaulting to genesis") + d.updateHead(d.Genesis.L1, d.Genesis.L2) + } + go d.loop() return nil } -func (d *DriverV2) Close() error { +func (d *Driver) Close() error { ec := make(chan error) d.done <- ec err := <-ec return err } -func (d *DriverV2) loop(ctx context.Context) error { +func (d *Driver) loop() { + ctx := context.Background() backoff := cold syncTicker := time.NewTicker(cold) l2HeadPoll := time.NewTicker(time.Second * 14) @@ -150,26 +93,25 @@ func (d *DriverV2) loop(ctx context.Context) error { for { select { - case <-ctx.Done(): - return ctx.Err() + case <-d.done: - return nil + return case <-l2HeadPoll.C: ctx, cancel := context.WithTimeout(ctx, time.Second*4) - if d.RequestUpdate(ctx, d.log, d) { + if d.requestUpdate(ctx, d.log, d) { onL2Update() } cancel() continue case l1HeadSig := <-d.l1Heads: - if d.NotifyL1Head(ctx, d.log, l1HeadSig, d) { + if d.notifyL1Head(ctx, d.log, l1HeadSig, d) { syncQuickly() } continue case <-syncTicker.C: // If already synced, or in case of failure, we slow down syncBackoff() - if d.RequestSync(ctx, d.log, d) { + if d.requestSync(ctx, d.log, d) { // Successfully stepped toward target. Continue quickly if we are not there yet syncQuickly() onL2Update() @@ -178,3 +120,18 @@ func (d *DriverV2) loop(ctx context.Context) error { } } + +// Fulfill the `internalDriver` interface + +func (e *Driver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { + refL1, refL2, _, err = e.syncRef.RefByL2Num(ctx, nil, &e.genesis) + return +} + +func (e *Driver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { + return rollupSync.FindSyncStart(ctx, e.syncRef, &e.genesis) +} + +func (e *Driver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { + return e.step(ctx, nextRefL1, refL2, finalized.Hash) +} diff --git a/opnode/rollup/driver/loop.go b/opnode/rollup/driver/loop.go deleted file mode 100644 index 8356db2a7336..000000000000 --- a/opnode/rollup/driver/loop.go +++ /dev/null @@ -1,76 +0,0 @@ -package driver - -import ( - "context" - "time" - - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum/go-ethereum/log" -) - -// keep making many sync steps if we can make sync progress -const hot = time.Millisecond * 30 - -// check on sync regularly, but prioritize sync triggers with head updates etc. -const cold = time.Second * 8 - -// at least try every minute to sync, even if things are going well -const max = time.Minute - -func newDriverLoop(ctx context.Context, state stateMachine, log log.Logger, l1Heads <-chan eth.HeadSignal, driver Driver) func(quit <-chan struct{}) error { - - backoff := cold - syncTicker := time.NewTicker(cold) - l2HeadPoll := time.NewTicker(time.Second * 14) - - // exponential backoff, add 10% each step, up to max. - syncBackoff := func() { - backoff += backoff / 10 - if backoff > max { - backoff = max - } - syncTicker.Reset(backoff) - } - syncQuickly := func() { - syncTicker.Reset(hot) - backoff = cold - } - onL2Update := func() { - // And we want to slow down requesting the L2 engine for its head (we just changed it ourselves) - // Request head if we don't successfully change it in the next 14 seconds. - l2HeadPoll.Reset(time.Second * 14) - } - return func(quit <-chan struct{}) error { - defer syncTicker.Stop() - defer l2HeadPoll.Stop() - - for { - select { - case <-ctx.Done(): - return ctx.Err() - case <-quit: - return nil - case <-l2HeadPoll.C: - ctx, cancel := context.WithTimeout(ctx, time.Second*4) - if state.RequestUpdate(ctx, log, driver) { - onL2Update() - } - cancel() - continue - case l1HeadSig := <-l1Heads: - if state.NotifyL1Head(ctx, log, l1HeadSig, driver) { - syncQuickly() - } - continue - case <-syncTicker.C: - // If already synced, or in case of failure, we slow down - syncBackoff() - if state.RequestSync(ctx, log, driver) { - // Successfully stepped toward target. Continue quickly if we are not there yet - syncQuickly() - onL2Update() - } - } - } - } -} diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 6e37f2d97652..2885da69f76f 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -2,31 +2,42 @@ package driver import ( "context" - "sync" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/log" ) +// internalDriver exposes the driver functionality that maintains the external execution-engine. +type internalDriver interface { + // requestEngineHead retrieves the L2 he```d reference of the engine, as well as the L1 reference it was derived from. + // An error is returned when the L2 head information could not be retrieved (timeout or connection issue) + requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) + // findSyncStart statelessly finds the next L1 block to derive, and on which L2 block it applies. + // If the engine is fully synced, then the last derived L1 block, and parent L2 block, is repeated. + // An error is returned if the sync starting point could not be determined (due to timeouts, wrong-chain, etc.) + findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) + // driverStep explicitly calls the engine to derive a L1 block into a L2 block, and apply it on top of the given L2 block. + // The finalized L2 block is provided to update the engine with finality, but does not affect the derivation step itself. + // The resulting L2 block ID is returned, or an error if the derivation fails. + driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) +} + // stateMachine provides control over the driver state, when given control over the Driver actions. type stateMachine interface { - // RequestUpdate tries to update the state-machine with the driver head information. + // requestUpdate tries to update the state-machine with the driver head information. // If the state-machine changed, considering the engine L1 and L2 head, it will return true. False otherwise. - RequestUpdate(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) - // RequestSync tries to sync the provided driver towards the sync target of the state-machine. + requestUpdate(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) + // requestSync tries to sync the provided driver towards the sync target of the state-machine. // If the L2 syncs a step, but is not finished yet, it will return true. False otherwise. - RequestSync(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) - // NotifyL1Head updates the state-machine with the L1 signal, + requestSync(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) + // notifyL1Head updates the state-machine with the L1 signal, // and attempts to sync the driver if the update extends the previous head. // Returns true if the driver successfully derived and synced the L2 block to match L1. False otherwise. - NotifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver Driver) (l2Updated bool) + notifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver internalDriver) (l2Updated bool) } -type EngineDriverState struct { - // Locks the L1 and L2 head changes, to keep a consistent view of the engine - headLock sync.RWMutex - +type state struct { // l1Head tracks the L1 block corresponding to the l2Head l1Head eth.BlockID @@ -44,48 +55,24 @@ type EngineDriverState struct { Genesis rollup.Genesis } -// L1Head returns the block-id (hash and number) of the last L1 block that was derived into the L2 block -func (e *EngineDriverState) L1Head() eth.BlockID { - e.headLock.RLock() - defer e.headLock.RUnlock() - return e.l1Head -} - -// L2Head returns the block-id (hash and number) of the L2 chain head -func (e *EngineDriverState) L2Head() eth.BlockID { - e.headLock.RLock() - defer e.headLock.RUnlock() - return e.l2Head -} - -func (e *EngineDriverState) Head() (l1Head eth.BlockID, l2Head eth.BlockID) { - e.headLock.RLock() - defer e.headLock.RUnlock() - return e.l1Head, e.l2Head -} - -func (e *EngineDriverState) UpdateHead(l1Head eth.BlockID, l2Head eth.BlockID) { - e.headLock.Lock() - defer e.headLock.Unlock() +func (e *state) updateHead(l1Head eth.BlockID, l2Head eth.BlockID) { e.l1Head = l1Head e.l2Head = l2Head } -func (e *EngineDriverState) RequestUpdate(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) { +func (e *state) requestUpdate(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { refL1, refL2, err := driver.requestEngineHead(ctx) if err != nil { log.Error("failed to request engine head", "err", err) return false } - e.headLock.Lock() - defer e.headLock.Unlock() e.l1Head = refL1 e.l2Head = refL2 return e.l1Head != refL1 || e.l2Head != refL2 } -func (e *EngineDriverState) RequestSync(ctx context.Context, log log.Logger, driver Driver) (l2Updated bool) { +func (e *state) requestSync(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { if e.l1Head == e.l1Target { log.Debug("Engine is fully synced", "l1_head", e.l1Head, "l2_head", e.l2Head) // TODO: even though we are fully synced, it may be worth attempting anyway, @@ -106,12 +93,12 @@ func (e *EngineDriverState) RequestSync(ctx context.Context, log log.Logger, dri log.Error("Failed to sync L2 chain with new L1 block", "l1", nextRefL1, "onto_l2", refL2, "err", err) return false } else { - e.UpdateHead(nextRefL1, l2ID) // l2ID is derived from the nextRefL1 + e.updateHead(nextRefL1, l2ID) // l2ID is derived from the nextRefL1 } return e.l1Head != e.l1Target } -func (e *EngineDriverState) NotifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver Driver) (l2Updated bool) { +func (e *state) notifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver internalDriver) (l2Updated bool) { if e.l1Head == l1HeadSig.Self { log.Debug("Received L1 head signal, already synced to it, ignoring event", "l1_head", e.l1Head) return @@ -124,7 +111,7 @@ func (e *EngineDriverState) NotifyL1Head(ctx context.Context, log log.Logger, l1 e.l1Target = l1HeadSig.Self return false } else { - e.UpdateHead(l1HeadSig.Self, l2ID) + e.updateHead(l1HeadSig.Self, l2ID) return true } } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index d1a63cdf00de..61405851536b 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -46,8 +46,8 @@ type testState struct { genesisL2 testID } -func makeState(st testState) *EngineDriverState { - return &EngineDriverState{ +func makeState(st testState) *state { + return &state{ l1Head: st.l1Head.ID(), l2Head: st.l2Head.ID(), l2Finalized: st.l2Finalized.ID(), @@ -86,7 +86,7 @@ func (m *mockDriver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL return } -var _ Driver = (*mockDriver)(nil) +var _ internalDriver = (*mockDriver)(nil) func TestEngineDriverState_RequestSync(t *testing.T) { log := testlog.Logger(t, log.LvlTrace) @@ -104,7 +104,7 @@ func TestEngineDriverState_RequestSync(t *testing.T) { driver.On("findSyncStart", ctx).Return(testID("d:3").ID(), testID("C:2").ID(), nil) driver.On("driverStep", ctx, testID("d:3").ID(), testID("C:2").ID(), testID("B:1").ID()).Return(testID("D:3").ID(), nil) - l2Updated := state.RequestSync(ctx, log, driver) + l2Updated := state.requestSync(ctx, log, driver) assert.Equal(t, state.l1Head, testID("d:3").ID()) assert.Equal(t, state.l2Head, testID("D:3").ID()) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 67f769ed5900..e8dc1f3ebc6c 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -5,13 +5,11 @@ import ( "fmt" "time" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" ) type DriverAPI interface { @@ -19,60 +17,13 @@ type DriverAPI interface { l2.EthBackend } -func Execute(ctx context.Context, rpc DriverAPI, payload *l2.ExecutionPayload) error { - execCtx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() - execRes, err := rpc.ExecutePayload(execCtx, payload) - if err != nil { - return fmt.Errorf("failed to execute payload: %v", err) - } - switch execRes.Status { - case l2.ExecutionValid: - return nil - case l2.ExecutionSyncing: - return fmt.Errorf("failed to execute payload %s, node is syncing, latest valid hash is %s", payload.ID(), execRes.LatestValidHash) - case l2.ExecutionInvalid: - return fmt.Errorf("execution payload %s was INVALID! Latest valid hash is %s, ignoring bad block: %q", payload.ID(), execRes.LatestValidHash, execRes.ValidationError) - default: - return fmt.Errorf("unknown execution status on %s: %q, ", payload.ID(), string(execRes.Status)) - } -} - -func ForkchoiceUpdate(ctx context.Context, rpc DriverAPI, l2BlockHash common.Hash, l2Finalized common.Hash) error { - postState := &l2.ForkchoiceState{ - HeadBlockHash: l2BlockHash, // no difference yet between Head and Safe, no data ahead of L1 yet. - SafeBlockHash: l2BlockHash, - FinalizedBlockHash: l2Finalized, - } - - fcCtx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() - fcRes, err := rpc.ForkchoiceUpdated(fcCtx, postState, nil) - if err != nil { - return fmt.Errorf("failed to update forkchoice: %v", err) - } - switch fcRes.Status { - case l2.UpdateSyncing: - return fmt.Errorf("updated forkchoice, but node is syncing: %v", err) - case l2.UpdateSuccess: - return nil - default: - return fmt.Errorf("unknown forkchoice status on %s: %q, ", l2BlockHash, string(fcRes.Status)) - } -} - -type Downloader interface { - Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) -} - -func DriverStep(ctx context.Context, log log.Logger, rpc DriverAPI, - dl Downloader, l1Input eth.BlockID, l2Parent eth.BlockID, l2Finalized common.Hash) (out eth.BlockID, err error) { - - logger := log.New("input_l1", l1Input, "input_l2_parent", l2Parent, "finalized_l2", l2Finalized) +// step takes an L1 block id and then creates and executes the L2 block. The forkchoice is updated as well. +func (d *Driver) step(ctx context.Context, l1Input eth.BlockID, l2Parent eth.BlockID, l2Finalized common.Hash) (eth.BlockID, error) { + logger := d.log.New("input_l1", l1Input, "input_l2_parent", l2Parent, "finalized_l2", l2Finalized) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - bl, receipts, err := dl.Fetch(fetchCtx, l1Input) + bl, receipts, err := d.dl.Fetch(fetchCtx, l1Input) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to fetch block with receipts: %v", err) } @@ -84,7 +35,7 @@ func DriverStep(ctx context.Context, log log.Logger, rpc DriverAPI, } logger.Debug("derived L2 block inputs") - payload, err := derive.ExecutionPayload(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) + payload, err := derive.ExecutionPayload(ctx, d.rpc, l2Parent.Hash, l2Finalized, attrs) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to derive execution payload: %v", err) } @@ -92,13 +43,13 @@ func DriverStep(ctx context.Context, log log.Logger, rpc DriverAPI, logger = logger.New("derived_l2", payload.ID()) logger.Info("derived full block") - err = Execute(ctx, rpc, payload) + err = l2.ExecutePayload(ctx, d.rpc, payload) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to apply execution payload: %v", err) } logger.Info("executed block") - err = ForkchoiceUpdate(ctx, rpc, payload.BlockHash, l2Finalized) + err = l2.ForkchoiceUpdate(ctx, d.rpc, payload.BlockHash, l2Finalized) if err != nil { return eth.BlockID{}, fmt.Errorf("failed to persist execution payload: %v", err) } From 82ad8f4854ab6d7fd942a37c996d7e5275c04416 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Feb 2022 15:43:54 -0800 Subject: [PATCH 233/585] Clean up interfaces This places the L1 Source Interface in the L1 package. --- opnode/eth/canonical.go | 37 -------------- opnode/eth/heads.go | 4 ++ opnode/eth/source.go | 89 --------------------------------- opnode/l1/downloader.go | 4 +- opnode/l1/source.go | 86 +++++++++++++++++++++++++++++++ opnode/l2/api.go | 17 +++---- opnode/node/node.go | 34 ++++++------- opnode/rollup/sync/reference.go | 11 +++- 8 files changed, 123 insertions(+), 159 deletions(-) delete mode 100644 opnode/eth/canonical.go delete mode 100644 opnode/eth/source.go create mode 100644 opnode/l1/source.go diff --git a/opnode/eth/canonical.go b/opnode/eth/canonical.go deleted file mode 100644 index 2ec870df7bd6..000000000000 --- a/opnode/eth/canonical.go +++ /dev/null @@ -1,37 +0,0 @@ -package eth - -import ( - "context" - "fmt" - "math/big" -) - -// BlockLinkByNumber Retrieves the *currently* canonical block-hash at the given block-height, and the parent before it. -// The results of this should not be cached, or the cache needs to be reorg-aware. -type BlockLinkByNumber interface { - BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) -} - -type blockLink struct { - l1Src HeaderByNumberSource -} - -func (b *blockLink) BlockLinkByNumber(ctx context.Context, num uint64) (self BlockID, parent BlockID, err error) { - header, err := b.l1Src.HeaderByNumber(ctx, big.NewInt(int64(num))) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return BlockID{}, BlockID{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", num, err) - } - parentNum := num - if parentNum > 0 { - parentNum -= 1 - } - return BlockID{Hash: header.Hash(), Number: num}, BlockID{Hash: header.ParentHash, Number: parentNum}, nil - -} - -// CanonicalChain presents the block-hashes by height by wrapping a header-source -// (useful due to lack of a direct JSON RPC endpoint) -func CanonicalChain(l1Src HeaderByNumberSource) BlockLinkByNumber { - return &blockLink{l1Src: l1Src} -} diff --git a/opnode/eth/heads.go b/opnode/eth/heads.go index 1d1d1b595ad3..b2774e2a5ed3 100644 --- a/opnode/eth/heads.go +++ b/opnode/eth/heads.go @@ -16,6 +16,10 @@ type HeadSignal struct { // HeadSignalFn is used as callback function to accept head-signals type HeadSignalFn func(sig HeadSignal) +type NewHeadSource interface { + SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) +} + // WatchHeadChanges wraps a new-head subscription from NewHeadSource to feed the given Tracker func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) (ethereum.Subscription, error) { headChanges := make(chan *types.Header, 10) diff --git a/opnode/eth/source.go b/opnode/eth/source.go deleted file mode 100644 index 4a92c47525ab..000000000000 --- a/opnode/eth/source.go +++ /dev/null @@ -1,89 +0,0 @@ -package eth - -import ( - "context" - "math/big" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -// Source interfaces isolate individual ethereum.ChainReader methods, -// and enable anonymous functions to implement them. - -type NewHeadSource interface { - SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) -} - -type HeaderByHashSource interface { - HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) -} - -type HeaderByNumberSource interface { - HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) -} - -type ReceiptSource interface { - TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) -} - -type BlockByHashSource interface { - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) -} - -type BlockByNumberSource interface { - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) -} - -type L1Source interface { - NewHeadSource - HeaderByHashSource - HeaderByNumberSource - ReceiptSource - BlockByHashSource - Close() -} - -type BlockSource interface { - BlockByHashSource - BlockByNumberSource -} - -// For test instances, composition etc. we implement the interfaces with equivalent function types - -type NewHeadFn func(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) - -func (fn NewHeadFn) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { - return fn(ctx, ch) -} - -type HeaderByHashFn func(ctx context.Context, hash common.Hash) (*types.Header, error) - -func (fn HeaderByHashFn) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return fn(ctx, hash) -} - -type HeaderByNumberFn func(ctx context.Context, number *big.Int) (*types.Header, error) - -func (fn HeaderByNumberFn) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return fn(ctx, number) -} - -type ReceiptFn func(ctx context.Context, txHash common.Hash) (*types.Receipt, error) - -func (fn ReceiptFn) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - return fn(ctx, txHash) -} - -type BlockByHashFn func(ctx context.Context, hash common.Hash) (*types.Block, error) - -func (fn BlockByHashFn) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return fn(ctx, hash) -} - -type BlockByNumFn func(ctx context.Context, number *big.Int) (*types.Block, error) - -func (fn BlockByNumFn) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - return fn(ctx, number) -} diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go index 75dfcdbb6f52..7aabe6093c46 100644 --- a/opnode/l1/downloader.go +++ b/opnode/l1/downloader.go @@ -102,8 +102,8 @@ type Downloader interface { } type DownloadSource interface { - eth.BlockByHashSource - eth.ReceiptSource + TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) } // downloader implements Downloader with parallel jobs, diff --git a/opnode/l1/source.go b/opnode/l1/source.go new file mode 100644 index 000000000000..3c5e721f02f3 --- /dev/null +++ b/opnode/l1/source.go @@ -0,0 +1,86 @@ +package l1 + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +// type L1Source interface { +// SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) +// HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) +// HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) +// TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) +// BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) +// BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) +// Close() +// } + +type Source struct { + client *ethclient.Client + downloader Downloader +} + +func NewSource(client *ethclient.Client) Source { + return Source{ + client: client, + downloader: NewDownloader(client), + } +} + +func (s Source) BlockLinkByNumber(ctx context.Context, num uint64) (self eth.BlockID, parent eth.BlockID, err error) { + header, err := s.client.HeaderByNumber(ctx, big.NewInt(int64(num))) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", num, err) + } + parentNum := num + if parentNum > 0 { + parentNum -= 1 + } + return eth.BlockID{Hash: header.Hash(), Number: num}, eth.BlockID{Hash: header.ParentHash, Number: parentNum}, nil + +} + +func (s Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { + return s.client.SubscribeNewHead(ctx, ch) +} + +func (s Source) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + return s.client.HeaderByHash(ctx, hash) +} + +func (s Source) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + return s.client.HeaderByNumber(ctx, number) +} + +func (s Source) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + return s.client.TransactionReceipt(ctx, txHash) +} + +func (s Source) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return s.client.BlockByHash(ctx, hash) +} + +func (s Source) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return s.client.BlockByNumber(ctx, number) +} + +func (s Source) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { + return s.downloader.Fetch(ctx, id) +} + +func (s Source) AddReceiptWorkers(n int) int { + return s.downloader.AddReceiptWorkers(n) +} + +func (s Source) Close() { + s.client.Close() + s.downloader.Close() +} diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 3de4081753cb..21dc1c4466cf 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -4,19 +4,18 @@ package l2 import ( "context" "fmt" + "math/big" "reflect" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum/go-ethereum/log" - + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/holiman/uint256" - + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" + "github.com/holiman/uint256" ) type ErrorCode int @@ -186,9 +185,9 @@ type RPCBackend interface { } type EthBackend interface { - eth.BlockByHashSource - eth.BlockByNumberSource - eth.NewHeadSource + SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) } type EngineClient struct { diff --git a/opnode/node/node.go b/opnode/node/node.go index 84b9744f10a4..3b8f04bfa5af 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -37,12 +37,11 @@ func (cfg *Config) Check() error { } type OpNode struct { - log log.Logger - l1Source eth.L1Source // (combined) source to fetch data from - l1Downloader l1.Downloader // actual downloader - l2Engines []*driver.EngineDriver // engines to keep synced - ctx context.Context // Embeded CTX to be removed - done chan struct{} + log log.Logger + l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) + l2Engines []*driver.EngineDriver // engines to keep synced + ctx context.Context // Embeded CTX to be removed + done chan struct{} } func (conf *Config) GetGenesis() rollup.Genesis { @@ -70,13 +69,9 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { // TODO: we may need to authenticate the connection with L1 // l1Node.SetHeader() - l1Source := ethclient.NewClient(l1Node) - l1CanonicalChain := eth.CanonicalChain(l1Source) - - l1Downloader := l1.NewDownloader(l1Source) + l1Source := l1.NewSource(ethclient.NewClient(l1Node)) genesis := cfg.GetGenesis() var l2Engines []*driver.EngineDriver - for i, addr := range cfg.L2EngineAddrs { // L2 exec engine: updated by this OpNode (L2 consensus layer node) backend, err := rpc.DialContext(ctx, addr) @@ -96,9 +91,9 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { engine := &driver.EngineDriver{ Log: log.New("engine", i), RPC: client, - DL: l1Downloader, + DL: l1Source, SyncRef: rollupSync.SyncSource{ - L1: l1CanonicalChain, + L1: l1Source, L2: client, }, EngineDriverState: driver.EngineDriverState{Genesis: genesis}, @@ -107,12 +102,11 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { } n := &OpNode{ - log: log, - l1Source: l1Source, - l1Downloader: l1Downloader, - l2Engines: l2Engines, - ctx: ctx, - done: make(chan struct{}), + log: log, + l1Source: l1Source, + l2Engines: l2Engines, + ctx: ctx, + done: make(chan struct{}), } return n, nil @@ -136,7 +130,7 @@ func (c *OpNode) Start() error { c.log.Info("Fetching rollup starting point") // We download receipts in parallel - c.l1Downloader.AddReceiptWorkers(4) + c.l1Source.AddReceiptWorkers(4) // Feed of eth.HeadSignal var l1HeadsFeed event.Feed diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index 2b0adf14a4e0..a7056f913be7 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -8,13 +8,20 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) // SyncSource implements SyncReference with a L2 block sources and L1 hash-by-number source type SyncSource struct { - L1 eth.BlockLinkByNumber - L2 eth.BlockSource + L1 interface { + BlockLinkByNumber(ctx context.Context, num uint64) (self eth.BlockID, parent eth.BlockID, err error) + } + L2 interface { + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + } } // RefByL1Num fetches the canonical L1 block hash and the parent for the given L1 block height. From a2c0bfe4e3a177b587b5704893feb60282695f8f Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 16 Feb 2022 13:10:46 -0700 Subject: [PATCH 234/585] ref impl: Remove stateMachine Dead code because the interface is no longer used. --- opnode/rollup/driver/state.go | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 2885da69f76f..a400f3049566 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -23,20 +23,6 @@ type internalDriver interface { driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) } -// stateMachine provides control over the driver state, when given control over the Driver actions. -type stateMachine interface { - // requestUpdate tries to update the state-machine with the driver head information. - // If the state-machine changed, considering the engine L1 and L2 head, it will return true. False otherwise. - requestUpdate(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) - // requestSync tries to sync the provided driver towards the sync target of the state-machine. - // If the L2 syncs a step, but is not finished yet, it will return true. False otherwise. - requestSync(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) - // notifyL1Head updates the state-machine with the L1 signal, - // and attempts to sync the driver if the update extends the previous head. - // Returns true if the driver successfully derived and synced the L2 block to match L1. False otherwise. - notifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver internalDriver) (l2Updated bool) -} - type state struct { // l1Head tracks the L1 block corresponding to the l2Head l1Head eth.BlockID @@ -60,6 +46,8 @@ func (e *state) updateHead(l1Head eth.BlockID, l2Head eth.BlockID) { e.l2Head = l2Head } +// requestUpdate tries to update the state-machine with the driver head information. +// If the state-machine changed, considering the engine L1 and L2 head, it will return true. False otherwise. func (e *state) requestUpdate(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { refL1, refL2, err := driver.requestEngineHead(ctx) if err != nil { @@ -72,6 +60,8 @@ func (e *state) requestUpdate(ctx context.Context, log log.Logger, driver intern return e.l1Head != refL1 || e.l2Head != refL2 } +// requestSync tries to sync the provided driver towards the sync target of the state-machine. +// If the L2 syncs a step, but is not finished yet, it will return true. False otherwise. func (e *state) requestSync(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { if e.l1Head == e.l1Target { log.Debug("Engine is fully synced", "l1_head", e.l1Head, "l2_head", e.l2Head) @@ -98,6 +88,9 @@ func (e *state) requestSync(ctx context.Context, log log.Logger, driver internal return e.l1Head != e.l1Target } +// notifyL1Head updates the state-machine with the L1 signal, +// and attempts to sync the driver if the update extends the previous head. +// Returns true if the driver successfully derived and synced the L2 block to match L1. False otherwise. func (e *state) notifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver internalDriver) (l2Updated bool) { if e.l1Head == l1HeadSig.Self { log.Debug("Received L1 head signal, already synced to it, ignoring event", "l1_head", e.l1Head) From ecd93ca359e0b0776b24e4e94086f822a5234beb Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 16 Feb 2022 13:12:41 -0700 Subject: [PATCH 235/585] ref impl: Fix lint in node Check the error code on rollup node start method. --- opnode/node/node.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index c4dae0c479e4..d88c7a087362 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -134,10 +134,14 @@ func (c *OpNode) Start() error { l1SubCh := make(chan eth.HeadSignal, 10) l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine - eng.Start(reqCtx, l1SubCh) + err := eng.Start(reqCtx, l1SubCh) // engDriveSub := eng.Drive(c.ctx, l1SubCh) // handleUnsubscribe(engDriveSub, "engine driver unexpectedly failed") reqCancel() + if err != nil { + c.log.Error("Could not start a rollup node", "err", err) + return err + } } // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync From d73d6fbb9961e50660c755fa1e4ed2b69b0dc80a Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 17 Feb 2022 12:12:37 -0700 Subject: [PATCH 236/585] Remove commented out interface --- opnode/l1/source.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 3c5e721f02f3..738643e4bb6a 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -12,16 +12,6 @@ import ( "github.com/ethereum/go-ethereum/ethclient" ) -// type L1Source interface { -// SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) -// HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) -// HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) -// TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) -// BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) -// BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) -// Close() -// } - type Source struct { client *ethclient.Client downloader Downloader From 95d363c0071b0fc4227e0912060e0f2d805416a3 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 13:53:55 -0800 Subject: [PATCH 237/585] ref impl: Remove stored context --- opnode/cmd/main.go | 2 +- opnode/node/node.go | 8 +++----- opnode/test/system_test.go | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index efa60d325615..1c331009f5f6 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -74,7 +74,7 @@ func RollupNodeMain(ctx *cli.Context) error { } log.Info("Starting rollup node") - if err := n.Start(); err != nil { + if err := n.Start(context.Background()); err != nil { log.Error("Unable to start L2 Output Submitter", "error", err) return err } diff --git a/opnode/node/node.go b/opnode/node/node.go index d88c7a087362..3e3c583d6e64 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -39,7 +39,6 @@ type OpNode struct { log log.Logger l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) l2Engines []*driver.Driver // engines to keep synced - ctx context.Context // Embeded CTX to be removed done chan struct{} } @@ -95,14 +94,13 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { log: log, l1Source: l1Source, l2Engines: l2Engines, - ctx: ctx, done: make(chan struct{}), } return n, nil } -func (c *OpNode) Start() error { +func (c *OpNode) Start(ctx context.Context) error { c.log.Info("Starting OpNode") var unsub []func() @@ -128,7 +126,7 @@ func (c *OpNode) Start() error { c.log.Info("Attaching execution engine(s)") for _, eng := range c.l2Engines { // Request initial head update, default to genesis otherwise - reqCtx, reqCancel := context.WithTimeout(c.ctx, time.Second*10) + reqCtx, reqCancel := context.WithTimeout(ctx, time.Second*10) // driver subscribes to L1 head changes l1SubCh := make(chan eth.HeadSignal, 10) @@ -149,7 +147,7 @@ func (c *OpNode) Start() error { if err != nil { c.log.Warn("resubscribing after failed L1 subscription", "err", err) } - return eth.WatchHeadChanges(c.ctx, c.l1Source, func(sig eth.HeadSignal) { + return eth.WatchHeadChanges(ctx, c.l1Source, func(sig eth.HeadSignal) { l1HeadsFeed.Send(sig) }) }) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index bc43ec170d8c..2321360b6f7f 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -124,7 +124,7 @@ func TestSystemE2E(t *testing.T) { if err != nil { t.Fatalf("Failed to create the new node: %v", err) } - err = node.Start() + err = node.Start(context.Background()) defer node.Stop() if err != nil { t.Fatal(err) From fb210b47c9efb8069f7e6ecef6ed5d8af6d72f49 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 13:58:33 -0800 Subject: [PATCH 238/585] ref impl: Set timeouts for all driver loop operations Previously we only had a timeout for the requestUpdate operation, but this commit adds timeouts for the notifyL1Head and requestSync operations. --- opnode/rollup/driver/driver.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index fc950c0ae9bd..2fd28aa18466 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -93,7 +93,6 @@ func (d *Driver) loop() { for { select { - case <-d.done: return case <-l2HeadPoll.C: @@ -104,18 +103,22 @@ func (d *Driver) loop() { cancel() continue case l1HeadSig := <-d.l1Heads: + ctx, cancel := context.WithTimeout(ctx, time.Second*4) if d.notifyL1Head(ctx, d.log, l1HeadSig, d) { syncQuickly() } + cancel() continue case <-syncTicker.C: // If already synced, or in case of failure, we slow down syncBackoff() + ctx, cancel := context.WithTimeout(ctx, time.Second*4) if d.requestSync(ctx, d.log, d) { // Successfully stepped toward target. Continue quickly if we are not there yet syncQuickly() onL2Update() } + cancel() } } From e45c57b1b9cf796cf7e318166bbe8d6743331379 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 14:34:52 -0800 Subject: [PATCH 239/585] ref impl: Remove dead comments --- opnode/node/node.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index 3e3c583d6e64..0287695b4770 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -133,8 +133,6 @@ func (c *OpNode) Start(ctx context.Context) error { l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine err := eng.Start(reqCtx, l1SubCh) - // engDriveSub := eng.Drive(c.ctx, l1SubCh) - // handleUnsubscribe(engDriveSub, "engine driver unexpectedly failed") reqCancel() if err != nil { c.log.Error("Could not start a rollup node", "err", err) From bd175212dbf78dd9a7a2fcc3c059cbb377adff1d Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 14:36:52 -0800 Subject: [PATCH 240/585] ref impl: Fix for resubscription bug Use background context rather than using the context in the resubscribeFunc. That context is shortlived and only for setting up the subscription rather than for long lived lifecycle management. Co-authored-by: Diederik Loerakker --- opnode/node/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index 0287695b4770..0ff11ff6a15d 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -145,7 +145,7 @@ func (c *OpNode) Start(ctx context.Context) error { if err != nil { c.log.Warn("resubscribing after failed L1 subscription", "err", err) } - return eth.WatchHeadChanges(ctx, c.l1Source, func(sig eth.HeadSignal) { + return eth.WatchHeadChanges(context.Background(), c.l1Source, func(sig eth.HeadSignal) { l1HeadsFeed.Send(sig) }) }) From 5774a4351c60e1dafd1c6f3bbf247c91337f4959 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 14:52:56 -0800 Subject: [PATCH 241/585] ref impl/driver: Don't use error return channel We were not sending any errors over the channel. --- opnode/rollup/driver/driver.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 2fd28aa18466..f8b96472e862 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -32,7 +32,7 @@ type Driver struct { syncRef rollupSync.SyncReference dl Downloader l1Heads <-chan eth.HeadSignal - done chan chan error + done chan struct{} genesis rollup.Genesis state // embedded engine state } @@ -43,7 +43,7 @@ func NewDriver(l2 DriverAPI, l1 l1.Source, log log.Logger, genesis rollup.Genesi rpc: l2, syncRef: rollupSync.SyncSource{L1: l1, L2: l2}, dl: l1, - done: make(chan chan error), + done: make(chan struct{}), genesis: genesis, state: state{Genesis: genesis}, } @@ -59,10 +59,8 @@ func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error return nil } func (d *Driver) Close() error { - ec := make(chan error) - d.done <- ec - err := <-ec - return err + close(d.done) + return nil } func (d *Driver) loop() { From e937cc32156459397ed8dea8eef64db6b23a0e16 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 15:10:18 -0800 Subject: [PATCH 242/585] ref impl: Track code coverage across packages (#214) This enables tracking code coverage across packages to see an increase in code coverage due to the e2e test. --- .github/workflows/go-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 8a855b14c098..b638ff0ab015 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -26,6 +26,6 @@ jobs: # rules: https://golangci-lint.run/usage/quick-start/ args: -E asciicheck,goimports - name: Test and generate coverage - run: go test -coverprofile=coverage.out -covermode=atomic ./... + run: go test -coverpkg=./... -coverprofile=coverage.out -covermode=atomic ./... - name: Upload coverage output - uses: codecov/codecov-action@v2 \ No newline at end of file + uses: codecov/codecov-action@v2 From 1dd2db2c95c844c03140e3581a2b694edd5c895b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 16:05:42 -0800 Subject: [PATCH 243/585] ref impl: Add L1HeadRef function This is used in the sync algorithm to get the head block of the L1 chain. This was not previously acessible as the BlockLinkByNumber function takes an uint64. --- opnode/l1/source.go | 14 ++++++++++++++ opnode/rollup/sync/reference.go | 9 +++++++++ opnode/rollup/sync/start_test.go | 13 +++++++++++++ 3 files changed, 36 insertions(+) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 738643e4bb6a..e0e8276fa24d 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -38,6 +38,20 @@ func (s Source) BlockLinkByNumber(ctx context.Context, num uint64) (self eth.Blo } +func (s Source) HeadBlockLink(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) { + header, err := s.client.HeaderByNumber(ctx, nil) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("failed to determine block-hash of head block, could not get header: %w", err) + } + parentNum := header.Number.Uint64() + if parentNum > 0 { + parentNum -= 1 + } + return eth.BlockID{Hash: header.Hash(), Number: header.Number.Uint64()}, eth.BlockID{Hash: header.ParentHash, Number: parentNum}, nil + +} + func (s Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { return s.client.SubscribeNewHead(ctx, ch) } diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index a7056f913be7..3e81dd95132f 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -16,6 +16,7 @@ import ( // SyncSource implements SyncReference with a L2 block sources and L1 hash-by-number source type SyncSource struct { L1 interface { + HeadBlockLink(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) BlockLinkByNumber(ctx context.Context, num uint64) (self eth.BlockID, parent eth.BlockID, err error) } L2 interface { @@ -29,6 +30,11 @@ func (src SyncSource) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.Bl return src.L1.BlockLinkByNumber(ctx, l1Num) } +// L1HeadRef fetches the canonical L1 block hash and the parent for the head of the L1 chain. +func (src SyncSource) L1HeadRef(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) { + return src.L1.HeadBlockLink(ctx) +} + // RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. // Use a nil height to fetch the head. func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { @@ -55,6 +61,9 @@ type SyncReference interface { // RefByL1Num fetches the canonical L1 block hash and the parent for the given L1 block height. RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) + // L1HeadRef fetches the canonical L1 block hash and the parent for the head of the L1 chain. + L1HeadRef(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) + // RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. // Use a nil height to fetch the head. RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 3923f5b4d4fd..575f2726aa54 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -34,6 +34,19 @@ func (m *mockSyncReference) RefByL1Num(ctx context.Context, l1Num uint64) (self return } +func (m *mockSyncReference) L1HeadRef(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) { + l := len(m.L1) + if l == 0 { + err = ethereum.NotFound + return + } + self = m.L1[l-1] + if l-1 > 0 { + parent = m.L1[l-1-1] + } + return +} + func (m *mockSyncReference) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { if len(m.L2) == 0 { panic("bad test, no l2 chain") From 33fa47cc55b342dae10a69c2085ff4b02e9b67a0 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 16:10:30 -0800 Subject: [PATCH 244/585] ref impl: Add SyncReferenceV2 interface This is a nicer interface to work with the sync start algorithm. --- opnode/rollup/sync/reference.go | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index 3e81dd95132f..866e144a6898 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -13,6 +13,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// Sync Source Interface TODOs: +// Relax block by hash??? would have to use by number interface though +// Merge v1 and v2 +// Put node definitions in eth? + // SyncSource implements SyncReference with a L2 block sources and L1 hash-by-number source type SyncSource struct { L1 interface { @@ -71,3 +76,59 @@ type SyncReference interface { // RefByL2Hash fetches the L1 and L2 block IDs from the engine for the given L2 block hash. RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) } + +// SyncReferenceV2 wraps the return types of SyncReference to be easier to work with. +type SyncReferenceV2 interface { + L1NodeByNumber(ctx context.Context, l1Num uint64) (L1Node, error) + L1HeadNode(ctx context.Context) (L1Node, error) + L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (L2Node, error) + L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (L2Node, error) +} + +type SyncSourceV2 struct { + SyncReference +} + +func (src SyncSourceV2) L1NodeByNumber(ctx context.Context, l1Num uint64) (L1Node, error) { + self, parent, err := src.RefByL1Num(ctx, l1Num) + if err != nil { + return L1Node{}, err + } + return L1Node{self: self, parent: parent}, nil + +} + +func (src SyncSourceV2) L1HeadNode(ctx context.Context) (L1Node, error) { + self, parent, err := src.L1HeadRef(ctx) + if err != nil { + return L1Node{}, err + } + return L1Node{self: self, parent: parent}, nil +} + +func (src SyncSourceV2) L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (L2Node, error) { + l1Ref, l2ref, l2ParentHash, err := src.RefByL2Num(ctx, l2Num, genesis) + if err != nil { + return L2Node{}, err + } + return L2Node{self: l2ref, l1parent: l1Ref, l2parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil +} + +func (src SyncSourceV2) L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (L2Node, error) { + l1Ref, l2ref, l2ParentHash, err := src.RefByL2Hash(ctx, l2Hash, genesis) + if err != nil { + return L2Node{}, err + } + return L2Node{self: l2ref, l1parent: l1Ref, l2parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil +} + +type L2Node struct { + self eth.BlockID + l2parent eth.BlockID + l1parent eth.BlockID +} + +type L1Node struct { + self eth.BlockID + parent eth.BlockID +} From 76530ad79532a0506137769ef607545eb85e9ec0 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 16:11:43 -0800 Subject: [PATCH 245/585] ref impl: New sync start algorithms Extended to be able to build sequencing on top of them. --- opnode/rollup/sync/start.go | 126 ++++++++++++- opnode/rollup/sync/start_test.go | 312 +++++++++++++++---------------- 2 files changed, 278 insertions(+), 160 deletions(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 352f9a2312e4..474d44b2a6a2 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -14,7 +14,131 @@ import ( var WrongChainErr = errors.New("wrong chain") -// FindSyncStart finds nextRefL1: the L1 block needed next for sync, to derive into a L2 block on top of refL2. +// The ethereum chain is a DAG of blocks with the root block being the genesis block. +// At any given time, the head (or tip) of the chain can change if an offshoot of the chain +// has a higher difficulty. This is known as a re-organization of the canonical chain. +// Each block points to a parent block and the node is responsible for deciding which block is the head +// and thus the mapping from block number to canonical block. +// +// The optimism chain has similar properties, but also retains references to the ethereum chain. +// Each optimism block retains a reference to an ethereum (L1) block and to it's parent optimism (L2) block. +// The L2 chain node must satisfy the following validity rules +// 1. l2block.height == l2parent.block.height + 1 +// 2. l2block.l1parent.height >= l2block.l2parent.l1parent.height +// 3. l2block.l1parent is in the canonical chain on L1 +// 4. l1_rollup_genesis is reachable from l2block.l1parent +// +// +// During normal operation, both the L1 and L2 canonical chains can change. +// - L1 reorg +// - L1 extension +// - L2 reorg +// - L2 extension +// +// When one of those actions occurs, the L2 chain head may need to be updated and we would like a portion of the L1 chain +// that we should use to derive the L2 chain from. +// These are two different functions, but doing the first requires walking both chains in which case it is easy to also +// return a portion of the chain. +// +// This function returns the highest possible l2block that is valid. This is the (possibly new) L2 chain head. +// It also returns a portion of the L1 chain starting just after l2block.l1parent.number. +// - The L1 chain was canonical when the function was called. +// - The L1 chain is continuous +// - The L1 chain is from low to high +// - The length is not defined. +// If err is not nil, the above return values are not well defined. An error will be returned in the following cases: +// - Wrapped ethereum.NotFound if it could not find a block in L1 or L2. This error may be temporary. +// - Wrapped WrongChainErr if the l1_rollup_genesis block is not reachable from the L2 chain. +// - ?? + +func V3FindSyncStart(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { + l2Head, err := findL2Head(ctx, source, genesis) + if err != nil { + return nil, eth.BlockID{}, err + } + l1blocks, err := findL1Range(ctx, source, l2Head.l1parent) + if err != nil { + return nil, eth.BlockID{}, fmt.Errorf("failed to fetch l1 range: %w", err) + } + + return l1blocks, l2Head.self, nil + +} + +// findL2Head takes the current L2 Head and then finds the topmost L2 head that is valid +// In the case that there are no re-orgs, +func findL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) (L2Node, error) { + // Starting point + l2Head, err := source.L2NodeByNumber(ctx, nil, genesis) + if err != nil { + return L2Node{}, fmt.Errorf("failed to fetch L2 head: %w", err) + } + // Walk L2 chain from L2 head to first L2 block which has a L1 Parent that is canonical. May walk to L2 genesis + for n := l2Head; ; { + l1header, err := source.L1NodeByNumber(ctx, n.l1parent.Number) + if err != nil { + // Generic error, bail out. + if !errors.Is(err, ethereum.NotFound) { + return L2Node{}, fmt.Errorf("failed to fetch L1 block %v: %w", n.l1parent.Number, err) + } + // L1 block not found, keep walking chain + } else { + // L1 Block found, check if matches & should keep walking the chain + if l1header.self.Hash == n.l1parent.Hash { + return n, nil + } + } + + // Don't walk past genesis. If we were at the L2 genesis, but could not find the L1 genesis + // pointed to from it, we are on the wrong L1 chain. + if n.self.Hash == genesis.L2.Hash || n.self.Number == genesis.L2.Number { + return L2Node{}, WrongChainErr + } + + // Pull L2 parent for next iteration + n, err = source.L2NodeByHash(ctx, n.l2parent.Hash, genesis) + if err != nil { + return L2Node{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.l2parent.Hash, err) + } + } +} + +func findL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) ([]eth.BlockID, error) { + if _, err := source.L1NodeByNumber(ctx, begin.Number); err != nil { + return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) + } + // TODO: Check hash here (even if slightly redudant) + l1head, err := source.L1HeadNode(ctx) + if err != nil { + return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) + } + maxBlocks := uint64(100) + if l1head.self.Number-begin.Number <= maxBlocks { + fmt.Println("Capping max blocks") + maxBlocks = l1head.self.Number - begin.Number + fmt.Println(maxBlocks) + } + + prevHash := begin.Hash + var res []eth.BlockID + for i := begin.Number + 1; i < begin.Number+maxBlocks+1; i++ { + fmt.Println(i, i) + n, err := source.L1NodeByNumber(ctx, i) + if err != nil { + return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) + } + fmt.Println(prevHash, n.parent.Hash) + if n.parent.Hash != prevHash { + return nil, errors.New("re-organization occurred while attempting to get l1 range") + } + prevHash = n.self.Hash + res = append(res, n.self) + } + + return res, nil +} + +// FindSyncStart finds nextL1s: the L1 blocks needed next for sync, to derive into a L2 block on top of refL2. // If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. func FindSyncStart(ctx context.Context, reference SyncReference, genesis *rollup.Genesis) (nextRefL1, refL2 eth.BlockID, err error) { var refL1 eth.BlockID // the L1 block the refL2 was derived from diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 575f2726aa54..fbd579e35c4e 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -2,6 +2,7 @@ package sync import ( "context" + "fmt" "math/big" "testing" @@ -103,19 +104,23 @@ type syncStartTestCase struct { Name string OffsetL2 uint64 - EngineL1 string - EngineL2 string - ActualL1 string + EngineL1 string // L1 Chain prior to a re-org or other change + EngineL2 string // L2 Chain that follows from L1Chain + ActualL1 string // L1 Chain after a change may have occurred GenesisL1 rune GenesisL2 rune - ExpectedNextRefL1 rune - ExpectedRefL2 rune + ExpectedNextRefsL1 string // The L1 extension to follow (i.e. L1 after the L1 parent in the new L2 Head) + ExpectedRefL2 rune // The new L2 tip after a L1 change that may have occured ExpectedErr error } +func refToRune(r eth.BlockID) rune { + return rune(r.Hash.Bytes()[0]) +} + func (c *syncStartTestCase) Run(t *testing.T) { engL1 := chainL1(c.OffsetL2, c.EngineL1) engL2 := chainL2(engL1, c.EngineL2) @@ -131,196 +136,185 @@ func (c *syncStartTestCase) Run(t *testing.T) { L2: mockID(c.GenesisL2, 0), } - expectedNextRefL1Num := ^uint64(0) - for i, id := range c.ActualL1 { - if id == c.ExpectedNextRefL1 { - expectedNextRefL1Num = uint64(i) - } - } - if c.ExpectedNextRefL1 == 0 { - expectedNextRefL1Num = uint64(0) - } - expectedNextRefL1 := mockID(c.ExpectedNextRefL1, expectedNextRefL1Num) + fmt.Println(engL1) + fmt.Println(actL1) + fmt.Println(engL2) - expectedRefL2Num := ^uint64(0) - for i, id := range c.EngineL2 { - if id == c.ExpectedRefL2 { - expectedRefL2Num = uint64(i) - } - } - if c.ExpectedRefL2 == 0 { - expectedRefL2Num = uint64(0) - } - expectedRefL2 := mockID(c.ExpectedRefL2, expectedRefL2Num) + nextRefL1s, refL2, err := V3FindSyncStart(context.Background(), SyncSourceV2{msr}, genesis) - nextRefL1, refL2, err := FindSyncStart(context.Background(), msr, genesis) if c.ExpectedErr != nil { - assert.Error(t, err, "got next L1 %s (%d), onto L2: %s (%d)", nextRefL1.Hash[:1], nextRefL1.Number, refL2.Hash[:1], refL2.Number) + assert.Error(t, err, "Expecting an error in this test case") assert.ErrorIs(t, err, c.ExpectedErr) } else { + expectedRefL2 := refToRune(refL2) + var expectedRefsL1 []rune + for _, ref := range nextRefL1s { + expectedRefsL1 = append(expectedRefsL1, refToRune(ref)) + } + assert.NoError(t, err) - assert.Equal(t, expectedNextRefL1, nextRefL1, "expected %s (nr %d) but got %s (nr %d)", expectedNextRefL1.Hash[:1], expectedNextRefL1.Number, nextRefL1.Hash[:1], nextRefL1.Number) - assert.Equal(t, expectedRefL2, refL2, "expected %s (nr %d) but got %s (nr %d)", expectedRefL2.Hash[:1], expectedRefL2.Number, refL2.Hash[:1], refL2.Number) + assert.Equal(t, c.ExpectedNextRefsL1, string(expectedRefsL1), "Next L1 refs not equal") + assert.Equal(t, expectedRefL2, c.ExpectedRefL2, "Next L2 Head not equal") } } func TestFindSyncStart(t *testing.T) { testCases := []syncStartTestCase{ { - Name: "happy extend", - OffsetL2: 0, - EngineL1: "ab", - EngineL2: "AB", - ActualL1: "abc", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 'c', - ExpectedRefL2: 'B', - ExpectedErr: nil, + Name: "happy extend", + OffsetL2: 0, + EngineL1: "ab", + EngineL2: "AB", + ActualL1: "abc", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "c", + ExpectedRefL2: 'B', + ExpectedErr: nil, }, { - Name: "extend one at a time", - OffsetL2: 0, - EngineL1: "ab", - EngineL2: "AB", - ActualL1: "abcdef", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 'c', - ExpectedRefL2: 'B', - ExpectedErr: nil, + Name: "extend one at a time", + OffsetL2: 0, + EngineL1: "ab", + EngineL2: "AB", + ActualL1: "abcdef", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "cdef", + ExpectedRefL2: 'B', + ExpectedErr: nil, }, { - Name: "already synced", - OffsetL2: 0, - EngineL1: "abcde", - EngineL2: "ABCDE", - ActualL1: "abcde", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 'e', - ExpectedRefL2: 'D', - ExpectedErr: nil, + Name: "already synced", + OffsetL2: 0, + EngineL1: "abcde", + EngineL2: "ABCDE", + ActualL1: "abcde", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "", + ExpectedRefL2: 'E', + ExpectedErr: nil, }, { - Name: "genesis", - OffsetL2: 0, - EngineL1: "a", - EngineL2: "A", - ActualL1: "a", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 'a', - ExpectedRefL2: 0, // actual zero hash before genesis hash - ExpectedErr: nil, + Name: "genesis", + OffsetL2: 0, + EngineL1: "a", + EngineL2: "A", + ActualL1: "a", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "", + ExpectedRefL2: 'A', + ExpectedErr: nil, }, { - Name: "reorg two steps back", - OffsetL2: 0, - EngineL1: "abc", - EngineL2: "ABC", - ActualL1: "axy", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 'x', - ExpectedRefL2: 'A', - ExpectedErr: nil, + Name: "reorg two steps back", + OffsetL2: 0, + EngineL1: "abc", + EngineL2: "ABC", + ActualL1: "axy", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "xy", + ExpectedRefL2: 'A', + ExpectedErr: nil, }, { - Name: "Orphan block", - OffsetL2: 0, - EngineL1: "abcd", - EngineL2: "ABCD", - ActualL1: "abcx", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 'x', - ExpectedRefL2: 'C', - ExpectedErr: nil, + Name: "Orphan block", + OffsetL2: 0, + EngineL1: "abcd", + EngineL2: "ABCD", + ActualL1: "abcx", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "x", + ExpectedRefL2: 'C', + ExpectedErr: nil, }, { - Name: "L2 chain ahead", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "abc", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 0, - ExpectedRefL2: 0, - ExpectedErr: ethereum.NotFound, + Name: "L2 chain ahead", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "abc", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "", + ExpectedRefL2: 'C', + ExpectedErr: nil, }, { - Name: "L2 chain ahead reorg", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "abcx", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 'x', - ExpectedRefL2: 'C', - ExpectedErr: nil, + Name: "L2 chain ahead reorg", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "abcx", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "x", + ExpectedRefL2: 'C', + ExpectedErr: nil, }, { - Name: "unexpected L1 chain", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "xyz", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefL1: 0, - ExpectedRefL2: 0, - ExpectedErr: WrongChainErr, + Name: "unexpected L1 chain", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "xyz", + GenesisL1: 'a', + GenesisL2: 'A', + ExpectedNextRefsL1: "", + ExpectedRefL2: 0, + ExpectedErr: WrongChainErr, }, { - Name: "unexpected L2 chain", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "xyz", - GenesisL1: 'a', - GenesisL2: 'X', - ExpectedNextRefL1: 0, - ExpectedRefL2: 0, - ExpectedErr: WrongChainErr, + Name: "unexpected L2 chain", + OffsetL2: 0, + EngineL1: "abcdef", + EngineL2: "ABCDEF", + ActualL1: "xyz", + GenesisL1: 'a', + GenesisL2: 'X', + ExpectedNextRefsL1: "", + ExpectedRefL2: 0, + ExpectedErr: WrongChainErr, }, { - Name: "offset L2 genesis extend", - OffsetL2: 3, - EngineL1: "def", - EngineL2: "DEF", - ActualL1: "abcdefg", - GenesisL1: 'd', - GenesisL2: 'D', - ExpectedNextRefL1: 'g', - ExpectedRefL2: 'F', - ExpectedErr: nil, + Name: "offset L2 genesis extend", + OffsetL2: 3, + EngineL1: "def", + EngineL2: "DEF", + ActualL1: "abcdefg", + GenesisL1: 'd', + GenesisL2: 'D', + ExpectedNextRefsL1: "g", + ExpectedRefL2: 'F', + ExpectedErr: nil, }, { - Name: "offset L2 genesis reorg", - OffsetL2: 3, - EngineL1: "defgh", - EngineL2: "DEFGH", - ActualL1: "abcdx", - GenesisL1: 'd', - GenesisL2: 'D', - ExpectedNextRefL1: 'x', - ExpectedRefL2: 'D', - ExpectedErr: nil, + Name: "offset L2 genesis reorg", + OffsetL2: 3, + EngineL1: "defgh", + EngineL2: "DEFGH", + ActualL1: "abcdx", + GenesisL1: 'd', + GenesisL2: 'D', + ExpectedNextRefsL1: "x", + ExpectedRefL2: 'D', + ExpectedErr: nil, }, { - Name: "reorg past offset genesis", - OffsetL2: 3, - EngineL1: "defgh", - EngineL2: "DEFGH", - ActualL1: "abx", - GenesisL1: 'd', - GenesisL2: 'D', - ExpectedNextRefL1: 0, - ExpectedRefL2: 0, - ExpectedErr: WrongChainErr, + Name: "reorg past offset genesis", + OffsetL2: 3, + EngineL1: "abcdefgh", + EngineL2: "ABCDEFGH", + ActualL1: "abx", + GenesisL1: 'd', + GenesisL2: 'D', + ExpectedNextRefsL1: "", + ExpectedRefL2: 0, + ExpectedErr: WrongChainErr, }, } From ff8db1bb46c3f6e3bec013a547ba46c41b359282 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Feb 2022 16:24:51 -0800 Subject: [PATCH 246/585] ref impl: Use new implementation of sync start --- opnode/rollup/sync/start.go | 92 ++----------------------------------- 1 file changed, 3 insertions(+), 89 deletions(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 474d44b2a6a2..783d49c7cf44 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum/common" ) var WrongChainErr = errors.New("wrong chain") @@ -141,94 +140,9 @@ func findL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) // FindSyncStart finds nextL1s: the L1 blocks needed next for sync, to derive into a L2 block on top of refL2. // If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. func FindSyncStart(ctx context.Context, reference SyncReference, genesis *rollup.Genesis) (nextRefL1, refL2 eth.BlockID, err error) { - var refL1 eth.BlockID // the L1 block the refL2 was derived from - var parentL2 common.Hash // the parent of refL2 - // Start at L2 head - refL1, refL2, parentL2, err = reference.RefByL2Num(ctx, nil, genesis) - if err != nil { - err = fmt.Errorf("failed to fetch L2 head: %v", err) - return - } - // Check if L1 source has the block - var currentL1 eth.BlockID // the expected L1 block at the height of refL1 - currentL1, _, err = reference.RefByL1Num(ctx, refL1.Number) - if err != nil { - if !errors.Is(err, ethereum.NotFound) { - err = fmt.Errorf("failed to lookup block %d in L1: %w", refL1.Number, err) - return - } - // If the L1 did not find the block, it might be out of sync. - // We cannot sync from L1 in this case, but we still traverse back to - // make sure we are not just in a reorg to a L1 chain with fewer blocks. - err = nil - currentL1 = eth.BlockID{} // empty = not found - } - if currentL1 == refL1 { - // L1 node has head-block of execution-engine, so we should fetch the L1 block that builds on top. - var ontoL1 eth.BlockID // ontoL1 is the parent, to make sure we got a nextRefL1 that connects as expected. - nextRefL1, ontoL1, err = reference.RefByL1Num(ctx, refL1.Number+1) - if err != nil { - // If refL1 is the head block, then we might not have a next block to build on the head - if errors.Is(err, ethereum.NotFound) { - // return the same as the engine head was already built on, no error. - nextRefL1 = refL1 - refL2 = eth.BlockID{Hash: parentL2, Number: refL2.Number} - if refL2.Number > 0 { - refL2.Number -= 1 - } - err = nil - return - } - return - } - // The L1 source might rug us with a reorg between API calls, catch that. - if ontoL1 != currentL1 { - err = fmt.Errorf("the L1 source reorged, the block for N+1 %s doesn't have the previously fetched block N %s as parent, but builds on %s instead", nextRefL1, currentL1, ontoL1) - } - return - } - - // Search back: linear walk back from engine head. Should only be as deep as the reorg. - for refL2.Number > 0 { - // remember the canonical L1 block that builds on top of the L1 source block of the L2 parent block. - nextRefL1 = currentL1 - refL1, refL2, parentL2, err = reference.RefByL2Hash(ctx, parentL2, genesis) - if err != nil { - // TODO: re-attempt look-up, now that we already traversed previous history? - err = fmt.Errorf("failed to lookup block %s in L2: %w", refL2, err) // refL2 is previous parentL2 - return - } - // Check if L1 source has the block that derived the L2 block we are planning to build on - currentL1, _, err = reference.RefByL1Num(ctx, refL1.Number) - if err != nil { - if !errors.Is(err, ethereum.NotFound) { - err = fmt.Errorf("failed to lookup block %d in L1: %w", refL1.Number, err) - return - } - // again, if L1 does not have the block, then we just search if we are reorging. - err = nil - currentL1 = eth.BlockID{} // empty = not found - } - if currentL1 == refL1 { - // check if we had a L1 block to build on top of the common chain with - if nextRefL1 == (eth.BlockID{}) { - err = ethereum.NotFound - } - return - } - // TODO: after e.g. initial N steps, use binary search instead - // (relies on block numbers, not great for tip of chain, but nice-to-have in deep reorgs) - } - // Enforce that we build on the desired genesis block. - // The engine might be configured for a different chain or older testnet. - if refL2 != genesis.L2 { - err = fmt.Errorf("unexpected L2 genesis block: %s, expected %s, %w", refL2, genesis.L2, WrongChainErr) - return - } - if currentL1 != genesis.L1 { - err = fmt.Errorf("unexpected L1 anchor block: %s, expected %s, %w", currentL1, genesis.L1, WrongChainErr) - return + l1s, refL2, err := V3FindSyncStart(ctx, SyncSourceV2{reference}, genesis) + if err != nil && len(l1s) > 0 { + nextRefL1 = l1s[0] } - // we got the correct genesis, all good, but a lot to sync! return } From 2c4017d4982a7dd2175e6e89a900c375322cc98f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 28 Jan 2022 13:49:55 -0800 Subject: [PATCH 247/585] feat: add vim swap files to gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a6cdcec18194..6841a1f303c3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,7 @@ coverage.out .deps # built binaries -bin \ No newline at end of file +bin +# +# vim swap files +*.sw* From 18ef32dc557c026b92b53b197971cca03887afeb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 28 Jan 2022 10:41:52 -0800 Subject: [PATCH 248/585] feat: copy stripped down EIP-1559 BSS --- l2os/.gitignore | 1 + l2os/Makefile | 26 ++ l2os/cmd/l2os/main.go | 43 +++ l2os/config.go | 71 +++++ l2os/drivers/interface.go | 36 +++ l2os/flags/flags.go | 105 +++++++ l2os/flags/flags_test.go | 28 ++ l2os/l2_output_submitter.go | 161 ++++++++++ l2os/mock/l1client.go | 164 ++++++++++ l2os/service.go | 170 +++++++++++ l2os/txmgr/send_state.go | 111 +++++++ l2os/txmgr/send_state_test.go | 161 ++++++++++ l2os/txmgr/txmgr.go | 327 ++++++++++++++++++++ l2os/txmgr/txmgr_test.go | 543 ++++++++++++++++++++++++++++++++++ 14 files changed, 1947 insertions(+) create mode 100644 l2os/.gitignore create mode 100644 l2os/Makefile create mode 100644 l2os/cmd/l2os/main.go create mode 100644 l2os/config.go create mode 100644 l2os/drivers/interface.go create mode 100644 l2os/flags/flags.go create mode 100644 l2os/flags/flags_test.go create mode 100644 l2os/l2_output_submitter.go create mode 100644 l2os/mock/l1client.go create mode 100644 l2os/service.go create mode 100644 l2os/txmgr/send_state.go create mode 100644 l2os/txmgr/send_state_test.go create mode 100644 l2os/txmgr/txmgr.go create mode 100644 l2os/txmgr/txmgr_test.go diff --git a/l2os/.gitignore b/l2os/.gitignore new file mode 100644 index 000000000000..edc49d3186f3 --- /dev/null +++ b/l2os/.gitignore @@ -0,0 +1 @@ +/l2os diff --git a/l2os/Makefile b/l2os/Makefile new file mode 100644 index 000000000000..4d9a20e201b9 --- /dev/null +++ b/l2os/Makefile @@ -0,0 +1,26 @@ +GITCOMMIT := $(shell git rev-parse HEAD) +GITDATE := $(shell git show -s --format='%ct') +VERSION := v0.0.0 + +LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) +LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) +LDFLAGSSTRING +=-X main.Version=$(VERSION) +LDFLAGS := -ldflags "$(LDFLAGSSTRING)" + +l2os: + env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/l2os + +clean: + rm l2os + +test: + go test -v ./... + +lint: + golangci-lint run ./... + +.PHONY: \ + clean \ + l2os \ + test \ + lint diff --git a/l2os/cmd/l2os/main.go b/l2os/cmd/l2os/main.go new file mode 100644 index 000000000000..ee3f3c0a7459 --- /dev/null +++ b/l2os/cmd/l2os/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "os" + + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli" + + "github.com/ethereum-optimism/optimistic-specs/l2os" + "github.com/ethereum-optimism/optimistic-specs/l2os/flags" +) + +var ( + Version = "" + GitCommit = "" + GitDate = "" +) + +func main() { + // Set up logger with a default INFO level in case we fail to parse flags, + // otherwise the final critical log won't show what the parsing error was. + log.Root().SetHandler( + log.LvlFilterHandler( + log.LvlInfo, + log.StreamHandler(os.Stdout, log.TerminalFormat(true)), + ), + ) + + app := cli.NewApp() + app.Flags = flags.Flags + app.Version = fmt.Sprintf("%s-%s-%s", Version, GitCommit, GitDate) + app.Name = "l2os" + app.Usage = "L2Output Submitter" + app.Description = "Service for generating and submitting L2 Output " + + "checkpoints to the L2OutputOracle contract" + + app.Action = l2os.Main(Version) + err := app.Run(os.Args) + if err != nil { + log.Crit("Application failed", "message", err) + } +} diff --git a/l2os/config.go b/l2os/config.go new file mode 100644 index 000000000000..78ec5a61e367 --- /dev/null +++ b/l2os/config.go @@ -0,0 +1,71 @@ +package l2os + +import ( + "time" + + "github.com/urfave/cli" + + "github.com/ethereum-optimism/optimistic-specs/l2os/flags" +) + +type Config struct { + /* Required Params */ + + // L1EthRpc is the HTTP provider URL for L1. + L1EthRpc string + + // L2EthRpc is the HTTP provider URL for L1. + L2EthRpc string + + // L2OOAddress is the L2OutputOracle contract address. + L2OOAddress string + + // PollInterval is the delay between querying L2 for more transaction + // and creating a new batch. + PollInterval time.Duration + + // NumConfirmations is the number of confirmations which we will wait after + // appending new batches. + NumConfirmations uint64 + + // SafeAbortNonceTooLowCount is the number of ErrNonceTooLowObservations + // required to give up on a tx at a particular nonce without receiving + // confirmation. + SafeAbortNonceTooLowCount uint64 + + // ResubmissionTimeout is time we will wait before resubmitting a + // transaction. + ResubmissionTimeout time.Duration + + // Mnemonic is the HD seed used to derive the wallet private keys for both + // the sequence and proposer. Must be used in conjunction with + // SequencerHDPath and ProposerHDPath. + Mnemonic string + + // L2OutputHDPath is the derivation path used to obtain the private key for + // the l2output transactions. + L2OutputHDPath string + + /* Optional Params */ + + // LogLevel is the lowest log level that will be output. + LogLevel string +} + +// NewConfig parses the Config from the provided flags or environment variables. +func NewConfig(ctx *cli.Context) Config { + return Config{ + /* Required Flags */ + L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name), + L2EthRpc: ctx.GlobalString(flags.L2EthRpcFlag.Name), + L2OOAddress: ctx.GlobalString(flags.L2OOAddressFlag.Name), + PollInterval: ctx.GlobalDuration(flags.PollIntervalFlag.Name), + NumConfirmations: ctx.GlobalUint64(flags.NumConfirmationsFlag.Name), + SafeAbortNonceTooLowCount: ctx.GlobalUint64(flags.SafeAbortNonceTooLowCountFlag.Name), + ResubmissionTimeout: ctx.GlobalDuration(flags.ResubmissionTimeoutFlag.Name), + Mnemonic: ctx.GlobalString(flags.MnemonicFlag.Name), + L2OutputHDPath: ctx.GlobalString(flags.L2OutputHDPathFlag.Name), + /* Optional Flags */ + LogLevel: ctx.GlobalString(flags.LogLevelFlag.Name), + } +} diff --git a/l2os/drivers/interface.go b/l2os/drivers/interface.go new file mode 100644 index 000000000000..286518ef5c43 --- /dev/null +++ b/l2os/drivers/interface.go @@ -0,0 +1,36 @@ +package drivers + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// L1Client is an abstraction over an L1 Ethereum client functionality required +// by the batch submitter. +type L1Client interface { + // HeaderByNumber returns a block header from the current canonical chain. + // If number is nil, the latest known header is returned. + HeaderByNumber(context.Context, *big.Int) (*types.Header, error) + + // NonceAt returns the account nonce of the given account. The block number + // can be nil, in which case the nonce is taken from the latest known block. + NonceAt(context.Context, common.Address, *big.Int) (uint64, error) + + // SendTransaction injects a signed transaction into the pending pool for + // execution. + // + // If the transaction was a contract creation use the TransactionReceipt + // method to get the contract address after the transaction has been mined. + SendTransaction(context.Context, *types.Transaction) error + + // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 + // to allow a timely execution of a transaction. + SuggestGasTipCap(context.Context) (*big.Int, error) + + // TransactionReceipt returns the receipt of a transaction by transaction + // hash. Note that the receipt is not available for pending transactions. + TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) +} diff --git a/l2os/flags/flags.go b/l2os/flags/flags.go new file mode 100644 index 000000000000..5a5a927415bd --- /dev/null +++ b/l2os/flags/flags.go @@ -0,0 +1,105 @@ +package flags + +import ( + "github.com/urfave/cli" +) + +const envVarPrefix = "BATCH_SUBMITTER_" + +func prefixEnvVar(name string) string { + return envVarPrefix + name +} + +var ( + /* Required Flags */ + + L1EthRpcFlag = cli.StringFlag{ + Name: "l1-eth-rpc", + Usage: "HTTP provider URL for L1", + Required: true, + EnvVar: "L1_ETH_RPC", + } + L2EthRpcFlag = cli.StringFlag{ + Name: "l2-eth-rpc", + Usage: "HTTP provider URL for L2", + Required: true, + EnvVar: "L2_ETH_RPC", + } + L2OOAddressFlag = cli.StringFlag{ + Name: "l2oo-address", + Usage: "Address of the L2OutputOracle contract", + Required: true, + EnvVar: "L2OO_ADDRESS", + } + PollIntervalFlag = cli.DurationFlag{ + Name: "poll-interval", + Usage: "Delay between querying L2 for more transactions and " + + "creating a new batch", + Required: true, + EnvVar: prefixEnvVar("POLL_INTERVAL"), + } + NumConfirmationsFlag = cli.Uint64Flag{ + Name: "num-confirmations", + Usage: "Number of confirmations which we will wait after " + + "appending a new batch", + Required: true, + EnvVar: prefixEnvVar("NUM_CONFIRMATIONS"), + } + SafeAbortNonceTooLowCountFlag = cli.Uint64Flag{ + Name: "safe-abort-nonce-too-low-count", + Usage: "Number of ErrNonceTooLow observations required to " + + "give up on a tx at a particular nonce without receiving " + + "confirmation", + Required: true, + EnvVar: prefixEnvVar("SAFE_ABORT_NONCE_TOO_LOW_COUNT"), + } + ResubmissionTimeoutFlag = cli.DurationFlag{ + Name: "resubmission-timeout", + Usage: "Duration we will wait before resubmitting a " + + "transaction to L1", + Required: true, + EnvVar: prefixEnvVar("RESUBMISSION_TIMEOUT"), + } + MnemonicFlag = cli.StringFlag{ + Name: "mnemonic", + Usage: "The mnemonic used to derive the wallets for either the " + + "sequencer or the l2output", + Required: true, + EnvVar: prefixEnvVar("MNEMONIC"), + } + L2OutputHDPathFlag = cli.StringFlag{ + Name: "l2-output-hd-path", + Usage: "The HD path used to derive the l2output wallet from the " + + "mnemonic. The mnemonic flag must also be set.", + Required: true, + EnvVar: prefixEnvVar("L2_OUTPUT_HD_PATH"), + } + + /* Optional Flags */ + + LogLevelFlag = cli.StringFlag{ + Name: "log-level", + Usage: "The lowest log level that will be output", + Value: "info", + EnvVar: prefixEnvVar("LOG_LEVEL"), + } +) + +var requiredFlags = []cli.Flag{ + L1EthRpcFlag, + L2EthRpcFlag, + L2OOAddressFlag, + PollIntervalFlag, + NumConfirmationsFlag, + SafeAbortNonceTooLowCountFlag, + ResubmissionTimeoutFlag, + MnemonicFlag, + L2OutputHDPathFlag, +} + +var optionalFlags = []cli.Flag{ + LogLevelFlag, +} + +// Flags contains the list of configuration options available to the binary. +var Flags = append(requiredFlags, optionalFlags...) diff --git a/l2os/flags/flags_test.go b/l2os/flags/flags_test.go new file mode 100644 index 000000000000..ae0bc3d02e37 --- /dev/null +++ b/l2os/flags/flags_test.go @@ -0,0 +1,28 @@ +package flags + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli" +) + +// TestRequiredFlagsSetRequired asserts that all flags deemed required properly +// have the Required field set to true. +func TestRequiredFlagsSetRequired(t *testing.T) { + for _, flag := range requiredFlags { + reqFlag, ok := flag.(cli.RequiredFlag) + require.True(t, ok) + require.True(t, reqFlag.IsRequired()) + } +} + +// TestOptionalFlagsDontSetRequired asserts that all flags deemed optional set +// the Required field to false. +func TestOptionalFlagsDontSetRequired(t *testing.T) { + for _, flag := range optionalFlags { + reqFlag, ok := flag.(cli.RequiredFlag) + require.True(t, ok) + require.False(t, reqFlag.IsRequired()) + } +} diff --git a/l2os/l2_output_submitter.go b/l2os/l2_output_submitter.go new file mode 100644 index 000000000000..3c83f8e2cbbe --- /dev/null +++ b/l2os/l2_output_submitter.go @@ -0,0 +1,161 @@ +package l2os + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" + "time" + + "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + hdwallet "github.com/miguelmota/go-ethereum-hdwallet" + "github.com/urfave/cli" +) + +const ( + // defaultDialTimeout is default duration the service will wait on + // startup to make a connection to either the L1 or L2 backends. + defaultDialTimeout = 5 * time.Second +) + +// Main is the entrypoint into the L2 Output Submitter. This method returns a +// closure that executes the service and blocks until the service exits. The use +// of a closure allows the parameters bound to the top-level main package, e.g. +// GitVersion, to be captured and used once the function is executed. +func Main(version string) func(ctx *cli.Context) error { + return func(ctx *cli.Context) error { + cfg := NewConfig(ctx) + + log.Info("Initializing L2 Output Submitter") + + l2OutputSubmitter, err := NewL2OutputSubmitter(cfg, version) + if err != nil { + log.Error("Unable to create L2 Output Submitter", "error", err) + return err + } + + log.Info("Starting L2 Output Submitter") + + if err := l2OutputSubmitter.Start(); err != nil { + log.Error("Unable to start L2 Output Submitter", "error", err) + return err + } + defer l2OutputSubmitter.Stop() + + log.Info("L2 Output Submitter started") + + interruptChannel := make(chan os.Signal, 1) + signal.Notify(interruptChannel, []os.Signal{ + os.Interrupt, + os.Kill, + syscall.SIGTERM, + syscall.SIGQUIT, + }...) + <-interruptChannel + + return nil + } +} + +// L2OutputSubmitter encapsulates a service responsible for submitting +// L2Outputs to the L2OutputOracle contract. +type L2OutputSubmitter struct { + ctx context.Context +} + +// NewL2OutputSubmitter initializes the L2OutputSubmitter, gathering any resources +// that will be needed during operation. +func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, error) { + ctx := context.Background() + + // Set up our logging to stdout. + logHandler := log.StreamHandler(os.Stdout, log.TerminalFormat(true)) + + logLevel, err := log.LvlFromString(cfg.LogLevel) + if err != nil { + return nil, err + } + + log.Root().SetHandler(log.LvlFilterHandler(logLevel, logHandler)) + + // Parse l2output wallet private key and L2OO contract address. + wallet, err := hdwallet.NewFromMnemonic(cfg.Mnemonic) + if err != nil { + return nil, err + } + + _, err = wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: cfg.L2OutputHDPath, + }, + }) + if err != nil { + return nil, err + } + + _, err = parseAddress(cfg.L2OOAddress) + if err != nil { + return nil, err + } + + // Connect to L1 and L2 providers. Perform these last since they are the + // most expensive. + l1Client, err := dialEthClientWithTimeout(ctx, cfg.L1EthRpc) + if err != nil { + return nil, err + } + + _, err = dialEthClientWithTimeout(ctx, cfg.L2EthRpc) + if err != nil { + return nil, err + } + + _, err = l1Client.ChainID(ctx) + if err != nil { + return nil, err + } + + _ = txmgr.Config{ + ResubmissionTimeout: cfg.ResubmissionTimeout, + ReceiptQueryInterval: time.Second, + NumConfirmations: cfg.NumConfirmations, + SafeAbortNonceTooLowCount: cfg.SafeAbortNonceTooLowCount, + } + + return &L2OutputSubmitter{ + ctx: ctx, + }, nil +} + +func (l *L2OutputSubmitter) Start() error { + return nil +} + +func (l *L2OutputSubmitter) Stop() { +} + +// dialEthClientWithTimeout attempts to dial the L1 provider using the provided +// URL. If the dial doesn't complete within defaultDialTimeout seconds, this +// method will return an error. +func dialEthClientWithTimeout(ctx context.Context, url string) ( + *ethclient.Client, error) { + + ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) + defer cancel() + + return ethclient.DialContext(ctxt, url) +} + +// parseAddress parses an ETH addres from a hex string. This method will fail if +// the address is not a valid hexidecimal address. +func parseAddress(address string) (common.Address, error) { + if common.IsHexAddress(address) { + return common.HexToAddress(address), nil + } + return common.Address{}, fmt.Errorf("invalid address: %v", address) +} diff --git a/l2os/mock/l1client.go b/l2os/mock/l1client.go new file mode 100644 index 000000000000..cdb7df333d6c --- /dev/null +++ b/l2os/mock/l1client.go @@ -0,0 +1,164 @@ +package mock + +import ( + "context" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// L1ClientConfig houses the internal methods that are executed by the mock +// L1Client. Any members left as nil will panic on execution. +type L1ClientConfig struct { + // BlockNumber returns the most recent block number. + BlockNumber func(context.Context) (uint64, error) + + // HeaderByNumber returns a block header from the current canonical chain. + // If number is nil, the latest known header is returned. + HeaderByNumber func(context.Context, *big.Int) (*types.Header, error) + + // NonceAt returns the account nonce of the given account. The block number + // can be nil, in which case the nonce is taken from the latest known block. + NonceAt func(context.Context, common.Address, *big.Int) (uint64, error) + + // SendTransaction injects a signed transaction into the pending pool for + // execution. + // + // If the transaction was a contract creation use the TransactionReceipt + // method to get the contract address after the transaction has been mined. + SendTransaction func(context.Context, *types.Transaction) error + + // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 + // to allow a timely execution of a transaction. + SuggestGasTipCap func(context.Context) (*big.Int, error) + + // TransactionReceipt returns the receipt of a transaction by transaction + // hash. Note that the receipt is not available for pending transactions. + TransactionReceipt func(context.Context, common.Hash) (*types.Receipt, error) +} + +// L1Client represents a mock L1Client. +type L1Client struct { + cfg L1ClientConfig + mu sync.RWMutex +} + +// NewL1Client returns a new L1Client using the mocked methods in the +// L1ClientConfig. +func NewL1Client(cfg L1ClientConfig) *L1Client { + return &L1Client{ + cfg: cfg, + } +} + +// BlockNumber returns the most recent block number. +func (c *L1Client) BlockNumber(ctx context.Context) (uint64, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.cfg.BlockNumber(ctx) +} + +// HeaderByNumber returns a block header from the current canonical chain. If +// number is nil, the latest known header is returned. +func (c *L1Client) HeaderByNumber(ctx context.Context, blockNumber *big.Int) (*types.Header, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.cfg.HeaderByNumber(ctx, blockNumber) +} + +// NonceAt executes the mock NonceAt method. +func (c *L1Client) NonceAt(ctx context.Context, addr common.Address, blockNumber *big.Int) (uint64, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.cfg.NonceAt(ctx, addr, blockNumber) +} + +// SendTransaction executes the mock SendTransaction method. +func (c *L1Client) SendTransaction(ctx context.Context, tx *types.Transaction) error { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.cfg.SendTransaction(ctx, tx) +} + +// SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to +// allow a timely execution of a transaction. +func (c *L1Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.cfg.SuggestGasTipCap(ctx) +} + +// TransactionReceipt executes the mock TransactionReceipt method. +func (c *L1Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.cfg.TransactionReceipt(ctx, txHash) +} + +// SetBlockNumberFunc overwrites the mock BlockNumber method. +func (c *L1Client) SetBlockNumberFunc( + f func(context.Context) (uint64, error)) { + + c.mu.Lock() + defer c.mu.Unlock() + + c.cfg.BlockNumber = f +} + +// SetHeaderByNumberFunc overwrites the mock HeaderByNumber method. +func (c *L1Client) SetHeaderByNumberFunc( + f func(ctx context.Context, blockNumber *big.Int) (*types.Header, error)) { + + c.mu.Lock() + defer c.mu.Unlock() + + c.cfg.HeaderByNumber = f +} + +// SetNonceAtFunc overwrites the mock NonceAt method. +func (c *L1Client) SetNonceAtFunc( + f func(context.Context, common.Address, *big.Int) (uint64, error)) { + + c.mu.Lock() + defer c.mu.Unlock() + + c.cfg.NonceAt = f +} + +// SetSendTransactionFunc overwrites the mock SendTransaction method. +func (c *L1Client) SetSendTransactionFunc( + f func(context.Context, *types.Transaction) error) { + + c.mu.Lock() + defer c.mu.Unlock() + + c.cfg.SendTransaction = f +} + +// SetSuggestGasTipCapFunc overwrites themock SuggestGasTipCap method. +func (c *L1Client) SetSuggestGasTipCapFunc( + f func(context.Context) (*big.Int, error)) { + + c.mu.Lock() + defer c.mu.Unlock() + + c.cfg.SuggestGasTipCap = f +} + +// SetTransactionReceiptFunc overwrites the mock TransactionReceipt method. +func (c *L1Client) SetTransactionReceiptFunc( + f func(context.Context, common.Hash) (*types.Receipt, error)) { + + c.mu.Lock() + defer c.mu.Unlock() + + c.cfg.TransactionReceipt = f +} diff --git a/l2os/service.go b/l2os/service.go new file mode 100644 index 000000000000..71d413eadf89 --- /dev/null +++ b/l2os/service.go @@ -0,0 +1,170 @@ +package l2os + +import ( + "context" + "math/big" + "sync" + "time" + + "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" +) + +// Driver is an interface for creating and submitting transactions for a +// specific contract. +type Driver interface { + // Name is an identifier used to prefix logs for a particular service. + Name() string + + // WalletAddr is the wallet address used to pay for transaction fees. + WalletAddr() common.Address + + // GetBlockRange returns the start and end L2 block heights that need to be + // processed. Note that the end value is *exclusive*, therefore if the + // returned values are identical nothing needs to be processed. + GetBlockRange(ctx context.Context) (*big.Int, *big.Int, error) + + // CraftTx transforms the L2 blocks between start and end into a transaction + // using the given nonce. + // + // NOTE: This method SHOULD NOT publish the resulting transaction. + CraftTx( + ctx context.Context, + start, end, nonce *big.Int, + ) (*types.Transaction, error) + + // UpdateGasPrice signs an otherwise identical txn to the one provided but + // with updated gas prices sampled from the existing network conditions. + // + // NOTE: Thie method SHOULD NOT publish the resulting transaction. + UpdateGasPrice( + ctx context.Context, + tx *types.Transaction, + ) (*types.Transaction, error) + + // SendTransaction injects a signed transaction into the pending pool for + // execution. + SendTransaction(ctx context.Context, tx *types.Transaction) error +} + +type ServiceConfig struct { + Context context.Context + Driver Driver + PollInterval time.Duration + L1Client *ethclient.Client + TxManagerConfig txmgr.Config +} + +type Service struct { + cfg ServiceConfig + ctx context.Context + cancel func() + + txMgr txmgr.TxManager + + wg sync.WaitGroup +} + +func NewService(cfg ServiceConfig) *Service { + ctx, cancel := context.WithCancel(cfg.Context) + + txMgr := txmgr.NewSimpleTxManager( + cfg.Driver.Name(), cfg.TxManagerConfig, cfg.L1Client, + ) + + return &Service{ + cfg: cfg, + ctx: ctx, + cancel: cancel, + txMgr: txMgr, + } +} + +func (s *Service) Start() error { + s.wg.Add(1) + go s.eventLoop() + return nil +} + +func (s *Service) Stop() error { + s.cancel() + s.wg.Wait() + return nil +} + +func (s *Service) eventLoop() { + defer s.wg.Done() + + name := s.cfg.Driver.Name() + + for { + select { + case <-time.After(s.cfg.PollInterval): + // Determine the range of L2 blocks that the submitter has not + // processed, and needs to take action on. + log.Info(name + " fetching current block range") + start, end, err := s.cfg.Driver.GetBlockRange(s.ctx) + if err != nil { + log.Error(name+" unable to get block range", "err", err) + continue + } + + // No new updates. + if start.Cmp(end) == 0 { + log.Info(name+" no updates", "start", start, "end", end) + continue + } + log.Info(name+" block range", "start", start, "end", end) + + // Query for the submitter's current nonce. + nonce64, err := s.cfg.L1Client.NonceAt( + s.ctx, s.cfg.Driver.WalletAddr(), nil, + ) + if err != nil { + log.Error(name+" unable to get current nonce", + "err", err) + continue + } + nonce := new(big.Int).SetUint64(nonce64) + + tx, err := s.cfg.Driver.CraftTx( + s.ctx, start, end, nonce, + ) + if err != nil { + log.Error(name+" unable to craft tx", + "err", err) + continue + } + + // Construct the a closure that will update the txn with the current + // gas prices. + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + log.Info(name+" updating batch tx gas price", "start", start, + "end", end, "nonce", nonce) + + return s.cfg.Driver.UpdateGasPrice(ctx, tx) + } + + // Wait until one of our submitted transactions confirms. If no + // receipt is received it's likely our gas price was too low. + receipt, err := s.txMgr.Send( + s.ctx, updateGasPrice, s.cfg.Driver.SendTransaction, + ) + if err != nil { + log.Error(name+" unable to publish tx", "err", err) + continue + } + + // The transaction was successfully submitted. + log.Info(name+" tx successfully published", + "tx_hash", receipt.TxHash) + + case err := <-s.ctx.Done(): + log.Error(name+" service shutting down", "err", err) + return + } + } +} diff --git a/l2os/txmgr/send_state.go b/l2os/txmgr/send_state.go new file mode 100644 index 000000000000..c223f743edfc --- /dev/null +++ b/l2os/txmgr/send_state.go @@ -0,0 +1,111 @@ +package txmgr + +import ( + "strings" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" +) + +// SendState tracks information about the publication state of a given txn. In +// this context, a txn may correspond to multiple different txn hashes due to +// varying gas prices, though we treat them all as the same logical txn. This +// struct is primarly used to determine whether or not the txmgr should abort a +// given txn and retry with a higher nonce. +type SendState struct { + minedTxs map[common.Hash]struct{} + nonceTooLowCount uint64 + mu sync.RWMutex + + safeAbortNonceTooLowCount uint64 +} + +// NewSendState parameterizes a new SendState from the passed +// safeAbortNonceTooLowCount. +func NewSendState(safeAbortNonceTooLowCount uint64) *SendState { + if safeAbortNonceTooLowCount == 0 { + panic("txmgr: safeAbortNonceTooLowCount cannot be zero") + } + + return &SendState{ + minedTxs: make(map[common.Hash]struct{}), + nonceTooLowCount: 0, + safeAbortNonceTooLowCount: safeAbortNonceTooLowCount, + } +} + +// ProcessSendError should be invoked with the error returned for each +// publication. It is safe to call this method with nil or arbitrary errors. +// Currently it only acts on errors containing the ErrNonceTooLow message. +func (s *SendState) ProcessSendError(err error) { + // Nothing to do. + if err == nil { + return + } + + // Only concerned with ErrNonceTooLow. + if !strings.Contains(err.Error(), core.ErrNonceTooLow.Error()) { + return + } + + s.mu.Lock() + defer s.mu.Unlock() + + // Record this nonce too low observation. + s.nonceTooLowCount++ +} + +// TxMined records that the txn with txnHash has been mined and is await +// confirmation. It is safe to call this function multiple times. +func (s *SendState) TxMined(txHash common.Hash) { + s.mu.Lock() + defer s.mu.Unlock() + + s.minedTxs[txHash] = struct{}{} +} + +// TxMined records that the txn with txnHash has not been mined or has been +// reorg'd out. It is safe to call this function multiple times. +func (s *SendState) TxNotMined(txHash common.Hash) { + s.mu.Lock() + defer s.mu.Unlock() + + _, wasMined := s.minedTxs[txHash] + delete(s.minedTxs, txHash) + + // If the txn got reorged and left us with no mined txns, reset the nonce + // too low count, otherwise we might abort too soon when processing the next + // error. If the nonce too low errors persist, we want to ensure we wait out + // the full safe abort count to enesure we have a sufficient number of + // observations. + if len(s.minedTxs) == 0 && wasMined { + s.nonceTooLowCount = 0 + } +} + +// ShouldAbortImmediately returns true if the txmgr should give up on trying a +// given txn with the target nonce. For now, this only happens if we see an +// extended period of getting ErrNonceTooLow without having a txn mined. +func (s *SendState) ShouldAbortImmediately() bool { + s.mu.RLock() + defer s.mu.RUnlock() + + // Never abort if our latest sample reports having at least one mined txn. + if len(s.minedTxs) > 0 { + return false + } + + // Only abort if we've observed enough ErrNonceTooLow to meet our safe abort + // threshold. + return s.nonceTooLowCount >= s.safeAbortNonceTooLowCount +} + +// IsWaitingForConfirmation returns true if we have at least one confirmation on +// one of our txs. +func (s *SendState) IsWaitingForConfirmation() bool { + s.mu.RLock() + defer s.mu.RUnlock() + + return len(s.minedTxs) > 0 +} diff --git a/l2os/txmgr/send_state_test.go b/l2os/txmgr/send_state_test.go new file mode 100644 index 000000000000..8dd610793646 --- /dev/null +++ b/l2os/txmgr/send_state_test.go @@ -0,0 +1,161 @@ +package txmgr_test + +import ( + "errors" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/stretchr/testify/require" +) + +const testSafeAbortNonceTooLowCount = 3 + +var ( + testHash = common.HexToHash("0x01") +) + +func newSendState() *txmgr.SendState { + return txmgr.NewSendState(testSafeAbortNonceTooLowCount) +} + +func processNSendErrors(sendState *txmgr.SendState, err error, n int) { + for i := 0; i < n; i++ { + sendState.ProcessSendError(err) + } +} + +// TestSendStateNoAbortAfterInit asserts that the default SendState won't +// trigger an abort even after the safe abort interval has elapsed. +func TestSendStateNoAbortAfterInit(t *testing.T) { + sendState := newSendState() + require.False(t, sendState.ShouldAbortImmediately()) + require.False(t, sendState.IsWaitingForConfirmation()) +} + +// TestSendStateNoAbortAfterProcessNilError asserts that nil errors are not +// considered for abort status. +func TestSendStateNoAbortAfterProcessNilError(t *testing.T) { + sendState := newSendState() + + processNSendErrors(sendState, nil, testSafeAbortNonceTooLowCount) + require.False(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateNoAbortAfterProcessOtherError asserts that non-nil errors other +// than ErrNonceTooLow are not considered for abort status. +func TestSendStateNoAbortAfterProcessOtherError(t *testing.T) { + sendState := newSendState() + + otherError := errors.New("other error") + processNSendErrors(sendState, otherError, testSafeAbortNonceTooLowCount) + require.False(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateAbortSafelyAfterNonceTooLowButNoTxMined asserts that we will +// abort after the safe abort interval has elapsed if we haven't mined a tx. +func TestSendStateAbortSafelyAfterNonceTooLowButNoTxMined(t *testing.T) { + sendState := newSendState() + + sendState.ProcessSendError(core.ErrNonceTooLow) + require.False(t, sendState.ShouldAbortImmediately()) + sendState.ProcessSendError(core.ErrNonceTooLow) + require.False(t, sendState.ShouldAbortImmediately()) + sendState.ProcessSendError(core.ErrNonceTooLow) + require.True(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateMiningTxCancelsAbort asserts that a tx getting mined after +// processing ErrNonceTooLow takes precedence and doesn't cause an abort. +func TestSendStateMiningTxCancelsAbort(t *testing.T) { + sendState := newSendState() + + sendState.ProcessSendError(core.ErrNonceTooLow) + sendState.ProcessSendError(core.ErrNonceTooLow) + sendState.TxMined(testHash) + require.False(t, sendState.ShouldAbortImmediately()) + sendState.ProcessSendError(core.ErrNonceTooLow) + require.False(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateReorgingTxResetsAbort asserts that unmining a tx does not +// consider ErrNonceTooLow's prior to being mined when determing whether to +// abort. +func TestSendStateReorgingTxResetsAbort(t *testing.T) { + sendState := newSendState() + + sendState.ProcessSendError(core.ErrNonceTooLow) + sendState.ProcessSendError(core.ErrNonceTooLow) + sendState.TxMined(testHash) + sendState.TxNotMined(testHash) + sendState.ProcessSendError(core.ErrNonceTooLow) + require.False(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateNoAbortEvenIfNonceTooLowAfterTxMined asserts that we will not +// abort if we continue to get ErrNonceTooLow after a tx has been mined. +// +// NOTE: This is the most crucial role of the SendState, as we _expect_ to get +// ErrNonceTooLow failures after one of our txs has been mined, but that +// shouldn't cause us to not continue waiting for confirmations. +func TestSendStateNoAbortEvenIfNonceTooLowAfterTxMined(t *testing.T) { + sendState := newSendState() + + sendState.TxMined(testHash) + processNSendErrors( + sendState, core.ErrNonceTooLow, testSafeAbortNonceTooLowCount, + ) + require.False(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateSafeAbortIfNonceTooLowPersistsAfterUnmine asserts that we will +// correctly abort if we continue to get ErrNonceTooLow after a tx is unmined +// but not remined. +func TestSendStateSafeAbortIfNonceTooLowPersistsAfterUnmine(t *testing.T) { + sendState := newSendState() + + sendState.TxMined(testHash) + sendState.TxNotMined(testHash) + sendState.ProcessSendError(core.ErrNonceTooLow) + sendState.ProcessSendError(core.ErrNonceTooLow) + require.False(t, sendState.ShouldAbortImmediately()) + sendState.ProcessSendError(core.ErrNonceTooLow) + require.True(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateSafeAbortWhileCallingNotMinedOnUnminedTx asserts that we will +// correctly abort if we continue to call TxNotMined on txns that haven't been +// mined. +func TestSendStateSafeAbortWhileCallingNotMinedOnUnminedTx(t *testing.T) { + sendState := newSendState() + + processNSendErrors( + sendState, core.ErrNonceTooLow, testSafeAbortNonceTooLowCount, + ) + sendState.TxNotMined(testHash) + require.True(t, sendState.ShouldAbortImmediately()) +} + +// TestSendStateIsWaitingForConfirmationAfterTxMined asserts that we are waiting +// for confirmation after a tx is mined. +func TestSendStateIsWaitingForConfirmationAfterTxMined(t *testing.T) { + sendState := newSendState() + + testHash2 := common.HexToHash("0x02") + + sendState.TxMined(testHash) + require.True(t, sendState.IsWaitingForConfirmation()) + sendState.TxMined(testHash2) + require.True(t, sendState.IsWaitingForConfirmation()) +} + +// TestSendStateIsNotWaitingForConfirmationAfterTxUnmined asserts that we are +// not waiting for confirmation after a tx is mined then unmined. +func TestSendStateIsNotWaitingForConfirmationAfterTxUnmined(t *testing.T) { + sendState := newSendState() + + sendState.TxMined(testHash) + sendState.TxNotMined(testHash) + require.False(t, sendState.IsWaitingForConfirmation()) +} diff --git a/l2os/txmgr/txmgr.go b/l2os/txmgr/txmgr.go new file mode 100644 index 000000000000..ca206da1926a --- /dev/null +++ b/l2os/txmgr/txmgr.go @@ -0,0 +1,327 @@ +package txmgr + +import ( + "context" + "math/big" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +// UpdateGasPriceSendTxFunc defines a function signature for publishing a +// desired tx with a specific gas price. Implementations of this signature +// should also return promptly when the context is canceled. +type UpdateGasPriceFunc = func(ctx context.Context) (*types.Transaction, error) + +type SendTransactionFunc = func(ctx context.Context, tx *types.Transaction) error + +// Config houses parameters for altering the behavior of a SimpleTxManager. +type Config struct { + // Name the name of the driver to appear in log lines. + Name string + + // ResubmissionTimeout is the interval at which, if no previously + // published transaction has been mined, the new tx with a bumped gas + // price will be published. Only one publication at MaxGasPrice will be + // attempted. + ResubmissionTimeout time.Duration + + // RequireQueryInterval is the interval at which the tx manager will + // query the backend to check for confirmations after a tx at a + // specific gas price has been published. + ReceiptQueryInterval time.Duration + + // NumConfirmations specifies how many blocks are need to consider a + // transaction confirmed. + NumConfirmations uint64 + + // SafeAbortNonceTooLowCount specifies how many ErrNonceTooLow observations + // are required to give up on a tx at a particular nonce without receiving + // confirmation. + SafeAbortNonceTooLowCount uint64 +} + +// TxManager is an interface that allows callers to reliably publish txs, +// bumping the gas price if needed, and obtain the receipt of the resulting tx. +type TxManager interface { + // Send is used to publish a transaction with incrementally higher gas + // prices until the transaction eventually confirms. This method blocks + // until an invocation of sendTx returns (called with differing gas + // prices). The method may be canceled using the passed context. + // + // NOTE: Send should be called by AT MOST one caller at a time. + Send( + ctx context.Context, + updateGasPrice UpdateGasPriceFunc, + sendTxn SendTransactionFunc, + ) (*types.Receipt, error) +} + +// ReceiptSource is a minimal function signature used to detect the confirmation +// of published txs. +// +// NOTE: This is a subset of bind.DeployBackend. +type ReceiptSource interface { + // BlockNumber returns the most recent block number. + BlockNumber(ctx context.Context) (uint64, error) + + // TransactionReceipt queries the backend for a receipt associated with + // txHash. If lookup does not fail, but the transaction is not found, + // nil should be returned for both values. + TransactionReceipt( + ctx context.Context, txHash common.Hash) (*types.Receipt, error) +} + +// SimpleTxManager is a implementation of TxManager that performs linear fee +// bumping of a tx until it confirms. +type SimpleTxManager struct { + name string + cfg Config + backend ReceiptSource +} + +// NewSimpleTxManager initializes a new SimpleTxManager with the passed Config. +func NewSimpleTxManager( + name string, cfg Config, backend ReceiptSource) *SimpleTxManager { + + if cfg.NumConfirmations == 0 { + panic("txmgr: NumConfirmations cannot be zero") + } + + return &SimpleTxManager{ + name: name, + cfg: cfg, + backend: backend, + } +} + +// Send is used to publish a transaction with incrementally higher gas prices +// until the transaction eventually confirms. This method blocks until an +// invocation of sendTx returns (called with differing gas prices). The method +// may be canceled using the passed context. +// +// NOTE: Send should be called by AT MOST one caller at a time. +func (m *SimpleTxManager) Send( + ctx context.Context, + updateGasPrice UpdateGasPriceFunc, + sendTx SendTransactionFunc, +) (*types.Receipt, error) { + + name := m.name + + // Initialize a wait group to track any spawned goroutines, and ensure + // we properly clean up any dangling resources this method generates. + // We assert that this is the case thoroughly in our unit tests. + var wg sync.WaitGroup + defer wg.Wait() + + // Initialize a subcontext for the goroutines spawned in this process. + // The defer to cancel is done here (in reverse order of Wait) so that + // the goroutines can exit before blocking on the wait group. + ctxc, cancel := context.WithCancel(ctx) + defer cancel() + + sendState := NewSendState(m.cfg.SafeAbortNonceTooLowCount) + + // Create a closure that will block on passed sendTx function in the + // background, returning the first successfully mined receipt back to + // the main event loop via receiptChan. + receiptChan := make(chan *types.Receipt, 1) + sendTxAsync := func() { + defer wg.Done() + + tx, err := updateGasPrice(ctxc) + if err != nil { + if err == context.Canceled || + strings.Contains(err.Error(), "context canceled") { + return + } + log.Error(name+" unable to update txn gas price", "err", err) + return + } + + txHash := tx.Hash() + nonce := tx.Nonce() + gasTipCap := tx.GasTipCap() + gasFeeCap := tx.GasFeeCap() + log.Info(name+" publishing transaction", "txHash", txHash, + "nonce", nonce, "gasTipCap", gasTipCap, "gasFeeCap", gasFeeCap) + + // Sign and publish transaction with current gas price. + err = sendTx(ctxc, tx) + sendState.ProcessSendError(err) + if err != nil { + if err == context.Canceled || + strings.Contains(err.Error(), "context canceled") { + return + } + log.Error(name+" unable to publish transaction", "err", err) + if sendState.ShouldAbortImmediately() { + cancel() + } + // TODO(conner): add retry? + return + } + + log.Info(name+" transaction published successfully", "hash", txHash, + "nonce", nonce, "gasTipCap", gasTipCap, "gasFeeCap", gasFeeCap) + + // Wait for the transaction to be mined, reporting the receipt + // back to the main event loop if found. + receipt, err := waitMined( + ctxc, m.backend, tx, m.cfg.ReceiptQueryInterval, + m.cfg.NumConfirmations, sendState, + ) + if err != nil { + log.Debug(name+" send tx failed", "hash", txHash, + "nonce", nonce, "gasTipCap", gasTipCap, "gasFeeCap", gasFeeCap, + "err", err) + } + if receipt != nil { + // Use non-blocking select to ensure function can exit + // if more than one receipt is discovered. + select { + case receiptChan <- receipt: + log.Trace(name+" send tx succeeded", "hash", txHash, + "nonce", nonce, "gasTipCap", gasTipCap, + "gasFeeCap", gasFeeCap) + default: + } + } + } + + // Submit and wait for the receipt at our first gas price in the + // background, before entering the event loop and waiting out the + // resubmission timeout. + wg.Add(1) + go sendTxAsync() + + for { + select { + + // Whenever a resubmission timeout has elapsed, bump the gas + // price and publish a new transaction. + case <-time.After(m.cfg.ResubmissionTimeout): + // Avoid republishing if we are waiting for confirmation on an + // existing tx. This is primarily an optimization to reduce the + // number of API calls we make, but also reduces the chances of + // getting a false postive reading for ShouldAbortImmediately. + if sendState.IsWaitingForConfirmation() { + continue + } + + // Submit and wait for the bumped traction to confirm. + wg.Add(1) + go sendTxAsync() + + // The passed context has been canceled, i.e. in the event of a + // shutdown. + case <-ctxc.Done(): + return nil, ctxc.Err() + + // The transaction has confirmed. + case receipt := <-receiptChan: + return receipt, nil + } + } +} + +// WaitMined blocks until the backend indicates confirmation of tx and returns +// the tx receipt. Queries are made every queryInterval, regardless of whether +// the backend returns an error. This method can be canceled using the passed +// context. +func WaitMined( + ctx context.Context, + backend ReceiptSource, + tx *types.Transaction, + queryInterval time.Duration, + numConfirmations uint64, +) (*types.Receipt, error) { + return waitMined(ctx, backend, tx, queryInterval, numConfirmations, nil) +} + +// waitMined implements the core functionality of WaitMined, with the option to +// pass in a SendState to record whether or not the transaction is mined. +func waitMined( + ctx context.Context, + backend ReceiptSource, + tx *types.Transaction, + queryInterval time.Duration, + numConfirmations uint64, + sendState *SendState, +) (*types.Receipt, error) { + + queryTicker := time.NewTicker(queryInterval) + defer queryTicker.Stop() + + txHash := tx.Hash() + + for { + receipt, err := backend.TransactionReceipt(ctx, txHash) + switch { + case receipt != nil: + if sendState != nil { + sendState.TxMined(txHash) + } + + txHeight := receipt.BlockNumber.Uint64() + tipHeight, err := backend.BlockNumber(ctx) + if err != nil { + log.Error("Unable to fetch block number", "err", err) + break + } + + log.Trace("Transaction mined, checking confirmations", + "txHash", txHash, "txHeight", txHeight, + "tipHeight", tipHeight, + "numConfirmations", numConfirmations) + + // The transaction is considered confirmed when + // txHeight+numConfirmations-1 <= tipHeight. Note that the -1 is + // needed to account for the fact that confirmations have an + // inherent off-by-one, i.e. when using 1 confirmation the + // transaction should be confirmed when txHeight is equal to + // tipHeight. The equation is rewritten in this form to avoid + // underflows. + if txHeight+numConfirmations <= tipHeight+1 { + log.Info("Transaction confirmed", "txHash", txHash) + return receipt, nil + } + + // Safe to subtract since we know the LHS above is greater. + confsRemaining := (txHeight + numConfirmations) - (tipHeight + 1) + log.Info("Transaction not yet confirmed", "txHash", txHash, + "confsRemaining", confsRemaining) + + case err != nil: + log.Trace("Receipt retrievel failed", "hash", txHash, + "err", err) + + default: + if sendState != nil { + sendState.TxNotMined(txHash) + } + log.Trace("Transaction not yet mined", "hash", txHash) + } + + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-queryTicker.C: + } + } +} + +// CalcGasFeeCap deterministically computes the recommended gas fee cap given +// the base fee and gasTipCap. The resulting gasFeeCap is equal to: +// gasTipCap + 2*baseFee. +func CalcGasFeeCap(baseFee, gasTipCap *big.Int) *big.Int { + return new(big.Int).Add( + gasTipCap, + new(big.Int).Mul(baseFee, big.NewInt(2)), + ) +} diff --git a/l2os/txmgr/txmgr_test.go b/l2os/txmgr/txmgr_test.go new file mode 100644 index 000000000000..3fb0c4928bc6 --- /dev/null +++ b/l2os/txmgr/txmgr_test.go @@ -0,0 +1,543 @@ +package txmgr_test + +import ( + "context" + "errors" + "math/big" + "sync" + "testing" + "time" + + "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +// testHarness houses the necessary resources to test the SimpleTxManager. +type testHarness struct { + cfg txmgr.Config + mgr txmgr.TxManager + backend *mockBackend + gasPricer *gasPricer +} + +// newTestHarnessWithConfig initializes a testHarness with a specific +// configuration. +func newTestHarnessWithConfig(cfg txmgr.Config) *testHarness { + backend := newMockBackend() + mgr := txmgr.NewSimpleTxManager("TEST", cfg, backend) + + return &testHarness{ + cfg: cfg, + mgr: mgr, + backend: backend, + gasPricer: newGasPricer(3), + } +} + +// newTestHarness initializes a testHarness with a defualt configuration that is +// suitable for most tests. +func newTestHarness() *testHarness { + return newTestHarnessWithConfig(configWithNumConfs(1)) +} + +func configWithNumConfs(numConfirmations uint64) txmgr.Config { + return txmgr.Config{ + ResubmissionTimeout: time.Second, + ReceiptQueryInterval: 50 * time.Millisecond, + NumConfirmations: numConfirmations, + SafeAbortNonceTooLowCount: 3, + } +} + +type gasPricer struct { + epoch int64 + mineAtEpoch int64 + baseGasTipFee *big.Int + baseBaseFee *big.Int + mu sync.Mutex +} + +func newGasPricer(mineAtEpoch int64) *gasPricer { + return &gasPricer{ + mineAtEpoch: mineAtEpoch, + baseGasTipFee: big.NewInt(5), + baseBaseFee: big.NewInt(7), + } +} + +func (g *gasPricer) expGasFeeCap() *big.Int { + _, gasFeeCap := g.feesForEpoch(g.mineAtEpoch) + return gasFeeCap +} + +func (g *gasPricer) shouldMine(gasFeeCap *big.Int) bool { + return g.expGasFeeCap().Cmp(gasFeeCap) == 0 +} + +func (g *gasPricer) feesForEpoch(epoch int64) (*big.Int, *big.Int) { + epochBaseFee := new(big.Int).Mul(g.baseBaseFee, big.NewInt(epoch)) + epochGasTipCap := new(big.Int).Mul(g.baseGasTipFee, big.NewInt(epoch)) + epochGasFeeCap := txmgr.CalcGasFeeCap(epochBaseFee, epochGasTipCap) + + return epochGasTipCap, epochGasFeeCap +} + +func (g *gasPricer) sample() (*big.Int, *big.Int) { + g.mu.Lock() + defer g.mu.Unlock() + + g.epoch++ + epochGasTipCap, epochGasFeeCap := g.feesForEpoch(g.epoch) + + return epochGasTipCap, epochGasFeeCap +} + +type minedTxInfo struct { + gasFeeCap *big.Int + blockNumber uint64 +} + +// mockBackend implements txmgr.ReceiptSource that tracks mined transactions +// along with the gas price used. +type mockBackend struct { + mu sync.RWMutex + + // blockHeight tracks the current height of the chain. + blockHeight uint64 + + // minedTxs maps the hash of a mined transaction to its details. + minedTxs map[common.Hash]minedTxInfo +} + +// newMockBackend initializes a new mockBackend. +func newMockBackend() *mockBackend { + return &mockBackend{ + minedTxs: make(map[common.Hash]minedTxInfo), + } +} + +// mine records a (txHash, gasFeeCap) as confirmed. Subsequent calls to +// TransactionReceipt with a matching txHash will result in a non-nil receipt. +// If a nil txHash is supplied this has the effect of mining an empty block. +func (b *mockBackend) mine(txHash *common.Hash, gasFeeCap *big.Int) { + b.mu.Lock() + defer b.mu.Unlock() + + b.blockHeight++ + if txHash != nil { + b.minedTxs[*txHash] = minedTxInfo{ + gasFeeCap: gasFeeCap, + blockNumber: b.blockHeight, + } + } +} + +// BlockNumber returns the most recent block number. +func (b *mockBackend) BlockNumber(ctx context.Context) (uint64, error) { + b.mu.RLock() + defer b.mu.RUnlock() + + return b.blockHeight, nil +} + +// TransactionReceipt queries the mockBackend for a mined txHash. If none is +// found, nil is returned for both return values. Otherwise, it retruns a +// receipt containing the txHash and the gasFeeCap used in the GasUsed to make +// the value accessible from our test framework. +func (b *mockBackend) TransactionReceipt( + ctx context.Context, + txHash common.Hash, +) (*types.Receipt, error) { + + b.mu.RLock() + defer b.mu.RUnlock() + + txInfo, ok := b.minedTxs[txHash] + if !ok { + return nil, nil + } + + // Return the gas fee cap for the transaction in the GasUsed field so that + // we can assert the proper tx confirmed in our tests. + return &types.Receipt{ + TxHash: txHash, + GasUsed: txInfo.gasFeeCap.Uint64(), + BlockNumber: big.NewInt(int64(txInfo.blockNumber)), + }, nil +} + +// TestTxMgrConfirmAtMinGasPrice asserts that Send returns the min gas price tx +// if the tx is mined instantly. +func TestTxMgrConfirmAtMinGasPrice(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + gasPricer := newGasPricer(1) + + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + gasTipCap, gasFeeCap := gasPricer.sample() + return types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }), nil + } + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + if gasPricer.shouldMine(tx.GasFeeCap()) { + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap()) + } + return nil + } + + ctx := context.Background() + receipt, err := h.mgr.Send(ctx, updateGasPrice, sendTx) + require.Nil(t, err) + require.NotNil(t, receipt) + require.Equal(t, gasPricer.expGasFeeCap().Uint64(), receipt.GasUsed) +} + +// TestTxMgrNeverConfirmCancel asserts that a Send can be canceled even if no +// transaction is mined. This is done to ensure the the tx mgr can properly +// abort on shutdown, even if a txn is in the process of being published. +func TestTxMgrNeverConfirmCancel(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + gasTipCap, gasFeeCap := h.gasPricer.sample() + return types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }), nil + } + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + // Don't publish tx to backend, simulating never being mined. + return nil + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + receipt, err := h.mgr.Send(ctx, updateGasPrice, sendTx) + require.Equal(t, err, context.DeadlineExceeded) + require.Nil(t, receipt) +} + +// TestTxMgrConfirmsAtMaxGasPrice asserts that Send properly returns the max gas +// price receipt if none of the lower gas price txs were mined. +func TestTxMgrConfirmsAtHigherGasPrice(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + gasTipCap, gasFeeCap := h.gasPricer.sample() + return types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }), nil + } + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + if h.gasPricer.shouldMine(tx.GasFeeCap()) { + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap()) + } + return nil + } + + ctx := context.Background() + receipt, err := h.mgr.Send(ctx, updateGasPrice, sendTx) + require.Nil(t, err) + require.NotNil(t, receipt) + require.Equal(t, h.gasPricer.expGasFeeCap().Uint64(), receipt.GasUsed) +} + +// errRpcFailure is a sentinel error used in testing to fail publications. +var errRpcFailure = errors.New("rpc failure") + +// TestTxMgrBlocksOnFailingRpcCalls asserts that if all of the publication +// attempts fail due to rpc failures, that the tx manager will return +// txmgr.ErrPublishTimeout. +func TestTxMgrBlocksOnFailingRpcCalls(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + gasTipCap, gasFeeCap := h.gasPricer.sample() + return types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }), nil + } + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + return errRpcFailure + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + receipt, err := h.mgr.Send(ctx, updateGasPrice, sendTx) + require.Equal(t, err, context.DeadlineExceeded) + require.Nil(t, receipt) +} + +// TestTxMgrOnlyOnePublicationSucceeds asserts that the tx manager will return a +// receipt so long as at least one of the publications is able to succeed with a +// simulated rpc failure. +func TestTxMgrOnlyOnePublicationSucceeds(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + gasTipCap, gasFeeCap := h.gasPricer.sample() + return types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }), nil + } + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + // Fail all but the final attempt. + if !h.gasPricer.shouldMine(tx.GasFeeCap()) { + return errRpcFailure + } + + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap()) + return nil + } + + ctx := context.Background() + receipt, err := h.mgr.Send(ctx, updateGasPrice, sendTx) + require.Nil(t, err) + + require.NotNil(t, receipt) + require.Equal(t, h.gasPricer.expGasFeeCap().Uint64(), receipt.GasUsed) +} + +// TestTxMgrConfirmsMinGasPriceAfterBumping delays the mining of the initial tx +// with the minimum gas price, and asserts that it's receipt is returned even +// though if the gas price has been bumped in other goroutines. +func TestTxMgrConfirmsMinGasPriceAfterBumping(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + gasTipCap, gasFeeCap := h.gasPricer.sample() + return types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }), nil + } + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + // Delay mining the tx with the min gas price. + if h.gasPricer.shouldMine(tx.GasFeeCap()) { + time.AfterFunc(5*time.Second, func() { + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap()) + }) + } + return nil + } + + ctx := context.Background() + receipt, err := h.mgr.Send(ctx, updateGasPrice, sendTx) + require.Nil(t, err) + require.NotNil(t, receipt) + require.Equal(t, h.gasPricer.expGasFeeCap().Uint64(), receipt.GasUsed) +} + +// TestTxMgrDoesntAbortNonceTooLowAfterMiningTx +func TestTxMgrDoesntAbortNonceTooLowAfterMiningTx(t *testing.T) { + t.Parallel() + + h := newTestHarnessWithConfig(configWithNumConfs(2)) + + updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { + gasTipCap, gasFeeCap := h.gasPricer.sample() + return types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }), nil + } + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + switch { + + // If the txn's gas fee cap is less than the one we expect to mine, + // accept the txn to the mempool. + case tx.GasFeeCap().Cmp(h.gasPricer.expGasFeeCap()) < 0: + return nil + + // Accept and mine the actual txn we expect to confirm. + case h.gasPricer.shouldMine(tx.GasFeeCap()): + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap()) + time.AfterFunc(5*time.Second, func() { + h.backend.mine(nil, nil) + }) + return nil + + // For gas prices greater than our expected, return ErrNonceTooLow since + // the prior txn confirmed and will invalidate subsequent publications. + default: + return core.ErrNonceTooLow + } + } + + ctx := context.Background() + receipt, err := h.mgr.Send(ctx, updateGasPrice, sendTx) + require.Nil(t, err) + require.NotNil(t, receipt) + require.Equal(t, h.gasPricer.expGasFeeCap().Uint64(), receipt.GasUsed) +} + +// TestWaitMinedReturnsReceiptOnFirstSuccess insta-mines a transaction and +// asserts that WaitMined returns the appropriate receipt. +func TestWaitMinedReturnsReceiptOnFirstSuccess(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + // Create a tx and mine it immediately using the default backend. + tx := types.NewTx(&types.LegacyTx{}) + txHash := tx.Hash() + h.backend.mine(&txHash, new(big.Int)) + + ctx := context.Background() + receipt, err := txmgr.WaitMined(ctx, h.backend, tx, 50*time.Millisecond, 1) + require.Nil(t, err) + require.NotNil(t, receipt) + require.Equal(t, receipt.TxHash, txHash) +} + +// TestWaitMinedCanBeCanceled ensures that WaitMined exits of the passed context +// is canceled before a receipt is found. +func TestWaitMinedCanBeCanceled(t *testing.T) { + t.Parallel() + + h := newTestHarness() + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + // Create an unimined tx. + tx := types.NewTx(&types.LegacyTx{}) + + receipt, err := txmgr.WaitMined(ctx, h.backend, tx, 50*time.Millisecond, 1) + require.Equal(t, err, context.DeadlineExceeded) + require.Nil(t, receipt) +} + +// TestWaitMinedMultipleConfs asserts that WaitMiend will properly wait for more +// than one confirmation. +func TestWaitMinedMultipleConfs(t *testing.T) { + t.Parallel() + + const numConfs = 2 + + h := newTestHarnessWithConfig(configWithNumConfs(numConfs)) + ctxt, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + // Create an unimined tx. + tx := types.NewTx(&types.LegacyTx{}) + txHash := tx.Hash() + h.backend.mine(&txHash, new(big.Int)) + + receipt, err := txmgr.WaitMined(ctxt, h.backend, tx, 50*time.Millisecond, numConfs) + require.Equal(t, err, context.DeadlineExceeded) + require.Nil(t, receipt) + + ctxt, cancel = context.WithTimeout(context.Background(), time.Second) + defer cancel() + + // Mine an empty block, tx should now be confirmed. + h.backend.mine(nil, nil) + receipt, err = txmgr.WaitMined(ctxt, h.backend, tx, 50*time.Millisecond, numConfs) + require.Nil(t, err) + require.NotNil(t, receipt) + require.Equal(t, txHash, receipt.TxHash) +} + +// TestManagerPanicOnZeroConfs ensures that the NewSimpleTxManager will panic +// when attempting to configure with NumConfirmations set to zero. +func TestManagerPanicOnZeroConfs(t *testing.T) { + t.Parallel() + + defer func() { + if r := recover(); r == nil { + t.Fatal("NewSimpleTxManager should panic when using zero conf") + } + }() + + _ = newTestHarnessWithConfig(configWithNumConfs(0)) +} + +// failingBackend implements txmgr.ReceiptSource, returning a failure on the +// first call but a success on the second call. This allows us to test that the +// inner loop of WaitMined properly handles this case. +type failingBackend struct { + returnSuccessBlockNumber bool + returnSuccessReceipt bool +} + +// BlockNumber for the failingBackend returns errRpcFailure on the first +// invocation and a fixed block height on subsequent calls. +func (b *failingBackend) BlockNumber(ctx context.Context) (uint64, error) { + if !b.returnSuccessBlockNumber { + b.returnSuccessBlockNumber = true + return 0, errRpcFailure + } + + return 1, nil +} + +// TransactionReceipt for the failingBackend returns errRpcFailure on the first +// invocation, and a receipt containing the passed TxHash on the second. +func (b *failingBackend) TransactionReceipt( + ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + + if !b.returnSuccessReceipt { + b.returnSuccessReceipt = true + return nil, errRpcFailure + } + + return &types.Receipt{ + TxHash: txHash, + BlockNumber: big.NewInt(1), + }, nil +} + +// TestWaitMinedReturnsReceiptAfterFailure asserts that WaitMined is able to +// recover from failed calls to the backend. It uses the failedBackend to +// simulate an rpc call failure, followed by the successful return of a receipt. +func TestWaitMinedReturnsReceiptAfterFailure(t *testing.T) { + t.Parallel() + + var borkedBackend failingBackend + + // Don't mine the tx with the default backend. The failingBackend will + // return the txHash on the second call. + tx := types.NewTx(&types.LegacyTx{}) + txHash := tx.Hash() + + ctx := context.Background() + receipt, err := txmgr.WaitMined(ctx, &borkedBackend, tx, 50*time.Millisecond, 1) + require.Nil(t, err) + require.NotNil(t, receipt) + require.Equal(t, receipt.TxHash, txHash) +} From 325e5bbdd5da659b9a8305fe808405fefdbdcaeb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 28 Jan 2022 13:43:01 -0800 Subject: [PATCH 249/585] feat: add SRO contract, bindings, and l2output driver --- l2os/Makefile | 20 + l2os/bindings/l2oo/mock_l2_output_oracle.go | 471 ++++++++++++++++++ l2os/drivers/l2output/driver.go | 243 +++++++++ packages/contracts/.solhint.json | 3 +- .../contracts/L1/MockL2OutputOracle.sol | 69 +++ 5 files changed, 805 insertions(+), 1 deletion(-) create mode 100644 l2os/bindings/l2oo/mock_l2_output_oracle.go create mode 100644 l2os/drivers/l2output/driver.go create mode 100644 packages/contracts/contracts/L1/MockL2OutputOracle.sol diff --git a/l2os/Makefile b/l2os/Makefile index 4d9a20e201b9..1fab682f8e7d 100644 --- a/l2os/Makefile +++ b/l2os/Makefile @@ -7,6 +7,8 @@ LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) LDFLAGSSTRING +=-X main.Version=$(VERSION) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" +MOCK_L2_OUTPUT_ORACLE_SOL := ../packages/contracts/contracts/L1/MockL2OutputOracle.sol + l2os: env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/l2os @@ -19,7 +21,25 @@ test: lint: golangci-lint run ./... +bindings: bindings-mock-l2-output-oracle + +bindings-mock-l2-output-oracle: + $(eval temp := $(shell mktemp -d)) + solc \ + --abi $(MOCK_L2_OUTPUT_ORACLE_SOL) \ + --bin $(MOCK_L2_OUTPUT_ORACLE_SOL) \ + -o $(temp) + abigen \ + --abi $(temp)/MockL2OutputOracle.abi \ + --bin $(temp)/MockL2OutputOracle.bin \ + --pkg l2oo \ + --type MockL2OutputOracle \ + --out ./bindings/l2oo/mock_l2_output_oracle.go + + .PHONY: \ + bindings \ + bindings-mock-l2-output-oracle \ clean \ l2os \ test \ diff --git a/l2os/bindings/l2oo/mock_l2_output_oracle.go b/l2os/bindings/l2oo/mock_l2_output_oracle.go new file mode 100644 index 000000000000..36bc186f56c4 --- /dev/null +++ b/l2os/bindings/l2oo/mock_l2_output_oracle.go @@ -0,0 +1,471 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package l2oo + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// MockL2OutputOracleMetaData contains all meta data concerning the MockL2OutputOracle contract. +var MockL2OutputOracleMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionFrequency\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"l2Outputs\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionFrequency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5060405161098f38038061098f833981810160405281019061003291906100e7565b83600081905550826001819055508160026000428152602001908152602001600020819055508060038190555042600481905550426005819055505050505061014e565b600080fd5b6000819050919050565b61008e8161007b565b811461009957600080fd5b50565b6000815190506100ab81610085565b92915050565b6000819050919050565b6100c4816100b1565b81146100cf57600080fd5b50565b6000815190506100e1816100bb565b92915050565b6000806000806080858703121561010157610100610076565b5b600061010f8782880161009c565b94505060206101208782880161009c565b9350506040610131878288016100d2565b92505060606101428782880161009c565b91505092959194509250565b6108328061015d6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806393991af31161006657806393991af314610134578063b210dc2114610152578063b71d13e214610170578063c5095d681461018c578063c90ec2da146101aa57610093565b806302be8bfe1461009857806302e51345146100c85780630c1952d3146100f8578063357e951f14610116575b600080fd5b6100b260048036038101906100ad91906103b9565b6101c8565b6040516100bf91906103ff565b60405180910390f35b6100e260048036038101906100dd91906103b9565b6101e0565b6040516100ef9190610429565b60405180910390f35b610100610256565b60405161010d9190610429565b60405180910390f35b61011e61025c565b60405161012b9190610429565b60405180910390f35b61013c610272565b6040516101499190610429565b60405180910390f35b61015a610278565b6040516101679190610429565b60405180910390f35b61018a60048036038101906101859190610470565b61027e565b005b610194610372565b6040516101a19190610429565b60405180910390f35b6101b2610378565b6040516101bf9190610429565b60405180910390f35b60026020528060005260406000206000915090505481565b6000600554821015610227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021e90610533565b60405180910390fd5b600154600554836102389190610582565b61024291906105e5565b60035461024f9190610616565b9050919050565b60045481565b6000805460045461026d9190610616565b905090565b60015481565b60005481565b8042116102c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b7906106de565b60405180910390fd5b6000801b821415610306576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fd9061074a565b60405180910390fd5b61030e61025c565b811461034f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610346906107dc565b60405180910390fd5b816002600083815260200190815260200160002081905550806004819055505050565b60055481565b60035481565b600080fd5b6000819050919050565b61039681610383565b81146103a157600080fd5b50565b6000813590506103b38161038d565b92915050565b6000602082840312156103cf576103ce61037e565b5b60006103dd848285016103a4565b91505092915050565b6000819050919050565b6103f9816103e6565b82525050565b600060208201905061041460008301846103f0565b92915050565b61042381610383565b82525050565b600060208201905061043e600083018461041a565b92915050565b61044d816103e6565b811461045857600080fd5b50565b60008135905061046a81610444565b92915050565b600080604083850312156104875761048661037e565b5b60006104958582860161045b565b92505060206104a6858286016103a4565b9150509250929050565b600082825260208201905092915050565b7f74696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b600061051d6029836104b0565b9150610528826104c1565b604082019050919050565b6000602082019050818103600083015261054c81610510565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061058d82610383565b915061059883610383565b9250828210156105ab576105aa610553565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006105f082610383565b91506105fb83610383565b92508261060b5761060a6105b6565b5b828204905092915050565b600061062182610383565b915061062c83610383565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561066157610660610553565b5b828201905092915050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b60006106c86021836104b0565b91506106d38261066c565b604082019050919050565b600060208201905081810360008301526106f7816106bb565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610734601d836104b0565b915061073f826106fe565b602082019050919050565b6000602082019050818103600083015261076381610727565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b60006107c6602e836104b0565b91506107d18261076a565b604082019050919050565b600060208201905081810360008301526107f5816107b9565b905091905056fea2646970667358221220af714f0befbe4567f9ca655b787c21715645bed1c576fe2c2b7649d5dfe0af1564736f6c634300080b0033", +} + +// MockL2OutputOracleABI is the input ABI used to generate the binding from. +// Deprecated: Use MockL2OutputOracleMetaData.ABI instead. +var MockL2OutputOracleABI = MockL2OutputOracleMetaData.ABI + +// MockL2OutputOracleBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use MockL2OutputOracleMetaData.Bin instead. +var MockL2OutputOracleBin = MockL2OutputOracleMetaData.Bin + +// DeployMockL2OutputOracle deploys a new Ethereum contract, binding an instance of MockL2OutputOracle to it. +func DeployMockL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionFrequency *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int) (common.Address, *types.Transaction, *MockL2OutputOracle, error) { + parsed, err := MockL2OutputOracleMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MockL2OutputOracleBin), backend, _submissionFrequency, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &MockL2OutputOracle{MockL2OutputOracleCaller: MockL2OutputOracleCaller{contract: contract}, MockL2OutputOracleTransactor: MockL2OutputOracleTransactor{contract: contract}, MockL2OutputOracleFilterer: MockL2OutputOracleFilterer{contract: contract}}, nil +} + +// MockL2OutputOracle is an auto generated Go binding around an Ethereum contract. +type MockL2OutputOracle struct { + MockL2OutputOracleCaller // Read-only binding to the contract + MockL2OutputOracleTransactor // Write-only binding to the contract + MockL2OutputOracleFilterer // Log filterer for contract events +} + +// MockL2OutputOracleCaller is an auto generated read-only Go binding around an Ethereum contract. +type MockL2OutputOracleCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MockL2OutputOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. +type MockL2OutputOracleTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MockL2OutputOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type MockL2OutputOracleFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// MockL2OutputOracleSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type MockL2OutputOracleSession struct { + Contract *MockL2OutputOracle // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// MockL2OutputOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type MockL2OutputOracleCallerSession struct { + Contract *MockL2OutputOracleCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// MockL2OutputOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type MockL2OutputOracleTransactorSession struct { + Contract *MockL2OutputOracleTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// MockL2OutputOracleRaw is an auto generated low-level Go binding around an Ethereum contract. +type MockL2OutputOracleRaw struct { + Contract *MockL2OutputOracle // Generic contract binding to access the raw methods on +} + +// MockL2OutputOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type MockL2OutputOracleCallerRaw struct { + Contract *MockL2OutputOracleCaller // Generic read-only contract binding to access the raw methods on +} + +// MockL2OutputOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type MockL2OutputOracleTransactorRaw struct { + Contract *MockL2OutputOracleTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewMockL2OutputOracle creates a new instance of MockL2OutputOracle, bound to a specific deployed contract. +func NewMockL2OutputOracle(address common.Address, backend bind.ContractBackend) (*MockL2OutputOracle, error) { + contract, err := bindMockL2OutputOracle(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &MockL2OutputOracle{MockL2OutputOracleCaller: MockL2OutputOracleCaller{contract: contract}, MockL2OutputOracleTransactor: MockL2OutputOracleTransactor{contract: contract}, MockL2OutputOracleFilterer: MockL2OutputOracleFilterer{contract: contract}}, nil +} + +// NewMockL2OutputOracleCaller creates a new read-only instance of MockL2OutputOracle, bound to a specific deployed contract. +func NewMockL2OutputOracleCaller(address common.Address, caller bind.ContractCaller) (*MockL2OutputOracleCaller, error) { + contract, err := bindMockL2OutputOracle(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &MockL2OutputOracleCaller{contract: contract}, nil +} + +// NewMockL2OutputOracleTransactor creates a new write-only instance of MockL2OutputOracle, bound to a specific deployed contract. +func NewMockL2OutputOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*MockL2OutputOracleTransactor, error) { + contract, err := bindMockL2OutputOracle(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &MockL2OutputOracleTransactor{contract: contract}, nil +} + +// NewMockL2OutputOracleFilterer creates a new log filterer instance of MockL2OutputOracle, bound to a specific deployed contract. +func NewMockL2OutputOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*MockL2OutputOracleFilterer, error) { + contract, err := bindMockL2OutputOracle(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &MockL2OutputOracleFilterer{contract: contract}, nil +} + +// bindMockL2OutputOracle binds a generic wrapper to an already deployed contract. +func bindMockL2OutputOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(MockL2OutputOracleABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_MockL2OutputOracle *MockL2OutputOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockL2OutputOracle.Contract.MockL2OutputOracleCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_MockL2OutputOracle *MockL2OutputOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockL2OutputOracle.Contract.MockL2OutputOracleTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_MockL2OutputOracle *MockL2OutputOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockL2OutputOracle.Contract.MockL2OutputOracleTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_MockL2OutputOracle *MockL2OutputOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockL2OutputOracle.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_MockL2OutputOracle *MockL2OutputOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockL2OutputOracle.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_MockL2OutputOracle *MockL2OutputOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockL2OutputOracle.Contract.contract.Transact(opts, method, params...) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _timestamp) view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _timestamp *big.Int) (*big.Int, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _timestamp) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _timestamp) view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleSession) ComputeL2BlockNumber(_timestamp *big.Int) (*big.Int, error) { + return _MockL2OutputOracle.Contract.ComputeL2BlockNumber(&_MockL2OutputOracle.CallOpts, _timestamp) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _timestamp) view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) ComputeL2BlockNumber(_timestamp *big.Int) (*big.Int, error) { + return _MockL2OutputOracle.Contract.ComputeL2BlockNumber(&_MockL2OutputOracle.CallOpts, _timestamp) +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "historicalTotalBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleSession) HistoricalTotalBlocks() (*big.Int, error) { + return _MockL2OutputOracle.Contract.HistoricalTotalBlocks(&_MockL2OutputOracle.CallOpts) +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) HistoricalTotalBlocks() (*big.Int, error) { + return _MockL2OutputOracle.Contract.HistoricalTotalBlocks(&_MockL2OutputOracle.CallOpts) +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "l2BlockTime") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleSession) L2BlockTime() (*big.Int, error) { + return _MockL2OutputOracle.Contract.L2BlockTime(&_MockL2OutputOracle.CallOpts) +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) L2BlockTime() (*big.Int, error) { + return _MockL2OutputOracle.Contract.L2BlockTime(&_MockL2OutputOracle.CallOpts) +} + +// L2Outputs is a free data retrieval call binding the contract method 0x02be8bfe. +// +// Solidity: function l2Outputs(uint256 ) view returns(bytes32) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) L2Outputs(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "l2Outputs", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// L2Outputs is a free data retrieval call binding the contract method 0x02be8bfe. +// +// Solidity: function l2Outputs(uint256 ) view returns(bytes32) +func (_MockL2OutputOracle *MockL2OutputOracleSession) L2Outputs(arg0 *big.Int) ([32]byte, error) { + return _MockL2OutputOracle.Contract.L2Outputs(&_MockL2OutputOracle.CallOpts, arg0) +} + +// L2Outputs is a free data retrieval call binding the contract method 0x02be8bfe. +// +// Solidity: function l2Outputs(uint256 ) view returns(bytes32) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) L2Outputs(arg0 *big.Int) ([32]byte, error) { + return _MockL2OutputOracle.Contract.L2Outputs(&_MockL2OutputOracle.CallOpts, arg0) +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) LatestBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "latestBlockTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleSession) LatestBlockTimestamp() (*big.Int, error) { + return _MockL2OutputOracle.Contract.LatestBlockTimestamp(&_MockL2OutputOracle.CallOpts) +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) LatestBlockTimestamp() (*big.Int, error) { + return _MockL2OutputOracle.Contract.LatestBlockTimestamp(&_MockL2OutputOracle.CallOpts) +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) NextTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "nextTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleSession) NextTimestamp() (*big.Int, error) { + return _MockL2OutputOracle.Contract.NextTimestamp(&_MockL2OutputOracle.CallOpts) +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) NextTimestamp() (*big.Int, error) { + return _MockL2OutputOracle.Contract.NextTimestamp(&_MockL2OutputOracle.CallOpts) +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) StartingBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "startingBlockTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleSession) StartingBlockTimestamp() (*big.Int, error) { + return _MockL2OutputOracle.Contract.StartingBlockTimestamp(&_MockL2OutputOracle.CallOpts) +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) StartingBlockTimestamp() (*big.Int, error) { + return _MockL2OutputOracle.Contract.StartingBlockTimestamp(&_MockL2OutputOracle.CallOpts) +} + +// SubmissionFrequency is a free data retrieval call binding the contract method 0xb210dc21. +// +// Solidity: function submissionFrequency() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCaller) SubmissionFrequency(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockL2OutputOracle.contract.Call(opts, &out, "submissionFrequency") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SubmissionFrequency is a free data retrieval call binding the contract method 0xb210dc21. +// +// Solidity: function submissionFrequency() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleSession) SubmissionFrequency() (*big.Int, error) { + return _MockL2OutputOracle.Contract.SubmissionFrequency(&_MockL2OutputOracle.CallOpts) +} + +// SubmissionFrequency is a free data retrieval call binding the contract method 0xb210dc21. +// +// Solidity: function submissionFrequency() view returns(uint256) +func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) SubmissionFrequency() (*big.Int, error) { + return _MockL2OutputOracle.Contract.SubmissionFrequency(&_MockL2OutputOracle.CallOpts) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0xb71d13e2. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _timestamp) returns() +func (_MockL2OutputOracle *MockL2OutputOracleTransactor) AppendL2Output(opts *bind.TransactOpts, _l2Output [32]byte, _timestamp *big.Int) (*types.Transaction, error) { + return _MockL2OutputOracle.contract.Transact(opts, "appendL2Output", _l2Output, _timestamp) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0xb71d13e2. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _timestamp) returns() +func (_MockL2OutputOracle *MockL2OutputOracleSession) AppendL2Output(_l2Output [32]byte, _timestamp *big.Int) (*types.Transaction, error) { + return _MockL2OutputOracle.Contract.AppendL2Output(&_MockL2OutputOracle.TransactOpts, _l2Output, _timestamp) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0xb71d13e2. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _timestamp) returns() +func (_MockL2OutputOracle *MockL2OutputOracleTransactorSession) AppendL2Output(_l2Output [32]byte, _timestamp *big.Int) (*types.Transaction, error) { + return _MockL2OutputOracle.Contract.AppendL2Output(&_MockL2OutputOracle.TransactOpts, _l2Output, _timestamp) +} diff --git a/l2os/drivers/l2output/driver.go b/l2os/drivers/l2output/driver.go new file mode 100644 index 000000000000..3a782fece72e --- /dev/null +++ b/l2os/drivers/l2output/driver.go @@ -0,0 +1,243 @@ +package l2output + +import ( + "context" + "crypto/ecdsa" + "fmt" + "math/big" + "strings" + + "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" +) + +var bigOne = big.NewInt(1) + +type Config struct { + Name string + L1Client *ethclient.Client + L2Client *ethclient.Client + L2OOAddr common.Address + ChainID *big.Int + PrivKey *ecdsa.PrivateKey +} + +type Driver struct { + cfg Config + l2ooContract *l2oo.MockL2OutputOracle + rawL2ooContract *bind.BoundContract + walletAddr common.Address +} + +func NewDriver(cfg Config) (*Driver, error) { + l2ooContract, err := l2oo.NewMockL2OutputOracle( + cfg.L2OOAddr, cfg.L1Client, + ) + if err != nil { + return nil, err + } + + parsed, err := abi.JSON(strings.NewReader( + l2oo.MockL2OutputOracleMetaData.ABI, + )) + if err != nil { + return nil, err + } + + rawL2ooContract := bind.NewBoundContract( + cfg.L2OOAddr, parsed, cfg.L1Client, cfg.L1Client, cfg.L1Client, + ) + + walletAddr := crypto.PubkeyToAddress(cfg.PrivKey.PublicKey) + + return &Driver{ + cfg: cfg, + l2ooContract: l2ooContract, + rawL2ooContract: rawL2ooContract, + walletAddr: walletAddr, + }, nil +} + +// Name is an identifier used to prefix logs for a particular service. +func (d *Driver) Name() string { + return d.cfg.Name +} + +// WalletAddr is the wallet address used to pay for transaction fees. +func (d *Driver) WalletAddr() common.Address { + return d.walletAddr +} + +// GetBlockRange returns the start and end L2 block heights that need to be +// processed. Note that the end value is *exclusive*, therefore if the returned +// values are identical nothing needs to be processed. +func (d *Driver) GetBlockRange( + ctx context.Context) (*big.Int, *big.Int, error) { + + name := d.cfg.Name + + callOpts := &bind.CallOpts{ + Pending: false, + Context: ctx, + } + + // Determine the next uncommitted L2 block number. We do so by transforming + // the timestamp of the latest committed L2 block into its block number and + // adding one. + l2ooTimestamp, err := d.l2ooContract.LatestBlockTimestamp(callOpts) + if err != nil { + log.Error(name+" unable to get latest block timestamp", "err", err) + return nil, nil, err + } + start, err := d.l2ooContract.ComputeL2BlockNumber(callOpts, l2ooTimestamp) + if err != nil { + log.Error(name+" unable to compute latest l2 block number", "err", err) + return nil, nil, err + } + start.Add(start, bigOne) + + // Next we need to obtain the current timestamp and the next timestamp at + // which we will need to submit an L2 output. The former is done by simply + // adding the submission interval to the latest committed block's timestamp; + // the latter inspects the timestamp of the latest block. + nextTimestamp, err := d.l2ooContract.NextTimestamp(callOpts) + if err != nil { + log.Error(name+" unable to get next block timestamp", "err", err) + return nil, nil, err + } + latestHeader, err := d.cfg.L1Client.HeaderByNumber(ctx, nil) + if err != nil { + log.Error(name+" unable to retrieve latest header", "err", err) + return nil, nil, err + } + currentTimestamp := big.NewInt(int64(latestHeader.Time)) + + // If the submission window has yet to elapsed, we must wait before + // submitting our L2 output commitment. Return start as the end value which + // will signal that there is no work to be done. + if currentTimestamp.Cmp(nextTimestamp) < 0 { + log.Info(name+" submission interval has not elapsed", + "currentTimestamp", currentTimestamp, "nextTimestamp", nextTimestamp) + return start, start, nil + } + + log.Info(name+" submission interval has elapsed", + "currentTimestamp", currentTimestamp, "nextTimestamp", nextTimestamp) + + // Otherwise the submission interval has elapsed. Transform the next + // expected timestamp into its L2 block number, and add one since end is + // exclusive. + end, err := d.l2ooContract.ComputeL2BlockNumber(callOpts, nextTimestamp) + if err != nil { + log.Error(name+" unable to compute next l2 block number", "err", err) + return nil, nil, err + } + end.Add(end, bigOne) + + return start, end, nil +} + +// CraftTx transforms the L2 blocks between start and end into a transaction +// using the given nonce. +// +// NOTE: This method SHOULD NOT publish the resulting transaction. +func (d *Driver) CraftTx( + ctx context.Context, + start, end, nonce *big.Int, +) (*types.Transaction, error) { + + name := d.cfg.Name + + log.Info(name+" crafting checkpoint tx", "start", start, "end", end, + "nonce", nonce) + + // Fetch the final block in the range, as this is the only L2 output we need + // to submit. + nextCheckpointBlock := new(big.Int).Sub(end, bigOne) + checkpointBlock, err := d.cfg.L2Client.HeaderByNumber( + ctx, nextCheckpointBlock, + ) + if err != nil { + return nil, err + } + + // Fetch the next expected timestamp that we will submit along with the + // L2Output. + callOpts := &bind.CallOpts{ + Pending: false, + Context: ctx, + } + timestamp, err := d.l2ooContract.NextTimestamp(callOpts) + if err != nil { + return nil, err + } + + // Sanity check that we are submitting against the same expected timestamp. + expCheckpointBlock, err := d.l2ooContract.ComputeL2BlockNumber( + callOpts, timestamp, + ) + if err != nil { + return nil, err + } + if nextCheckpointBlock.Cmp(expCheckpointBlock) != 0 { + return nil, fmt.Errorf("expected next checkpoint block to be %d, "+ + "found %d", nextCheckpointBlock.Uint64(), + expCheckpointBlock.Uint64()) + } + + numElements := new(big.Int).Sub(start, end).Uint64() + log.Info(name+" checkpoint constructed", "start", start, "end", end, + "nonce", nonce, "blocks_committed", numElements) + + opts, err := bind.NewKeyedTransactorWithChainID( + d.cfg.PrivKey, d.cfg.ChainID, + ) + if err != nil { + return nil, err + } + opts.Context = ctx + opts.Nonce = nonce + opts.NoSend = true + + return d.l2ooContract.AppendL2Output( + opts, checkpointBlock.Root, timestamp, + ) +} + +// UpdateGasPrice signs an otherwise identical txn to the one provided but with +// updated gas prices sampled from the existing network conditions. +// +// NOTE: Thie method SHOULD NOT publish the resulting transaction. +func (d *Driver) UpdateGasPrice( + ctx context.Context, + tx *types.Transaction, +) (*types.Transaction, error) { + + opts, err := bind.NewKeyedTransactorWithChainID( + d.cfg.PrivKey, d.cfg.ChainID, + ) + if err != nil { + return nil, err + } + opts.Context = ctx + opts.Nonce = new(big.Int).SetUint64(tx.Nonce()) + opts.NoSend = true + + return d.rawL2ooContract.RawTransact(opts, tx.Data()) +} + +// SendTransaction injects a signed transaction into the pending pool for +// execution. +func (d *Driver) SendTransaction( + ctx context.Context, + tx *types.Transaction, +) error { + + return d.cfg.L1Client.SendTransaction(ctx, tx) +} diff --git a/packages/contracts/.solhint.json b/packages/contracts/.solhint.json index c0db83a45cc3..d33c0727b407 100644 --- a/packages/contracts/.solhint.json +++ b/packages/contracts/.solhint.json @@ -11,6 +11,7 @@ "ordering": "warn", "avoid-low-level-calls": "off", "reason-string": "off", - "avoid-tx-origin": "off" + "avoid-tx-origin": "off", + "func-visibility": ["warn", { "ignoreConstructors": true }] } } diff --git a/packages/contracts/contracts/L1/MockL2OutputOracle.sol b/packages/contracts/contracts/L1/MockL2OutputOracle.sol new file mode 100644 index 000000000000..d95ccc4c91c9 --- /dev/null +++ b/packages/contracts/contracts/L1/MockL2OutputOracle.sol @@ -0,0 +1,69 @@ +//SPDX-License-Identifier: MIT +pragma solidity >=0.8.10; + +/** + * @title MockL2OutputOracle + */ +contract MockL2OutputOracle { + uint256 public submissionFrequency; + uint256 public l2BlockTime; + mapping(uint256 => bytes32) public l2Outputs; + uint256 public historicalTotalBlocks; + uint256 public latestBlockTimestamp; + uint256 public startingBlockTimestamp; + + /** + * Initialize the MockL2OutputOracle contract. + * @param _submissionFrequency The desired interval in seconds at which + * checkpoints must be submitted. + * @param _l2BlockTime The desired L2 inter-block time in seconds. + * @param _genesisL2Output The initial L2 output of the L2 chain. + * @param _historicalTotalBlocks The number of blocks that preceding the + * initialization of the L2 chain. + */ + constructor( + uint256 _submissionFrequency, + uint256 _l2BlockTime, + bytes32 _genesisL2Output, + uint256 _historicalTotalBlocks + ) { + submissionFrequency = _submissionFrequency; + l2BlockTime = _l2BlockTime; + l2Outputs[block.timestamp] = _genesisL2Output; // solhint-disable not-rely-on-time + historicalTotalBlocks = _historicalTotalBlocks; + latestBlockTimestamp = block.timestamp; // solhint-disable not-rely-on-time + startingBlockTimestamp = block.timestamp; // solhint-disable not-rely-on-time + } + + /** + * Accepts an L2 output checkpoint and the timestamp of the corresponding L2 + * block. The timestamp must be equal to the current value returned by + * `nextTimestamp()` in order to be accepted. + * @param _l2Output The L2 output of the checkpoint block. + * @param _timestamp The L2 block timestamp that resulted in _l2Output. + */ + function appendL2Output(bytes32 _l2Output, uint256 _timestamp) external { + require(block.timestamp > _timestamp, "Cannot append L2 output in future"); + require(_l2Output != bytes32(0), "Cannot submit empty L2 output"); + require(_timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp"); + l2Outputs[_timestamp] = _l2Output; + latestBlockTimestamp = _timestamp; + } + + /** + * Computes the timestamp of the next L2 block that needs to be + * checkpointed. + */ + function nextTimestamp() public view returns (uint256) { + return latestBlockTimestamp + submissionFrequency; + } + + /** + * Computes the L2 block number given a target L2 block timestamp. + * @param _timestamp The L2 block timestamp of the target block. + */ + function computeL2BlockNumber(uint256 _timestamp) public view returns (uint256) { + require(_timestamp >= startingBlockTimestamp, "timestamp prior to startingBlockTimestamp"); + return historicalTotalBlocks + (_timestamp - startingBlockTimestamp) / l2BlockTime; + } +} From 6ba76360d35582c032b7a14b44094b64f807c989 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 28 Jan 2022 13:43:48 -0800 Subject: [PATCH 250/585] feat: hook up l2output driver to config options --- l2os/l2_output_submitter.go | 40 +++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/l2os/l2_output_submitter.go b/l2os/l2_output_submitter.go index 3c83f8e2cbbe..cff23be61965 100644 --- a/l2os/l2_output_submitter.go +++ b/l2os/l2_output_submitter.go @@ -8,6 +8,7 @@ import ( "syscall" "time" + "github.com/ethereum-optimism/optimistic-specs/l2os/drivers/l2output" "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" @@ -65,7 +66,8 @@ func Main(version string) func(ctx *cli.Context) error { // L2OutputSubmitter encapsulates a service responsible for submitting // L2Outputs to the L2OutputOracle contract. type L2OutputSubmitter struct { - ctx context.Context + ctx context.Context + l2OutputService *Service } // NewL2OutputSubmitter initializes the L2OutputSubmitter, gathering any resources @@ -89,7 +91,7 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er return nil, err } - _, err = wallet.PrivateKey(accounts.Account{ + l2OutputPrivKey, err := wallet.PrivateKey(accounts.Account{ URL: accounts.URL{ Path: cfg.L2OutputHDPath, }, @@ -98,7 +100,7 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er return nil, err } - _, err = parseAddress(cfg.L2OOAddress) + l2ooAddress, err := parseAddress(cfg.L2OOAddress) if err != nil { return nil, err } @@ -110,33 +112,55 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er return nil, err } - _, err = dialEthClientWithTimeout(ctx, cfg.L2EthRpc) + l2Client, err := dialEthClientWithTimeout(ctx, cfg.L2EthRpc) if err != nil { return nil, err } - _, err = l1Client.ChainID(ctx) + chainID, err := l1Client.ChainID(ctx) if err != nil { return nil, err } - _ = txmgr.Config{ + txManagerConfig := txmgr.Config{ ResubmissionTimeout: cfg.ResubmissionTimeout, ReceiptQueryInterval: time.Second, NumConfirmations: cfg.NumConfirmations, SafeAbortNonceTooLowCount: cfg.SafeAbortNonceTooLowCount, } + l2OutputDriver, err := l2output.NewDriver(l2output.Config{ + Name: "L2Output Submitter", + L1Client: l1Client, + L2Client: l2Client, + L2OOAddr: l2ooAddress, + ChainID: chainID, + PrivKey: l2OutputPrivKey, + }) + if err != nil { + return nil, err + } + + l2OutputService := NewService(ServiceConfig{ + Context: ctx, + Driver: l2OutputDriver, + PollInterval: cfg.PollInterval, + L1Client: l1Client, + TxManagerConfig: txManagerConfig, + }) + return &L2OutputSubmitter{ - ctx: ctx, + ctx: ctx, + l2OutputService: l2OutputService, }, nil } func (l *L2OutputSubmitter) Start() error { - return nil + return l.l2OutputService.Start() } func (l *L2OutputSubmitter) Stop() { + _ = l.l2OutputService.Stop() } // dialEthClientWithTimeout attempts to dial the L1 provider using the provided From b60e07d445ca22fbe3235b3a849ec6cfa2155a15 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 28 Jan 2022 15:20:16 -0800 Subject: [PATCH 251/585] feat: use require for test assertions --- opnode/test/system_test.go | 80 ++++++++++++-------------------------- 1 file changed, 25 insertions(+), 55 deletions(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 2321360b6f7f..71891970b275 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" @@ -78,38 +79,29 @@ func TestSystemE2E(t *testing.T) { // Start L1 l1Node, l1Backend, err := l1Geth(cfg) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer l1Node.Close() + err = l1Node.Start() - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) + err = l1Backend.StartMining(1) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) + l1Client, err := ethclient.Dial(endpoint(cfg.l1.nodeConfig)) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) l1GenesisHash := getGenesisHash(l1Client) // Start L2 l2Node, _, err := l2Geth(cfg) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer l2Node.Close() + err = l2Node.Start() - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) + l2Client, err := ethclient.Dial(endpoint(cfg.l2.nodeConfig)) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) l2GenesisHash := getGenesisHash(l2Client) // Rollup Node @@ -121,14 +113,11 @@ func TestSystemE2E(t *testing.T) { L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, } node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlTrace)) - if err != nil { - t.Fatalf("Failed to create the new node: %v", err) - } + require.Nil(t, err) + err = node.Start(context.Background()) + require.Nil(t, err) defer node.Stop() - if err != nil { - t.Fatal(err) - } // Send Transaction & wait for success contractAddr := common.HexToAddress(cfg.depositContractAddress) @@ -138,45 +127,33 @@ func TestSystemE2E(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() startBalance, err := l2Client.BalanceAt(ctx, fromAddr, nil) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) // Contract depositContract, err := deposit.NewDeposit(contractAddr, l1Client) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) // Signer ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], big.NewInt(int64(cfg.l1.ethConfig.NetworkId))) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) // Setup for L1 Confirmation watchChan := make(chan *deposit.DepositTransactionDeposited) watcher, err := depositContract.WatchTransactionDeposited(&bind.WatchOpts{}, watchChan, []common.Address{fromAddr}, []common.Address{fromAddr}) - if err != nil { - t.Fatalf("with watcher: %v", err) - } + require.Nil(t, err, "with watcher") defer watcher.Unsubscribe() // Setup for L2 Confirmation headChan := make(chan *types.Header, 100) l2HeadSub, err := l2Client.SubscribeNewHead(context.Background(), headChan) - if err != nil { - t.Fatalf("with l2 head sub: %v", err) - } + require.Nil(t, err, "with l2 head sub") defer l2HeadSub.Unsubscribe() // Finally send TX mintAmount := big.NewInt(1_000_000_000_000) tx, err := depositContract.DepositTransaction(opts, fromAddr, mintAmount, big.NewInt(1_000_000), false, nil) - if err != nil { - t.Fatalf("with deposit txt: %v", err) - } + require.Nil(t, err, "with deposit tx") // Wait for tx to be mined on L1 (or timeout) select { @@ -193,9 +170,7 @@ func TestSystemE2E(t *testing.T) { ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second) defer cancel() receipt, err := l1Client.TransactionReceipt(ctx, tx.Hash()) - if err != nil { - t.Fatalf("Could not get tranaction receipt: %v", err) - } + require.Nil(t, err, "Could not get transaction receipt") // Wait (or timeout) for that block to show up on L2 timeoutCh := time.After(3 * time.Second) @@ -217,14 +192,9 @@ loop: ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) defer cancel() endBalance, err := l2Client.BalanceAt(ctx, fromAddr, nil) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) diff := new(big.Int) diff = diff.Sub(endBalance, startBalance) - if diff.Cmp(mintAmount) != 0 { - t.Fatalf("Did not get expected balance change. start: %v, end: %v, mint: %v", startBalance, endBalance, mintAmount) - } - + require.Equal(t, diff, mintAmount, "Did not get expected balance change") } From 96efdc33834e3b8fa188863d8c02cf0db0f49dd8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 31 Jan 2022 11:54:51 -0800 Subject: [PATCH 252/585] feat: integrate L2 Output submitter in E2E test --- opnode/test/setup.go | 5 +- opnode/test/system_test.go | 108 +++++++++++++++++++++++++++++++++++-- 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index c94474eeb071..44d2a3622e86 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -27,7 +27,7 @@ func deriveAddress(w accounts.Wallet, path string) common.Address { // It will panic if the derivation path is not correctly formatted. func deriveAccount(w accounts.Wallet, path string) accounts.Account { derivPath := hdwallet.MustParseDerivationPath(path) - account, err := w.Derive(derivPath, false) + account, err := w.Derive(derivPath, true) if err != nil { panic(err) } @@ -49,6 +49,7 @@ type systemConfig struct { cliqueSigners []string // derivation path depositContractAddress string l1InforPredeployAddress string + wallet *hdwallet.Wallet } func precompileAlloc() core.GenesisAlloc { @@ -155,5 +156,5 @@ func initializeGenesis(cfg *systemConfig) { cfg.l1.ethConfig.Genesis = l1Genesis cfg.l2.ethConfig.Genesis = l2Genesis - + cfg.wallet = wallet } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 71891970b275..a894531b5083 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -7,15 +7,20 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimistic-specs/l2os" + "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" + "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/accounts" "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/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" @@ -40,6 +45,9 @@ func endpoint(cfg *node.Config) string { // All nodes are run in process (but are the full nodes, not mocked or stubbed). func TestSystemE2E(t *testing.T) { log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs + + const l2OutputHDPath = "m/44'/60'/0'/0/3" + // System Config cfg := &systemConfig{ mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness", @@ -69,6 +77,7 @@ func TestSystemE2E(t *testing.T) { "m/44'/60'/0'/0/0": 10000000, "m/44'/60'/0'/0/1": 10000000, "m/44'/60'/0'/0/2": 10000000, + l2OutputHDPath: 10000000, }, cliqueSigners: []string{"m/44'/60'/0'/0/0"}, depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", @@ -119,12 +128,66 @@ func TestSystemE2E(t *testing.T) { require.Nil(t, err) defer node.Stop() + // Deploy StateRootOracle + l2OutputPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: l2OutputHDPath, + }, + }) + require.Nil(t, err) + l2OutputAddr := crypto.PubkeyToAddress(l2OutputPrivKey.PublicKey) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + nonce, err := l1Client.NonceAt(ctx, l2OutputAddr, nil) + require.Nil(t, err) + + opts, err := bind.NewKeyedTransactorWithChainID( + l2OutputPrivKey, cfg.l1.ethConfig.Genesis.Config.ChainID, + ) + require.Nil(t, err) + opts.Nonce = big.NewInt(int64(nonce)) + + submissionFrequency := big.NewInt(10) // 10 seconds + l2BlockTime := big.NewInt(2) // 2 seconds + l2ooAddr, tx, l2OutputOracle, err := l2oo.DeployMockL2OutputOracle( + opts, l1Client, submissionFrequency, l2BlockTime, [32]byte{}, big.NewInt(0), + ) + require.Nil(t, err) + + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + _, err = txmgr.WaitMined(ctx, l1Client, tx, time.Second, 1) + require.Nil(t, err) + + initialSroTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{}) + require.Nil(t, err) + + // L2Output Submitter + l2OutputSubmitter, err := l2os.NewL2OutputSubmitter(l2os.Config{ + L1EthRpc: endpoint(cfg.l1.nodeConfig), + L2EthRpc: endpoint(cfg.l2.nodeConfig), + L2OOAddress: l2ooAddr.String(), + PollInterval: 5 * time.Second, + NumConfirmations: 1, + ResubmissionTimeout: 5 * time.Second, + SafeAbortNonceTooLowCount: 3, + LogLevel: "debug", + Mnemonic: cfg.mnemonic, + L2OutputHDPath: l2OutputHDPath, + }, "") + require.Nil(t, err) + + err = l2OutputSubmitter.Start() + require.Nil(t, err) + defer l2OutputSubmitter.Stop() + // Send Transaction & wait for success contractAddr := common.HexToAddress(cfg.depositContractAddress) fromAddr := common.HexToAddress("0x30ec912c5b1d14aa6d1cb9aa7a6682415c4f7eb0") // start balance - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) defer cancel() startBalance, err := l2Client.BalanceAt(ctx, fromAddr, nil) require.Nil(t, err) @@ -135,7 +198,7 @@ func TestSystemE2E(t *testing.T) { // Signer ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], big.NewInt(int64(cfg.l1.ethConfig.NetworkId))) + opts, err = bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], big.NewInt(int64(cfg.l1.ethConfig.NetworkId))) require.Nil(t, err) // Setup for L1 Confirmation @@ -152,7 +215,7 @@ func TestSystemE2E(t *testing.T) { // Finally send TX mintAmount := big.NewInt(1_000_000_000_000) - tx, err := depositContract.DepositTransaction(opts, fromAddr, mintAmount, big.NewInt(1_000_000), false, nil) + tx, err = depositContract.DepositTransaction(opts, fromAddr, mintAmount, big.NewInt(1_000_000), false, nil) require.Nil(t, err, "with deposit tx") // Wait for tx to be mined on L1 (or timeout) @@ -197,4 +260,43 @@ loop: diff := new(big.Int) diff = diff.Sub(endBalance, startBalance) require.Equal(t, diff, mintAmount, "Did not get expected balance change") + + // Wait for batch submitter to update L2 output oracle. + timeoutCh = time.After(15 * time.Second) + for { + l2ooTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{}) + require.Nil(t, err) + + // Wait for the L2 output oracle to have been changed from the initial + // timestamp set in the contract constructor. + if l2ooTimestamp.Cmp(initialSroTimestamp) > 0 { + // Retrieve the l2 output committed at this updated timestamp. + committedL2Output, err := l2OutputOracle.L2Outputs(&bind.CallOpts{}, l2ooTimestamp) + require.Nil(t, err) + + // Compute the committed L2 output's L2 block number. + l2ooBlockNumber, err := l2OutputOracle.ComputeL2BlockNumber( + &bind.CallOpts{}, l2ooTimestamp, + ) + require.Nil(t, err) + + // Fetch the corresponding L2 block and assert the committed L2 + // output matches the block's state root. + // + // NOTE: This assertion will change once the L2 output format is + // finalized. + ctx, cancel = context.WithTimeout(context.Background(), time.Second) + defer cancel() + l2Block, err := l2Client.BlockByNumber(ctx, l2ooBlockNumber) + require.Nil(t, err) + require.Equal(t, l2Block.Root(), common.Hash(committedL2Output)) + break + } + + select { + case <-timeoutCh: + t.Fatalf("State root oracle not updated") + case <-time.After(time.Second): + } + } } From 36bb0ed579f5649bc26709a6e1e3e60342b58f39 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Thu, 24 Feb 2022 12:53:03 -0800 Subject: [PATCH 253/585] ref impl: Mock new downloader interface Co-authored-by: Joshua Gutow --- opnode/l1/source.go | 15 +++++++++++++++ opnode/rollup/derive/doc.go | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index e0e8276fa24d..5a54a0b0f038 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -6,6 +6,7 @@ import ( "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -88,3 +89,17 @@ func (s Source) Close() { s.client.Close() s.downloader.Close() } + +func (s Source) FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) { + return nil, nil +} +func (s Source) FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) { + _, receipts, err := s.Fetch(ctx, id) + return receipts, err +} +func (s Source) FetchBatches(ctx context.Context, window []eth.BlockID) ([]derive.BatchData, error) { + return nil, nil +} +func (s Source) FetchL2Info(ctx context.Context, id eth.BlockID) (derive.L2Info, error) { + return nil, nil +} diff --git a/opnode/rollup/derive/doc.go b/opnode/rollup/derive/doc.go index e0b46265c0cd..6bd1e39ee9a7 100644 --- a/opnode/rollup/derive/doc.go +++ b/opnode/rollup/derive/doc.go @@ -14,3 +14,7 @@ // // The steps should be keep separate to enable easier testing. package derive + +// Mock interfaces. TODO: Remove +type BatchData interface{} +type L2Info interface{} From 3da2041be4b8a56620486ea7cc08210fa83aaffc Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 25 Feb 2022 13:09:01 -0800 Subject: [PATCH 254/585] ref impl: Expose L2 Head and L1 Range methods --- opnode/rollup/sync/start.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 783d49c7cf44..606a577a1a49 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -51,11 +51,11 @@ var WrongChainErr = errors.New("wrong chain") // - ?? func V3FindSyncStart(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { - l2Head, err := findL2Head(ctx, source, genesis) + l2Head, err := FindL2Head(ctx, source, genesis) if err != nil { return nil, eth.BlockID{}, err } - l1blocks, err := findL1Range(ctx, source, l2Head.l1parent) + l1blocks, err := FindL1Range(ctx, source, l2Head.l1parent) if err != nil { return nil, eth.BlockID{}, fmt.Errorf("failed to fetch l1 range: %w", err) } @@ -66,7 +66,7 @@ func V3FindSyncStart(ctx context.Context, source SyncReferenceV2, genesis *rollu // findL2Head takes the current L2 Head and then finds the topmost L2 head that is valid // In the case that there are no re-orgs, -func findL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) (L2Node, error) { +func FindL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) (L2Node, error) { // Starting point l2Head, err := source.L2NodeByNumber(ctx, nil, genesis) if err != nil { @@ -102,7 +102,7 @@ func findL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Gen } } -func findL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) ([]eth.BlockID, error) { +func FindL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) ([]eth.BlockID, error) { if _, err := source.L1NodeByNumber(ctx, begin.Number); err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) } From de2f6d86594c32bcd91b1e58852818ff0e73f57d Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 25 Feb 2022 13:16:47 -0800 Subject: [PATCH 255/585] ref impl: Small fix to FindL1Range It had an issues around the genesis block where it was thinking that it re-org'd when it in fact did not. --- opnode/rollup/sync/start.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 606a577a1a49..100df95fe925 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -127,7 +127,8 @@ func FindL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) } fmt.Println(prevHash, n.parent.Hash) - if n.parent.Hash != prevHash { + // TODO(Joshua): Look into why this fails around the genesis block + if n.parent.Number != 0 && n.parent.Hash != prevHash { return nil, errors.New("re-organization occurred while attempting to get l1 range") } prevHash = n.self.Hash From 49409f1d740876073b605e578c60168f5d4293d1 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 10:41:42 -0800 Subject: [PATCH 256/585] ref impl: Move L1/L2 nodes to eth package These structs represent blocks in the L1 and L2 chains. --- opnode/eth/id.go | 31 ++++++++++++++++++++++++ opnode/rollup/sync/reference.go | 43 ++++++++++++--------------------- opnode/rollup/sync/start.go | 34 +++++++++++++------------- 3 files changed, 64 insertions(+), 44 deletions(-) diff --git a/opnode/eth/id.go b/opnode/eth/id.go index aa33558efafa..bd795d181496 100644 --- a/opnode/eth/id.go +++ b/opnode/eth/id.go @@ -20,3 +20,34 @@ func (id BlockID) String() string { func (id BlockID) TerminalString() string { return fmt.Sprintf("%s:%d", id.Hash.TerminalString(), id.Number) } + +type L2Node struct { + Self BlockID + L2Parent BlockID + L1Parent BlockID +} + +func (id L2Node) String() string { + return fmt.Sprintf("%s:%d", id.Self.Hash.String(), id.Self.Number) +} + +// TerminalString implements log.TerminalStringer, formatting a string for console +// output during logging. +func (id L2Node) TerminalString() string { + return fmt.Sprintf("%s:%d", id.Self.Hash.TerminalString(), id.Self.Number) +} + +type L1Node struct { + Self BlockID + Parent BlockID +} + +func (id L1Node) String() string { + return fmt.Sprintf("%s:%d", id.Self.Hash.String(), id.Self.Number) +} + +// TerminalString implements log.TerminalStringer, formatting a string for console +// output during logging. +func (id L1Node) TerminalString() string { + return fmt.Sprintf("%s:%d", id.Self.Hash.TerminalString(), id.Self.Number) +} diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index 866e144a6898..3752dcdbd054 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -79,56 +79,45 @@ type SyncReference interface { // SyncReferenceV2 wraps the return types of SyncReference to be easier to work with. type SyncReferenceV2 interface { - L1NodeByNumber(ctx context.Context, l1Num uint64) (L1Node, error) - L1HeadNode(ctx context.Context) (L1Node, error) - L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (L2Node, error) - L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (L2Node, error) + L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) + L1HeadNode(ctx context.Context) (eth.L1Node, error) + L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (eth.L2Node, error) + L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (eth.L2Node, error) } type SyncSourceV2 struct { SyncReference } -func (src SyncSourceV2) L1NodeByNumber(ctx context.Context, l1Num uint64) (L1Node, error) { +func (src SyncSourceV2) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { self, parent, err := src.RefByL1Num(ctx, l1Num) if err != nil { - return L1Node{}, err + return eth.L1Node{}, err } - return L1Node{self: self, parent: parent}, nil + return eth.L1Node{Self: self, Parent: parent}, nil } -func (src SyncSourceV2) L1HeadNode(ctx context.Context) (L1Node, error) { +func (src SyncSourceV2) L1HeadNode(ctx context.Context) (eth.L1Node, error) { self, parent, err := src.L1HeadRef(ctx) if err != nil { - return L1Node{}, err + return eth.L1Node{}, err } - return L1Node{self: self, parent: parent}, nil + return eth.L1Node{Self: self, Parent: parent}, nil } -func (src SyncSourceV2) L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (L2Node, error) { +func (src SyncSourceV2) L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (eth.L2Node, error) { l1Ref, l2ref, l2ParentHash, err := src.RefByL2Num(ctx, l2Num, genesis) if err != nil { - return L2Node{}, err + return eth.L2Node{}, err } - return L2Node{self: l2ref, l1parent: l1Ref, l2parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil + return eth.L2Node{Self: l2ref, L1Parent: l1Ref, L2Parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil } -func (src SyncSourceV2) L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (L2Node, error) { +func (src SyncSourceV2) L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (eth.L2Node, error) { l1Ref, l2ref, l2ParentHash, err := src.RefByL2Hash(ctx, l2Hash, genesis) if err != nil { - return L2Node{}, err + return eth.L2Node{}, err } - return L2Node{self: l2ref, l1parent: l1Ref, l2parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil -} - -type L2Node struct { - self eth.BlockID - l2parent eth.BlockID - l1parent eth.BlockID -} - -type L1Node struct { - self eth.BlockID - parent eth.BlockID + return eth.L2Node{Self: l2ref, L1Parent: l1Ref, L2Parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil } diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 100df95fe925..39b0e1cd7f77 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -55,49 +55,49 @@ func V3FindSyncStart(ctx context.Context, source SyncReferenceV2, genesis *rollu if err != nil { return nil, eth.BlockID{}, err } - l1blocks, err := FindL1Range(ctx, source, l2Head.l1parent) + l1blocks, err := FindL1Range(ctx, source, l2Head.L1Parent) if err != nil { return nil, eth.BlockID{}, fmt.Errorf("failed to fetch l1 range: %w", err) } - return l1blocks, l2Head.self, nil + return l1blocks, l2Head.Self, nil } // findL2Head takes the current L2 Head and then finds the topmost L2 head that is valid // In the case that there are no re-orgs, -func FindL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) (L2Node, error) { +func FindL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) (eth.L2Node, error) { // Starting point l2Head, err := source.L2NodeByNumber(ctx, nil, genesis) if err != nil { - return L2Node{}, fmt.Errorf("failed to fetch L2 head: %w", err) + return eth.L2Node{}, fmt.Errorf("failed to fetch L2 head: %w", err) } // Walk L2 chain from L2 head to first L2 block which has a L1 Parent that is canonical. May walk to L2 genesis for n := l2Head; ; { - l1header, err := source.L1NodeByNumber(ctx, n.l1parent.Number) + l1header, err := source.L1NodeByNumber(ctx, n.L1Parent.Number) if err != nil { // Generic error, bail out. if !errors.Is(err, ethereum.NotFound) { - return L2Node{}, fmt.Errorf("failed to fetch L1 block %v: %w", n.l1parent.Number, err) + return eth.L2Node{}, fmt.Errorf("failed to fetch L1 block %v: %w", n.L1Parent.Number, err) } // L1 block not found, keep walking chain } else { // L1 Block found, check if matches & should keep walking the chain - if l1header.self.Hash == n.l1parent.Hash { + if l1header.Self.Hash == n.L1Parent.Hash { return n, nil } } // Don't walk past genesis. If we were at the L2 genesis, but could not find the L1 genesis // pointed to from it, we are on the wrong L1 chain. - if n.self.Hash == genesis.L2.Hash || n.self.Number == genesis.L2.Number { - return L2Node{}, WrongChainErr + if n.Self.Hash == genesis.L2.Hash || n.Self.Number == genesis.L2.Number { + return eth.L2Node{}, WrongChainErr } // Pull L2 parent for next iteration - n, err = source.L2NodeByHash(ctx, n.l2parent.Hash, genesis) + n, err = source.L2NodeByHash(ctx, n.L2Parent.Hash, genesis) if err != nil { - return L2Node{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.l2parent.Hash, err) + return eth.L2Node{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.L2Parent.Hash, err) } } } @@ -112,9 +112,9 @@ func FindL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) } maxBlocks := uint64(100) - if l1head.self.Number-begin.Number <= maxBlocks { + if l1head.Self.Number-begin.Number <= maxBlocks { fmt.Println("Capping max blocks") - maxBlocks = l1head.self.Number - begin.Number + maxBlocks = l1head.Self.Number - begin.Number fmt.Println(maxBlocks) } @@ -126,13 +126,13 @@ func FindL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) if err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) } - fmt.Println(prevHash, n.parent.Hash) + fmt.Println(prevHash, n.Parent.Hash) // TODO(Joshua): Look into why this fails around the genesis block - if n.parent.Number != 0 && n.parent.Hash != prevHash { + if n.Parent.Number != 0 && n.Parent.Hash != prevHash { return nil, errors.New("re-organization occurred while attempting to get l1 range") } - prevHash = n.self.Hash - res = append(res, n.self) + prevHash = n.Self.Hash + res = append(res, n.Self) } return res, nil From cf38df4d0dc83b2c084b758204ff6b7f5a2f7938 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 11:49:37 -0800 Subject: [PATCH 257/585] ref impl: Return eth.L2Node from derive.BlockReferences This function previously returned the three components of the L2Node, but split apart. This brings them together and makes usage easier. --- opnode/rollup/derive/invert.go | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/opnode/rollup/derive/invert.go b/opnode/rollup/derive/invert.go index df666bd27ede..3f99220759f1 100644 --- a/opnode/rollup/derive/invert.go +++ b/opnode/rollup/derive/invert.go @@ -36,30 +36,24 @@ type Block interface { } // BlockReferences takes a L2 block and determines which L1 block it was derived from, and the L2 self and parent id. -func BlockReferences(refL2Block Block, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { - refL2 = eth.BlockID{Hash: refL2Block.Hash(), Number: refL2Block.NumberU64()} - if refL2.Number <= genesis.L2.Number { - if refL2.Hash != genesis.L2.Hash { - err = fmt.Errorf("unexpected L2 genesis block: %s, expected %s", refL2, genesis.L2) - return +func BlockReferences(l2Block Block, genesis *rollup.Genesis) (eth.L2Node, error) { + self := eth.BlockID{Hash: l2Block.Hash(), Number: l2Block.NumberU64()} + if self.Number <= genesis.L2.Number { + if self.Hash != genesis.L2.Hash { + return eth.L2Node{}, fmt.Errorf("unexpected L2 genesis block: %s, expected %s", self, genesis.L2) } - refL1 = genesis.L1 - refL2 = genesis.L2 - parentL2 = common.Hash{} - return + return eth.L2Node{Self: self, L1Parent: genesis.L1}, nil } - parentL2 = refL2Block.ParentHash() - txs := refL2Block.Transactions() + l2Parent := eth.BlockID{Hash: l2Block.ParentHash(), Number: l2Block.NumberU64() - 1} + + txs := l2Block.Transactions() if len(txs) == 0 || txs[0].Type() != types.DepositTxType { - err = fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", refL2Block.Hash()) - return + return eth.L2Node{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", l2Block.Hash()) } - refL1Nr, _, _, refL1Hash, err := L1InfoDepositTxData(txs[0].Data()) + l1Number, _, _, l1Hash, err := L1InfoDepositTxData(txs[0].Data()) if err != nil { - err = fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) - return + return eth.L2Node{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) } - refL1 = eth.BlockID{Hash: refL1Hash, Number: refL1Nr} - return + return eth.L2Node{Self: self, L2Parent: l2Parent, L1Parent: eth.BlockID{Hash: l1Hash, Number: l1Number}}, nil } From 4bafbb78cb9cd6746a41b8df0a0e9404d1eb1c8e Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 11:53:45 -0800 Subject: [PATCH 258/585] ref impl: Clean up the sync package This unifies the sync reference into a single ChainSource interface and implementation. This also updates the mock implementation to be a fake (i.e. it is seeded with data rather than expecting a certain sequence of calls). The sync start impelemtnation remains mostly unchanged. The rollup/driver package is also slightly updated to use the new ChainSource. --- opnode/rollup/driver/driver.go | 36 ++++---- opnode/rollup/sync/reference.go | 141 +++++++++++++------------------ opnode/rollup/sync/start.go | 22 ++--- opnode/rollup/sync/start_test.go | 93 ++++++++++---------- 4 files changed, 132 insertions(+), 160 deletions(-) diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index f8b96472e862..32d322cdae49 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -27,25 +27,25 @@ type Downloader interface { } type Driver struct { - log log.Logger - rpc DriverAPI - syncRef rollupSync.SyncReference - dl Downloader - l1Heads <-chan eth.HeadSignal - done chan struct{} - genesis rollup.Genesis - state // embedded engine state + log log.Logger + rpc DriverAPI + chainSource rollupSync.ChainSource + dl Downloader + l1Heads <-chan eth.HeadSignal + done chan struct{} + genesis rollup.Genesis + state // embedded engine state } func NewDriver(l2 DriverAPI, l1 l1.Source, log log.Logger, genesis rollup.Genesis) *Driver { return &Driver{ - log: log, - rpc: l2, - syncRef: rollupSync.SyncSource{L1: l1, L2: l2}, - dl: l1, - done: make(chan struct{}), - genesis: genesis, - state: state{Genesis: genesis}, + log: log, + rpc: l2, + chainSource: rollupSync.NewChainSource(l1, l2, &genesis), + dl: l1, + done: make(chan struct{}), + genesis: genesis, + state: state{Genesis: genesis}, } } @@ -125,12 +125,12 @@ func (d *Driver) loop() { // Fulfill the `internalDriver` interface func (e *Driver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { - refL1, refL2, _, err = e.syncRef.RefByL2Num(ctx, nil, &e.genesis) - return + l2Head, err := e.chainSource.L2NodeByNumber(ctx, nil) + return l2Head.L1Parent, l2Head.Self, err } func (e *Driver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - return rollupSync.FindSyncStart(ctx, e.syncRef, &e.genesis) + return rollupSync.FindSyncStart(ctx, e.chainSource, &e.genesis) } func (e *Driver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index 3752dcdbd054..3a2c0a549fe7 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -13,111 +13,86 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -// Sync Source Interface TODOs: -// Relax block by hash??? would have to use by number interface though -// Merge v1 and v2 -// Put node definitions in eth? - -// SyncSource implements SyncReference with a L2 block sources and L1 hash-by-number source -type SyncSource struct { - L1 interface { - HeadBlockLink(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) - BlockLinkByNumber(ctx context.Context, num uint64) (self eth.BlockID, parent eth.BlockID, err error) - } - L2 interface { - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) - } +// L1Client is the subset of methods that ChainSource needs to determine the L1 block graph +type L1Client interface { + HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) } -// RefByL1Num fetches the canonical L1 block hash and the parent for the given L1 block height. -func (src SyncSource) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) { - return src.L1.BlockLinkByNumber(ctx, l1Num) -} - -// L1HeadRef fetches the canonical L1 block hash and the parent for the head of the L1 chain. -func (src SyncSource) L1HeadRef(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) { - return src.L1.HeadBlockLink(ctx) -} - -// RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. -// Use a nil height to fetch the head. -func (src SyncSource) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { - refL2Block, err2 := src.L2.BlockByNumber(ctx, l2Num) // nil for latest block - if err2 != nil { - err = fmt.Errorf("failed to retrieve L2 block: %v", err2) - return - } - return derive.BlockReferences(refL2Block, genesis) -} - -// RefByL2Hash fetches the L1 and L2 block IDs from the engine for the given L2 block hash. -func (src SyncSource) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { - refL2Block, err2 := src.L2.BlockByHash(ctx, l2Hash) - if err2 != nil { - err = fmt.Errorf("failed to retrieve L2 block: %v", err2) - return - } - return derive.BlockReferences(refL2Block, genesis) +// L2Client is the subset of methods that ChainSource needs to determine the L2 block graph +type L2Client interface { + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) } -// SyncReference helps inform the sync algorithm of the L2 sync-state and L1 canonical chain -type SyncReference interface { - // RefByL1Num fetches the canonical L1 block hash and the parent for the given L1 block height. - RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) - - // L1HeadRef fetches the canonical L1 block hash and the parent for the head of the L1 chain. - L1HeadRef(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) - - // RefByL2Num fetches the L1 and L2 block IDs from the engine for the given L2 block height. - // Use a nil height to fetch the head. - RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) - - // RefByL2Hash fetches the L1 and L2 block IDs from the engine for the given L2 block hash. - RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) -} - -// SyncReferenceV2 wraps the return types of SyncReference to be easier to work with. -type SyncReferenceV2 interface { +// ChainSource provides access to the L1 and L2 block graph +type ChainSource interface { L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) L1HeadNode(ctx context.Context) (eth.L1Node, error) - L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (eth.L2Node, error) - L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (eth.L2Node, error) + L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) + L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) } -type SyncSourceV2 struct { - SyncReference +func NewChainSource(l1 L1Client, l2 L2Client, genesis *rollup.Genesis) *chainSourceImpl { + return &chainSourceImpl{l1: l1, l2: l2, genesis: genesis} } -func (src SyncSourceV2) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { - self, parent, err := src.RefByL1Num(ctx, l1Num) +type chainSourceImpl struct { + l1 L1Client + l2 L2Client + genesis *rollup.Genesis +} + +// L1NodeByNumber returns the canonical block and parent ids. +func (src chainSourceImpl) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { + header, err := src.l1.HeaderByNumber(ctx, big.NewInt(int64(l1Num))) if err != nil { - return eth.L1Node{}, err + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L1Node{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", l1Num, err) } - return eth.L1Node{Self: self, Parent: parent}, nil - + parentNum := l1Num + if parentNum > 0 { + parentNum -= 1 + } + return eth.L1Node{ + Self: eth.BlockID{Hash: header.Hash(), Number: l1Num}, + Parent: eth.BlockID{Hash: header.ParentHash, Number: parentNum}, + }, nil } -func (src SyncSourceV2) L1HeadNode(ctx context.Context) (eth.L1Node, error) { - self, parent, err := src.L1HeadRef(ctx) +// L1NodeByNumber returns the canonical head block and parent ids. +func (src chainSourceImpl) L1HeadNode(ctx context.Context) (eth.L1Node, error) { + header, err := src.l1.HeaderByNumber(ctx, nil) if err != nil { - return eth.L1Node{}, err + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L1Node{}, fmt.Errorf("failed to determine block-hash of head block, could not get header: %w", err) + } + l1Num := header.Number.Uint64() + parentNum := l1Num + if parentNum > 0 { + parentNum -= 1 } - return eth.L1Node{Self: self, Parent: parent}, nil + return eth.L1Node{ + Self: eth.BlockID{Hash: header.Hash(), Number: l1Num}, + Parent: eth.BlockID{Hash: header.ParentHash, Number: parentNum}, + }, nil } -func (src SyncSourceV2) L2NodeByNumber(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (eth.L2Node, error) { - l1Ref, l2ref, l2ParentHash, err := src.RefByL2Num(ctx, l2Num, genesis) +// L2NodeByNumber returns the canonical block and parent ids. +func (src chainSourceImpl) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) { + block, err := src.l2.BlockByNumber(ctx, l2Num) if err != nil { - return eth.L2Node{}, err + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L2Node{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) } - return eth.L2Node{Self: l2ref, L1Parent: l1Ref, L2Parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil + return derive.BlockReferences(block, src.genesis) } -func (src SyncSourceV2) L2NodeByHash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (eth.L2Node, error) { - l1Ref, l2ref, l2ParentHash, err := src.RefByL2Hash(ctx, l2Hash, genesis) +// L2NodeByHash returns the block & parent ids based on the supplied hash. The returned node may not be in the canonical chain +func (src chainSourceImpl) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) { + block, err := src.l2.BlockByHash(ctx, l2Hash) if err != nil { - return eth.L2Node{}, err + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L2Node{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) } - return eth.L2Node{Self: l2ref, L1Parent: l1Ref, L2Parent: eth.BlockID{Hash: l2ParentHash, Number: l2ref.Number - 1}}, nil + return derive.BlockReferences(block, src.genesis) } diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 39b0e1cd7f77..6b07d7d29487 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -50,7 +50,7 @@ var WrongChainErr = errors.New("wrong chain") // - Wrapped WrongChainErr if the l1_rollup_genesis block is not reachable from the L2 chain. // - ?? -func V3FindSyncStart(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { +func V3FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { l2Head, err := FindL2Head(ctx, source, genesis) if err != nil { return nil, eth.BlockID{}, err @@ -64,11 +64,12 @@ func V3FindSyncStart(ctx context.Context, source SyncReferenceV2, genesis *rollu } -// findL2Head takes the current L2 Head and then finds the topmost L2 head that is valid -// In the case that there are no re-orgs, -func FindL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Genesis) (eth.L2Node, error) { +// FindL2Head takes the current L2 Head and then finds the topmost L2 head that is valid +// In the case that there are no re-orgs, this is just the L2 head. Otherwise it has to walk back +// until it finds the first L2 block that is based on a canonical L1 block. +func FindL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (eth.L2Node, error) { // Starting point - l2Head, err := source.L2NodeByNumber(ctx, nil, genesis) + l2Head, err := source.L2NodeByNumber(ctx, nil) if err != nil { return eth.L2Node{}, fmt.Errorf("failed to fetch L2 head: %w", err) } @@ -95,18 +96,19 @@ func FindL2Head(ctx context.Context, source SyncReferenceV2, genesis *rollup.Gen } // Pull L2 parent for next iteration - n, err = source.L2NodeByHash(ctx, n.L2Parent.Hash, genesis) + n, err = source.L2NodeByHash(ctx, n.L2Parent.Hash) if err != nil { return eth.L2Node{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.L2Parent.Hash, err) } } } -func FindL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) ([]eth.BlockID, error) { +// FindL1Range returns a range of L1 block beginning just after `begin`. +func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([]eth.BlockID, error) { if _, err := source.L1NodeByNumber(ctx, begin.Number); err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) } - // TODO: Check hash here (even if slightly redudant) + // TODO: Check hash (begin.hash = the same as from L1NodeByNumber above) here (even if slightly redudant) l1head, err := source.L1HeadNode(ctx) if err != nil { return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) @@ -140,8 +142,8 @@ func FindL1Range(ctx context.Context, source SyncReferenceV2, begin eth.BlockID) // FindSyncStart finds nextL1s: the L1 blocks needed next for sync, to derive into a L2 block on top of refL2. // If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. -func FindSyncStart(ctx context.Context, reference SyncReference, genesis *rollup.Genesis) (nextRefL1, refL2 eth.BlockID, err error) { - l1s, refL2, err := V3FindSyncStart(ctx, SyncSourceV2{reference}, genesis) +func FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (nextRefL1, refL2 eth.BlockID, err error) { + l1s, refL2, err := V3FindSyncStart(ctx, source, genesis) if err != nil && len(l1s) > 0 { nextRefL1 = l1s[0] } diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index fbd579e35c4e..ecd23fc66a6b 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -13,42 +13,27 @@ import ( "github.com/stretchr/testify/assert" ) -type l2Block struct { - Self eth.BlockID - FromL1 eth.BlockID +type fakeChainSource struct { + L1 []eth.L1Node + L2 []eth.L2Node } -type mockSyncReference struct { - L2 []l2Block - L1 []eth.BlockID -} - -func (m *mockSyncReference) RefByL1Num(ctx context.Context, l1Num uint64) (self eth.BlockID, parent eth.BlockID, err error) { +func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { if l1Num >= uint64(len(m.L1)) { - err = ethereum.NotFound - return + return eth.L1Node{}, ethereum.NotFound } - self = m.L1[l1Num] - if l1Num > 0 { - parent = m.L1[l1Num-1] - } - return + return m.L1[l1Num], nil } -func (m *mockSyncReference) L1HeadRef(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) { +func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1Node, error) { l := len(m.L1) if l == 0 { - err = ethereum.NotFound - return + return eth.L1Node{}, ethereum.NotFound } - self = m.L1[l-1] - if l-1 > 0 { - parent = m.L1[l-1-1] - } - return + return m.L1[l-1], nil } -func (m *mockSyncReference) RefByL2Num(ctx context.Context, l2Num *big.Int, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { +func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) { if len(m.L2) == 0 { panic("bad test, no l2 chain") } @@ -56,46 +41,56 @@ func (m *mockSyncReference) RefByL2Num(ctx context.Context, l2Num *big.Int, gene if l2Num != nil { i = l2Num.Uint64() } - head := m.L2[i] - refL1 = head.FromL1 - refL2 = head.Self - if i > 0 { - parentL2 = m.L2[i-1].Self.Hash - } - return + return m.L2[i], nil } -func (m *mockSyncReference) RefByL2Hash(ctx context.Context, l2Hash common.Hash, genesis *rollup.Genesis) (refL1 eth.BlockID, refL2 eth.BlockID, parentL2 common.Hash, err error) { +func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) { for i, bl := range m.L2 { if bl.Self.Hash == l2Hash { - return m.RefByL2Num(ctx, big.NewInt(int64(i)), genesis) + return m.L2NodeByNumber(ctx, big.NewInt(int64(i))) } } - err = ethereum.NotFound - return + return eth.L2Node{}, ethereum.NotFound } -var _ SyncReference = (*mockSyncReference)(nil) +var _ ChainSource = (*fakeChainSource)(nil) -func mockID(id rune, num uint64) eth.BlockID { +func fakeID(id rune, num uint64) eth.BlockID { var h common.Hash copy(h[:], string(id)) return eth.BlockID{Hash: h, Number: uint64(num)} } -func chainL1(offset uint64, ids string) (out []eth.BlockID) { +func fakeL1Block(self rune, parent rune, num uint64) eth.L1Node { + var parentID eth.BlockID + if num != 0 { + parentID = fakeID(parent, num-1) + } + return eth.L1Node{Self: fakeID(self, num), Parent: parentID} +} + +func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2Node { + var parentID eth.BlockID + if num != 0 { + parentID = fakeID(parent, num-1) + } + return eth.L2Node{Self: fakeID(self, num), L2Parent: parentID, L1Parent: l1parent} +} + +func chainL1(offset uint64, ids string) (out []eth.L1Node) { + var prevID rune for i, id := range ids { - out = append(out, mockID(id, offset+uint64(i))) + out = append(out, fakeL1Block(id, prevID, offset+uint64(i))) + prevID = id } return } -func chainL2(l1 []eth.BlockID, ids string) (out []l2Block) { +func chainL2(l1 []eth.L1Node, ids string) (out []eth.L2Node) { + var prevID rune for i, id := range ids { - out = append(out, l2Block{ - Self: mockID(id, uint64(i)), - FromL1: l1[i], - }) + out = append(out, fakeL2Block(id, prevID, l1[i].Self, uint64(i))) + prevID = id } return } @@ -126,21 +121,21 @@ func (c *syncStartTestCase) Run(t *testing.T) { engL2 := chainL2(engL1, c.EngineL2) actL1 := chainL1(0, c.ActualL1) - msr := &mockSyncReference{ + msr := &fakeChainSource{ L2: engL2, L1: actL1, } genesis := &rollup.Genesis{ - L1: mockID(c.GenesisL1, c.OffsetL2), - L2: mockID(c.GenesisL2, 0), + L1: fakeID(c.GenesisL1, c.OffsetL2), + L2: fakeID(c.GenesisL2, 0), } fmt.Println(engL1) fmt.Println(actL1) fmt.Println(engL2) - nextRefL1s, refL2, err := V3FindSyncStart(context.Background(), SyncSourceV2{msr}, genesis) + nextRefL1s, refL2, err := V3FindSyncStart(context.Background(), msr, genesis) if c.ExpectedErr != nil { assert.Error(t, err, "Expecting an error in this test case") From 8150947c7d5e53e295bdd480961fb5c0a6a3b9b8 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 13:31:24 -0800 Subject: [PATCH 259/585] ref impl: Remove HeadBlockLink Not used. --- opnode/l1/source.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 5a54a0b0f038..71bf3f978c57 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -39,20 +39,6 @@ func (s Source) BlockLinkByNumber(ctx context.Context, num uint64) (self eth.Blo } -func (s Source) HeadBlockLink(ctx context.Context) (self eth.BlockID, parent eth.BlockID, err error) { - header, err := s.client.HeaderByNumber(ctx, nil) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("failed to determine block-hash of head block, could not get header: %w", err) - } - parentNum := header.Number.Uint64() - if parentNum > 0 { - parentNum -= 1 - } - return eth.BlockID{Hash: header.Hash(), Number: header.Number.Uint64()}, eth.BlockID{Hash: header.ParentHash, Number: parentNum}, nil - -} - func (s Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { return s.client.SubscribeNewHead(ctx, ch) } From af84cf7bcd8a993a4e8ed05f54fdb48e988d5637 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 13:51:26 -0800 Subject: [PATCH 260/585] ref impl: Update sync/start comments Some small code cleanup as well. These are mainly comments from the PR review. --- opnode/rollup/sync/start.go | 83 +++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 6b07d7d29487..023064786882 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -1,21 +1,9 @@ -package sync - -import ( - "context" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum" - - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" -) - -var WrongChainErr = errors.New("wrong chain") - +// The sync package is responsible for reconciling L1 and L2. +// +// // The ethereum chain is a DAG of blocks with the root block being the genesis block. // At any given time, the head (or tip) of the chain can change if an offshoot of the chain -// has a higher difficulty. This is known as a re-organization of the canonical chain. +// has a higher number. This is known as a re-organization of the canonical chain. // Each block points to a parent block and the node is responsible for deciding which block is the head // and thus the mapping from block number to canonical block. // @@ -34,22 +22,39 @@ var WrongChainErr = errors.New("wrong chain") // - L2 reorg // - L2 extension // -// When one of those actions occurs, the L2 chain head may need to be updated and we would like a portion of the L1 chain -// that we should use to derive the L2 chain from. -// These are two different functions, but doing the first requires walking both chains in which case it is easy to also -// return a portion of the chain. -// -// This function returns the highest possible l2block that is valid. This is the (possibly new) L2 chain head. +// When one of these changes occurs, the rollup node needs to determine what the new L2 Head should be. +// In a simple extension case, the L2 head remains the same, but in the case of a re-org on L1, it needs +// to find the first L2 block where the l1parent is in the L1 canonical chain. +// In the case of a re-org, it is also helpful to obtain the L1 blocks after the L1 base to re-start the +// chain derivation process. + +package sync + +import ( + "context" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" +) + +var WrongChainErr = errors.New("wrong chain") +var MaxReorgDepth = 200 +var MaxBlocksInL1Range = uint64(100) + +// V3FindSyncStart finds the L2 head and the chain of L1 blocks after the L1 base block. +// The L2 Head is the highest possible l2block such that it is valid (see above rules). // It also returns a portion of the L1 chain starting just after l2block.l1parent.number. -// - The L1 chain was canonical when the function was called. -// - The L1 chain is continuous -// - The L1 chain is from low to high -// - The length is not defined. +// - The returned L1 blocks were canonical when the function was called. +// - The returned L1 block are contiguous and ordered from low to high. +// - The first block (if len > 0) has height l2block.l1parent.number + 1. +// - The length of the array may be any value, including 0. // If err is not nil, the above return values are not well defined. An error will be returned in the following cases: // - Wrapped ethereum.NotFound if it could not find a block in L1 or L2. This error may be temporary. // - Wrapped WrongChainErr if the l1_rollup_genesis block is not reachable from the L2 chain. -// - ?? - func V3FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { l2Head, err := FindL2Head(ctx, source, genesis) if err != nil { @@ -73,6 +78,7 @@ func FindL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis if err != nil { return eth.L2Node{}, fmt.Errorf("failed to fetch L2 head: %w", err) } + reorgDepth := 0 // Walk L2 chain from L2 head to first L2 block which has a L1 Parent that is canonical. May walk to L2 genesis for n := l2Head; ; { l1header, err := source.L1NodeByNumber(ctx, n.L1Parent.Number) @@ -100,35 +106,42 @@ func FindL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis if err != nil { return eth.L2Node{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.L2Parent.Hash, err) } + reorgDepth++ + if reorgDepth >= MaxReorgDepth { + panic("Too deep re-org") + } } } // FindL1Range returns a range of L1 block beginning just after `begin`. func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([]eth.BlockID, error) { - if _, err := source.L1NodeByNumber(ctx, begin.Number); err != nil { + // Ensure that we start on the expected chain. + if canonicalBegin, err := source.L1NodeByNumber(ctx, begin.Number); err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) + + } else { + if canonicalBegin.Self != begin { + return nil, fmt.Errorf("Re-org at begin block. Expected: %v. Actual: %v", begin, canonicalBegin.Self) + } } - // TODO: Check hash (begin.hash = the same as from L1NodeByNumber above) here (even if slightly redudant) + l1head, err := source.L1HeadNode(ctx) if err != nil { return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) } - maxBlocks := uint64(100) + maxBlocks := MaxBlocksInL1Range + // Cap maxBlocks if there are less than maxBlocks between `begin` and the head of the chain. if l1head.Self.Number-begin.Number <= maxBlocks { - fmt.Println("Capping max blocks") maxBlocks = l1head.Self.Number - begin.Number - fmt.Println(maxBlocks) } prevHash := begin.Hash var res []eth.BlockID for i := begin.Number + 1; i < begin.Number+maxBlocks+1; i++ { - fmt.Println(i, i) n, err := source.L1NodeByNumber(ctx, i) if err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) } - fmt.Println(prevHash, n.Parent.Hash) // TODO(Joshua): Look into why this fails around the genesis block if n.Parent.Number != 0 && n.Parent.Hash != prevHash { return nil, errors.New("re-organization occurred while attempting to get l1 range") From b64300e0cbe6ca5e081f77347bad2074e28c6a8d Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 4 Mar 2022 13:04:07 -0800 Subject: [PATCH 261/585] ref impl: Reduce duplication in L1NodeByNumber/L1HeadNode This creates an internal function that did what both of the functions previously did, but it takes a *big.Int to be able to pass `nil` to request the head block. --- opnode/rollup/sync/reference.go | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index 3a2c0a549fe7..9c6b9ccf7472 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -44,27 +44,21 @@ type chainSourceImpl struct { // L1NodeByNumber returns the canonical block and parent ids. func (src chainSourceImpl) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { - header, err := src.l1.HeaderByNumber(ctx, big.NewInt(int64(l1Num))) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L1Node{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", l1Num, err) - } - parentNum := l1Num - if parentNum > 0 { - parentNum -= 1 - } - return eth.L1Node{ - Self: eth.BlockID{Hash: header.Hash(), Number: l1Num}, - Parent: eth.BlockID{Hash: header.ParentHash, Number: parentNum}, - }, nil + return src.l1NodeByNumber(ctx, new(big.Int).SetUint64(l1Num)) } // L1NodeByNumber returns the canonical head block and parent ids. func (src chainSourceImpl) L1HeadNode(ctx context.Context) (eth.L1Node, error) { - header, err := src.l1.HeaderByNumber(ctx, nil) + return src.l1NodeByNumber(ctx, nil) +} + +// l1NodeByNumber wraps l1.HeaderByNumber to return an eth.L1Node +// This is internal because the exposed L1NodeByNumber takes uint64 instead of big.Ints +func (src chainSourceImpl) l1NodeByNumber(ctx context.Context, number *big.Int) (eth.L1Node, error) { + header, err := src.l1.HeaderByNumber(ctx, number) if err != nil { // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L1Node{}, fmt.Errorf("failed to determine block-hash of head block, could not get header: %w", err) + return eth.L1Node{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", number, err) } l1Num := header.Number.Uint64() parentNum := l1Num From ceba036615ac85aec1414b9f95459a7bb4416450 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 4 Mar 2022 13:17:39 -0800 Subject: [PATCH 262/585] ref impl: PR cleanup --- opnode/rollup/sync/start.go | 5 +++-- opnode/rollup/sync/start_test.go | 5 ----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 023064786882..577e566707ac 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -8,7 +8,7 @@ // and thus the mapping from block number to canonical block. // // The optimism chain has similar properties, but also retains references to the ethereum chain. -// Each optimism block retains a reference to an ethereum (L1) block and to it's parent optimism (L2) block. +// Each optimism block retains a reference to an L1 block and to its parent L2 block. // The L2 chain node must satisfy the following validity rules // 1. l2block.height == l2parent.block.height + 1 // 2. l2block.l1parent.height >= l2block.l2parent.l1parent.height @@ -16,7 +16,8 @@ // 4. l1_rollup_genesis is reachable from l2block.l1parent // // -// During normal operation, both the L1 and L2 canonical chains can change. +// During normal operation, both the L1 and L2 canonical chains can change, due to a reorg +// or an extension (new block). // - L1 reorg // - L1 extension // - L2 reorg diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index ecd23fc66a6b..389d4b568163 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -2,7 +2,6 @@ package sync import ( "context" - "fmt" "math/big" "testing" @@ -131,10 +130,6 @@ func (c *syncStartTestCase) Run(t *testing.T) { L2: fakeID(c.GenesisL2, 0), } - fmt.Println(engL1) - fmt.Println(actL1) - fmt.Println(engL2) - nextRefL1s, refL2, err := V3FindSyncStart(context.Background(), msr, genesis) if c.ExpectedErr != nil { From 0098776077216f432db30467fcbc0c743d6c2862 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 4 Mar 2022 14:22:29 -0800 Subject: [PATCH 263/585] ref impl: Implement FetchL1Info as well This does not need to be mocked out at this time. We have an implementation for it. --- opnode/l1/source.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 71bf3f978c57..a0d6b627cf41 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -77,7 +77,8 @@ func (s Source) Close() { } func (s Source) FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) { - return nil, nil + block, _, err := s.Fetch(ctx, id) + return block, err } func (s Source) FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) { _, receipts, err := s.Fetch(ctx, id) From e2d430cd0ee368a922dddeb3a1315c661277afd9 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 3 Mar 2022 13:48:02 +0100 Subject: [PATCH 264/585] fix dead link --- specs/deposits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index bbcc6f1bd644..ee8da2634b6e 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -92,7 +92,7 @@ software, and complexity in general. As noted above, the deposited transaction type does not include a signature for validation. Rather, authorization is handled by the [L2 chain derivation][g-derivation] process, which when correctly applied will only derive transactions with a `from` address attested to by the logs of the [L1 -deposit feed contract][deposit-feed-contract]. +deposit contract][deposit-contract]. ### Execution From 8c1d509e3882ca49f2415c2b724c8a58a134cec7 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 3 Mar 2022 13:54:45 +0100 Subject: [PATCH 265/585] fix deposit specs to account for contract creation (isCreation & null to field) --- specs/deposits.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index ee8da2634b6e..252c311896d6 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -56,7 +56,8 @@ fields (rlp encoded in the order they appear here): [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 - `address from`: The address of the sender account. -- `address to`: The address of the recipient account. +- `address to`: The address of the recipient account, or the null (zero-length) address if the + deposited transaction is a contract creation. - `uint256 mint`: The ETH value to mint on L2. - `uint256 value`: The ETH value to send to the recipient account. - `bytes data`: The input data. @@ -199,14 +200,14 @@ feed contract][deposit-feed-contract] on L1. 1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in the deposit feed contract). -2. `to` may be either: - 1. any 20-byte address (including the zero-address) - 2. `null` in which case a contract is created. +2. `to` is any 20-byte address (including the zero address) + - In case of a contract creation (cf. `isCreation`), this address is always zero. 3. `mint` is set to the emitted value. 4. `value` is set to the emitted value. 5. `gaslimit` is unchanged from the emitted value. -6. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as - either calldata or initialization code depending on the value of `to`. +6. `isCreation` is set to `true` if the transaction is a contract creation, `false` otherwise. +7. `data` is unchanged from the emitted value. Depending on the value of `isCreation` it is handled + as either calldata or contract initialization code. ### Deposit Contract From 3990854da03575ea269509bf9d482552d6f54aa9 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 7 Mar 2022 14:48:16 -0800 Subject: [PATCH 266/585] ref impl: PR Review comments Fixes the following: - Sync function names / versions (removes prefixes) - Have comment to memoize ChainSource - FindL2Head -> FindSafeL2Head rename - Remove panic on deep reorg --- opnode/rollup/derive/invert.go | 2 +- opnode/rollup/driver/driver.go | 7 ++++++- opnode/rollup/sync/start.go | 27 +++++++++------------------ opnode/rollup/sync/start_test.go | 2 +- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/opnode/rollup/derive/invert.go b/opnode/rollup/derive/invert.go index 3f99220759f1..cb8a531e9ef5 100644 --- a/opnode/rollup/derive/invert.go +++ b/opnode/rollup/derive/invert.go @@ -35,7 +35,7 @@ type Block interface { Transactions() types.Transactions } -// BlockReferences takes a L2 block and determines which L1 block it was derived from, and the L2 self and parent id. +// BlockReferences takes a L2 block and determines which L1 block it was derived from, its L2 parent id, and its own id. func BlockReferences(l2Block Block, genesis *rollup.Genesis) (eth.L2Node, error) { self := eth.BlockID{Hash: l2Block.Hash(), Number: l2Block.NumberU64()} if self.Number <= genesis.L2.Number { diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 32d322cdae49..d854ff6ff5cd 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -130,7 +130,12 @@ func (e *Driver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL } func (e *Driver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - return rollupSync.FindSyncStart(ctx, e.chainSource, &e.genesis) + var l1s []eth.BlockID + l1s, refL2, err = rollupSync.FindSyncStart(ctx, e.chainSource, &e.genesis) + if err != nil && len(l1s) > 0 { + nextRefL1 = l1s[0] + } + return } func (e *Driver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 577e566707ac..b963b4d72f3e 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -43,10 +43,12 @@ import ( ) var WrongChainErr = errors.New("wrong chain") -var MaxReorgDepth = 200 +var TooDeepReorgErr = errors.New("reorg is too deep") +var MaxReorgDepth = 500 var MaxBlocksInL1Range = uint64(100) -// V3FindSyncStart finds the L2 head and the chain of L1 blocks after the L1 base block. +// FindSyncStart finds the L2 head and the chain of L1 blocks after the L1 base block. +// Note: The ChainSource should memoize calls as the L1 and L2 chains will be walked multiple times. // The L2 Head is the highest possible l2block such that it is valid (see above rules). // It also returns a portion of the L1 chain starting just after l2block.l1parent.number. // - The returned L1 blocks were canonical when the function was called. @@ -56,8 +58,8 @@ var MaxBlocksInL1Range = uint64(100) // If err is not nil, the above return values are not well defined. An error will be returned in the following cases: // - Wrapped ethereum.NotFound if it could not find a block in L1 or L2. This error may be temporary. // - Wrapped WrongChainErr if the l1_rollup_genesis block is not reachable from the L2 chain. -func V3FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { - l2Head, err := FindL2Head(ctx, source, genesis) +func FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { + l2Head, err := FindSafeL2Head(ctx, source, genesis) if err != nil { return nil, eth.BlockID{}, err } @@ -70,10 +72,10 @@ func V3FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Ge } -// FindL2Head takes the current L2 Head and then finds the topmost L2 head that is valid +// FindSafeL2Head takes the current L2 Head and then finds the topmost L2 head that is valid // In the case that there are no re-orgs, this is just the L2 head. Otherwise it has to walk back // until it finds the first L2 block that is based on a canonical L1 block. -func FindL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (eth.L2Node, error) { +func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (eth.L2Node, error) { // Starting point l2Head, err := source.L2NodeByNumber(ctx, nil) if err != nil { @@ -109,7 +111,7 @@ func FindL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis } reorgDepth++ if reorgDepth >= MaxReorgDepth { - panic("Too deep re-org") + return eth.L2Node{}, TooDeepReorgErr } } } @@ -119,7 +121,6 @@ func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([] // Ensure that we start on the expected chain. if canonicalBegin, err := source.L1NodeByNumber(ctx, begin.Number); err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) - } else { if canonicalBegin.Self != begin { return nil, fmt.Errorf("Re-org at begin block. Expected: %v. Actual: %v", begin, canonicalBegin.Self) @@ -153,13 +154,3 @@ func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([] return res, nil } - -// FindSyncStart finds nextL1s: the L1 blocks needed next for sync, to derive into a L2 block on top of refL2. -// If the L1 reorgs then this will find the common history to build on top of and then follow the first step of the reorg. -func FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (nextRefL1, refL2 eth.BlockID, err error) { - l1s, refL2, err := V3FindSyncStart(ctx, source, genesis) - if err != nil && len(l1s) > 0 { - nextRefL1 = l1s[0] - } - return -} diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 389d4b568163..42e965f7f660 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -130,7 +130,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { L2: fakeID(c.GenesisL2, 0), } - nextRefL1s, refL2, err := V3FindSyncStart(context.Background(), msr, genesis) + nextRefL1s, refL2, err := FindSyncStart(context.Background(), msr, genesis) if c.ExpectedErr != nil { assert.Error(t, err, "Expecting an error in this test case") From ea08b0435730a083241712332507e5c38e528b86 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 7 Mar 2022 18:05:55 -0800 Subject: [PATCH 267/585] ref impl: Switch to much simpler downloader (#221) This still has concurrency when fetching receipts and does retries, but it removes the cache in front of the L1 client and does not limit the total amount of in flight requests. --- opnode/l1/downloader.go | 311 ++++++----------------------------- opnode/l1/downloader_test.go | 210 ----------------------- opnode/l1/source.go | 7 +- opnode/node/node.go | 3 - 4 files changed, 47 insertions(+), 484 deletions(-) delete mode 100644 opnode/l1/downloader_test.go diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go index 7aabe6093c46..6c2e22d0ce7c 100644 --- a/opnode/l1/downloader.go +++ b/opnode/l1/downloader.go @@ -2,291 +2,72 @@ package l1 import ( "context" - "errors" - "fmt" "sync" - "sync/atomic" "time" - lru "github.com/hashicorp/golang-lru" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -const ( - fetchBlockTimeout = 10 * time.Second - fetchReceiptTimeout = 10 * time.Second - maxReceiptRetry = 5 - - // 500 at 100 KB each would be 50 MB of memory for the L1 block inputs cache - cacheSize = 500 - - // Amount of receipt tasks to buffer before applying back-pressure (blocking new block-requests) - receiptQueueSize = 100 -) - -var ( - DownloadEvictedErr = errors.New("evicted") - DownloadClosedErr = errors.New("closed") ) -type downloadTask struct { - // Incremented when Finish is called, to check whether the task already completed (with or without error). - // May increment >1 when other sub-tasks fail. - // - // First field, aligned atomic changes. - finished uint32 - - // Count already downloaded receipts to track status - // - // Aligned after above field, atomic changes. - downloadedReceipts uint32 - - block *types.Block - // receipts slice is allocated in advance, one slot for each transaction, nil until downloaded - receipts []*types.Receipt - - // stop fetching if this context is dead - ctx context.Context - // to free up resources (e.g. ongoing receipt tasks) if a downloadTask finishes prematurely - cancel context.CancelFunc - - // feed to subscribe the requests to (de-duplicate work) - feed event.Feed -} - -// wrappedErr wraps an error, since event.Feed cannot handle nil errors otherwise (reflection on nil) -type wrappedErr struct { - error -} - -func (bl *downloadTask) Finish(err wrappedErr) { - if atomic.AddUint32(&bl.finished, 1) == 1 { - bl.feed.Send(err) - } -} - -type receiptTask struct { - blockHash common.Hash - txHash common.Hash - txIndex uint64 - // Count the attempts we made to fetch this receipt. Block as a whole fails if we tried too many times. - retry uint64 - // Avoid concurrent Downloader cache access and pruning edge cases with receipts. - // Keep a pointer to the parent task to insert the receipt into. - dest *downloadTask -} - -type Downloader interface { - // Fetch downloads a block and all the corresponding transaction receipts. - // Past and ongoing download jobs are cached in an LRU to de-duplicate work. - // - // If the Downloader is closed, then a DownloadClosedErr is returned. - // - // If the Downloader is stressed with too many new requests, - // a long call may be evicted and return a DownloadEvictedErr. - // - // If the provided ctx is done the download may also finish with the context error. - // - // Internal timeouts are maintained to ensure nothing halts the downloader indefinitely. - Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) - // AddReceiptWorkers can add n parallel workers, or remove if n < 0, or no-op if n == 0. - // It then returns the new number of workers. - AddReceiptWorkers(n int) int - Close() -} +const MaxConcurrentFetchesPerCall = 10 +const MaxReceiptRetry = 3 -type DownloadSource interface { - TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) +type EthClient interface { + BlockByHash(context.Context, common.Hash) (*types.Block, error) + TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) } -// downloader implements Downloader with parallel jobs, -// to work around the limited standard JSON-RPC that can only fetch receipts individually. -// -// The downloader maintains a LRU of past and ongoing requests, to de-duplicate work. -// After the first task of downloading the block completes, the transactions are mapped to receipt download tasks. -// Receipt tasks are queued up, split between parallel workers, and re-scheduled on failure up to 5 times. -// -// Receipt-downloading workers can be added/removed through AddReceiptWorkers at any time. -type downloader struct { - // cache of ongoing/completed block tasks: block hash -> block - cacheEvict *lru.Cache - // Get/Add calls need to be atomic to avoid duplicate jobs being created and added - cacheLock sync.Mutex - - receiptTasks chan *receiptTask - receiptWorkers []ethereum.Subscription - receiptWorkersLock sync.Mutex - - // source to pull data from. Nil when downloader is closed - src DownloadSource +type Downloader struct { + client EthClient + // log log.Logger } -func NewDownloader(dlSource DownloadSource) Downloader { - dl := &downloader{ - receiptTasks: make(chan *receiptTask, receiptQueueSize), - src: dlSource, - } - evict := func(k, v interface{}) { - // stop downloading things if they were evicted (already finished items are unaffected) - v.(*downloadTask).Finish(wrappedErr{DownloadEvictedErr}) - v.(*downloadTask).cancel() - } - dl.cacheEvict, _ = lru.NewWithEvict(cacheSize, evict) - return dl +func NewDownloader(client EthClient) *Downloader { + return &Downloader{client: client} } -func (dl *downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { - // check if we are already working on it - dl.cacheLock.Lock() - if dl.src == nil { - dl.cacheLock.Unlock() - return nil, nil, DownloadClosedErr +func (dl Downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { + block, err := dl.client.BlockByHash(ctx, id.Hash) + if err != nil { + return nil, nil, err } - - var dlTask *downloadTask - if dlTaskIfc, ok := dl.cacheEvict.Get(id.Hash); ok { - dlTask = dlTaskIfc.(*downloadTask) - } else { - ctx, cancel := context.WithCancel(ctx) - dlTask = &downloadTask{ctx: ctx, cancel: cancel} - dl.cacheEvict.Add(id.Hash, dlTask) - - // pull the block in the background + txs := block.Transactions() + receipts := make([]*types.Receipt, len(txs)) + + semaphoreChan := make(chan struct{}, MaxConcurrentFetchesPerCall) + defer close(semaphoreChan) + var retErr error + var errMu sync.Mutex + var wg sync.WaitGroup + for idx, tx := range txs { + wg.Add(1) + i := idx + hash := tx.Hash() go func() { - ctx, cancel := context.WithTimeout(ctx, fetchBlockTimeout) - defer cancel() - bl, err := dl.src.BlockByHash(ctx, id.Hash) - if err != nil { - dlTask.Finish(wrappedErr{fmt.Errorf("failed to download block %s: %v", id.Hash, err)}) - return - } - - txs := bl.Transactions() - dlTask.block = bl - dlTask.receipts = make([]*types.Receipt, len(txs)) - - for i, tx := range txs { - dl.receiptTasks <- &receiptTask{blockHash: id.Hash, txHash: tx.Hash(), txIndex: uint64(i), dest: dlTask} - } - - // no receipts to fetch? Then we are done! - if len(txs) == 0 { - dlTask.Finish(wrappedErr{nil}) + semaphoreChan <- struct{}{} + for j := 0; j < MaxReceiptRetry; j++ { + receipt, err := dl.client.TransactionReceipt(ctx, hash) + if err != nil && j == MaxReceiptRetry-1 { + // dl.log.Error("Got error in final retry of fetch", "err", err) + errMu.Lock() + retErr = err + errMu.Unlock() + } else if err == nil { + receipts[i] = receipt + break + } else { + time.Sleep(20 * time.Millisecond) + } } + wg.Done() + <-semaphoreChan }() } - dl.cacheLock.Unlock() - - ch := make(chan wrappedErr) - sub := dlTask.feed.Subscribe(ch) - select { - case wErr := <-ch: - if wErr.error != nil { - return nil, nil, wErr.error - } - return dlTask.block, dlTask.receipts, nil - case err := <-sub.Err(): - return nil, nil, err - case <-ctx.Done(): - return nil, nil, ctx.Err() - } -} - -func (dl *downloader) processTask(task *receiptTask) { - // scheduled tasks may be stale if other receipts of the block failed too many times - if task.dest.finished > 0 { // no need for locks, a very rare stale download does not hurt - return - } - // stop fetching when the task is cancelled or when the individual receipt times out - ctx, cancel := context.WithTimeout(task.dest.ctx, fetchReceiptTimeout) - defer cancel() - receipt, err := dl.src.TransactionReceipt(ctx, task.txHash) - if err != nil { - // if a single receipt fails out of the whole block, we can retry a few times. - if task.retry >= maxReceiptRetry { - // Failed to get the receipt too many times, block fails! - task.dest.Finish(wrappedErr{fmt.Errorf("failed to download receipt again, and reached max %d retries: %v", maxReceiptRetry, err)}) - return - } else { - task.retry += 1 - select { - case dl.receiptTasks <- task: - // all good, retry scheduled successfully - return - default: - // failed to schedule, too much receipt work, stop block to relieve pressure. - task.dest.Finish(wrappedErr{fmt.Errorf("receipt downloader too busy, not downloading receipt again (%d retries): %v", task.retry, err)}) - return - } - } - } - task.dest.receipts[task.txIndex] = receipt - // We count the receipts we have so far (atomic, avoid parallel counting race condition) - total := atomic.AddUint32(&task.dest.downloadedReceipts, 1) - if total == uint32(len(task.dest.receipts)) { - // block completed without error! - task.dest.Finish(wrappedErr{nil}) - return - } - // task completed, but no Finish call without other receipt tasks finishing first -} - -func (dl *downloader) newReceiptWorker() ethereum.Subscription { - return event.NewSubscription(func(quit <-chan struct{}) error { - for { - select { - case task := <-dl.receiptTasks: - dl.processTask(task) - case <-quit: - return nil - } - } - }) -} - -// AddReceiptWorkers can add or remove (negative value) worker routines to parallelize receipt downloads with. -// It returns the number of active workers. -func (dl *downloader) AddReceiptWorkers(n int) int { - dl.receiptWorkersLock.Lock() - defer dl.receiptWorkersLock.Unlock() - if n < 0 { - for i := 0; i < -n && len(dl.receiptWorkers) > 0; i++ { - last := len(dl.receiptWorkers) - 1 - dl.receiptWorkers[last].Unsubscribe() - dl.receiptWorkers = dl.receiptWorkers[:last] - } - } - for i := 0; i < n; i++ { - dl.receiptWorkers = append(dl.receiptWorkers, dl.newReceiptWorker()) - } - return len(dl.receiptWorkers) -} - -// Close unsubscribes and removes the receipt workers, then drains all remaining tasks -func (dl *downloader) Close() { - // nil the src to stop accepting new download tasks - dl.cacheLock.Lock() - if dl.src == nil { - return // already closed - } - dl.src = nil - dl.cacheLock.Unlock() - - dl.receiptWorkersLock.Lock() - defer dl.receiptWorkersLock.Unlock() - for _, w := range dl.receiptWorkers { - w.Unsubscribe() - } - dl.receiptWorkers = dl.receiptWorkers[:0] - close(dl.receiptTasks) - for task := range dl.receiptTasks { - task.dest.Finish(wrappedErr{DownloadClosedErr}) + wg.Wait() + if retErr != nil { + return nil, nil, retErr } + return block, receipts, nil } diff --git a/opnode/l1/downloader_test.go b/opnode/l1/downloader_test.go deleted file mode 100644 index 7529c695ca62..000000000000 --- a/opnode/l1/downloader_test.go +++ /dev/null @@ -1,210 +0,0 @@ -package l1 - -import ( - "context" - "crypto/ecdsa" - "errors" - "fmt" - "math/big" - "math/rand" - "testing" - - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/trie" - "github.com/stretchr/testify/assert" -) - -type retryReceipt struct { - tries int - receipt *types.Receipt -} -type mockDownloaderSource struct { - block *types.Block - receipts map[common.Hash]*retryReceipt -} - -func (m *mockDownloaderSource) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - if m.block == nil { - return nil, errors.New("no block here") - } - return m.block, nil -} - -func (m *mockDownloaderSource) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - ret, ok := m.receipts[txHash] - if !ok { - return nil, errors.New("no receipt here") - } - ret.tries -= 1 - if ret.tries < 0 { - return ret.receipt, nil - } - return nil, fmt.Errorf("receipt takes %d more tries to download", ret.tries) -} - -func RandomL1Block(txCount int) (*types.Block, []*types.Receipt) { - // insecure but reproducible secret key RNG for test txs - rng := rand.New(rand.NewSource(123)) - key, _ := ecdsa.GenerateKey(crypto.S256(), rng) - signer := types.NewLondonSigner(big.NewInt(1234)) - - var txs []*types.Transaction - for i := 0; i < txCount; i++ { - tx, err := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: uint64(i), - GasPrice: big.NewInt(7), - Gas: 21000, - To: &common.Address{}, // burn, send to zero address - Value: big.NewInt(1337), - Data: nil, - }) - if err != nil { - panic(fmt.Errorf("failed to sign tx %d: %v", i, err)) - } - txs = append(txs, tx) - } - - receipts := make([]*types.Receipt, 0, len(txs)) - for i, tx := range txs { - h := tx.Hash() - receipts = append(receipts, &types.Receipt{ - Type: tx.Type(), - Status: types.ReceiptStatusSuccessful, - // not part of the receipt, but extra optional info, which we use for testing - TxHash: h, - TransactionIndex: uint(i), - }) - } - hasher := trie.NewStackTrie(nil) - - var parent common.Hash - rng.Read(parent[:]) - var state common.Hash - rng.Read(state[:]) - block := types.NewBlock(&types.Header{ - ParentHash: parent, - UncleHash: types.EmptyUncleHash, - Coinbase: common.Address{}, - Root: state, - TxHash: types.DeriveSha(types.Transactions(txs), hasher), - ReceiptHash: types.DeriveSha(types.Receipts(receipts), hasher), - Bloom: types.Bloom{}, - Difficulty: nil, - Number: big.NewInt(123), - }, txs, nil, receipts, trie.NewStackTrie(nil)) - return block, receipts -} - -func TestDownloader_Fetch(t *testing.T) { - checks := func(t *testing.T, bl *types.Block, rs []*types.Receipt, workers int, change func(src *mockDownloaderSource) bool) { - receiptRetries := make(map[common.Hash]*retryReceipt) - for _, r := range rs { - receiptRetries[r.TxHash] = &retryReceipt{tries: 0, receipt: r} - } - src := &mockDownloaderSource{block: bl, receipts: receiptRetries} - expectOK := true - if change != nil { - expectOK = change(src) - } - dl := NewDownloader(src) - dl.AddReceiptWorkers(workers) - block, receipts, err := dl.Fetch(context.Background(), eth.BlockID{Hash: bl.Hash(), Number: bl.NumberU64()}) - if expectOK { - if err != nil { - t.Fatal(err) - } - assert.Equal(t, bl, block, "block retrieved") - assert.Equal(t, rs, receipts, "receipts received") - } else { - if err == nil { - t.Fatal("expected error, but got none") - } - } - dl.Close() - _, _, err = dl.Fetch(context.Background(), eth.BlockID{Hash: common.Hash{0xff}, Number: 42}) - assert.Error(t, err) - assert.ErrorIs(t, err, DownloadClosedErr) - } - - testWithWorkers := func(workers int) { - t.Run(fmt.Sprintf("%d workers", workers), func(t *testing.T) { - - t.Run("empty block", func(t *testing.T) { - bl, rs := RandomL1Block(0) - checks(t, bl, rs, 2, nil) - }) - - t.Run("missing block", func(t *testing.T) { - bl, rs := RandomL1Block(0) - checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { - src.block = nil - return false - }) - }) - - t.Run("single tx block", func(t *testing.T) { - bl, rs := RandomL1Block(1) - checks(t, bl, rs, 2, nil) - }) - - t.Run("single tx single retry block", func(t *testing.T) { - bl, rs := RandomL1Block(1) - checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { - for _, r := range src.receipts { - r.tries = 1 - } - return true - }) - }) - - t.Run("single tx too many retries block", func(t *testing.T) { - bl, rs := RandomL1Block(1) - checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { - for _, r := range src.receipts { - r.tries = 9999 - } - return false - }) - }) - - t.Run("two tx retry block", func(t *testing.T) { - bl, rs := RandomL1Block(2) - checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { - for _, r := range src.receipts { - r.tries = 1 - } - return true - }) - }) - - t.Run("few tx no retry block", func(t *testing.T) { - bl, rs := RandomL1Block(10) - checks(t, bl, rs, 2, nil) - }) - - t.Run("many tx no retry block", func(t *testing.T) { - bl, rs := RandomL1Block(100) - checks(t, bl, rs, 2, nil) - }) - - t.Run("many tx random retries block", func(t *testing.T) { - bl, rs := RandomL1Block(100) - rng := rand.New(rand.NewSource(123)) - checks(t, bl, rs, 2, func(src *mockDownloaderSource) bool { - for _, r := range src.receipts { - r.tries = rng.Intn(4) - } - return true - }) - }) - }) - } - - testWithWorkers(1) - testWithWorkers(2) - testWithWorkers(5) -} diff --git a/opnode/l1/source.go b/opnode/l1/source.go index a0d6b627cf41..4765dc0900f2 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -15,7 +15,7 @@ import ( type Source struct { client *ethclient.Client - downloader Downloader + downloader *Downloader } func NewSource(client *ethclient.Client) Source { @@ -67,13 +67,8 @@ func (s Source) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*typ return s.downloader.Fetch(ctx, id) } -func (s Source) AddReceiptWorkers(n int) int { - return s.downloader.AddReceiptWorkers(n) -} - func (s Source) Close() { s.client.Close() - s.downloader.Close() } func (s Source) FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) { diff --git a/opnode/node/node.go b/opnode/node/node.go index 0ff11ff6a15d..fc52358b11f8 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -117,9 +117,6 @@ func (c *OpNode) Start(ctx context.Context) error { c.log.Info("Fetching rollup starting point") - // We download receipts in parallel - c.l1Source.AddReceiptWorkers(4) - // Feed of eth.HeadSignal var l1HeadsFeed event.Feed From fc2aaa0ed2f3fe00e324a9ff027434bbc1a2fc41 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Thu, 24 Feb 2022 11:10:03 -0800 Subject: [PATCH 268/585] ref impl: Add rollup config This config contains information for sequencing. Co-authored-by: Joshua Gutow --- opnode/node/node.go | 15 ++++++++++- opnode/rollup/driver/driver.go | 12 ++++----- opnode/rollup/driver/state.go | 4 +-- opnode/rollup/driver/state_test.go | 28 ++++++++++++++++---- opnode/rollup/types.go | 42 +++++++++++++++++++++++++++++- 5 files changed, 85 insertions(+), 16 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index fc52358b11f8..7ae227b61b61 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -3,6 +3,7 @@ package node import ( "context" "fmt" + "math/big" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -70,6 +71,18 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { l1Source := l1.NewSource(ethclient.NewClient(l1Node)) genesis := cfg.GetGenesis() var l2Engines []*driver.Driver + // TODO: Merge into node.Config? + config := rollup.Config{ + Genesis: genesis, + BlockTime: 2, + MaxSequencerTimeDiff: 10, + SeqWindowSize: 64, + L1ChainID: big.NewInt(901), + // TODO pick defaults + FeeRecipientAddress: common.Address{0xff, 0x01}, + BatchInboxAddress: common.Address{0xff, 0x02}, + BatchSenderAddress: common.Address{0xff, 0x03}, + } for i, addr := range cfg.L2EngineAddrs { // L2 exec engine: updated by this OpNode (L2 consensus layer node) backend, err := rpc.DialContext(ctx, addr) @@ -86,7 +99,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { EthBackend: ethclient.NewClient(backend), Log: log.New("engine_client", i), } - engine := driver.NewDriver(client, l1Source, log.New("engine", i), genesis) + engine := driver.NewDriver(config, client, l1Source, log.New("engine", i)) l2Engines = append(l2Engines, engine) } diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index d854ff6ff5cd..8909013494e6 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -33,19 +33,17 @@ type Driver struct { dl Downloader l1Heads <-chan eth.HeadSignal done chan struct{} - genesis rollup.Genesis state // embedded engine state } -func NewDriver(l2 DriverAPI, l1 l1.Source, log log.Logger, genesis rollup.Genesis) *Driver { +func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger) *Driver { return &Driver{ log: log, rpc: l2, - chainSource: rollupSync.NewChainSource(l1, l2, &genesis), + chainSource: rollupSync.NewChainSource(l1, l2, &cfg.Genesis), dl: l1, done: make(chan struct{}), - genesis: genesis, - state: state{Genesis: genesis}, + state: state{Config: cfg}, } } @@ -53,7 +51,7 @@ func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error d.l1Heads = l1Heads if !d.requestUpdate(ctx, d.log, d) { d.log.Error("failed to fetch engine head, defaulting to genesis") - d.updateHead(d.Genesis.L1, d.Genesis.L2) + d.updateHead(d.state.Config.Genesis.L1, d.state.Config.Genesis.L2) } go d.loop() return nil @@ -131,7 +129,7 @@ func (e *Driver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL func (e *Driver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { var l1s []eth.BlockID - l1s, refL2, err = rollupSync.FindSyncStart(ctx, e.chainSource, &e.genesis) + l1s, refL2, err = rollupSync.FindSyncStart(ctx, e.chainSource, &e.Config.Genesis) if err != nil && len(l1s) > 0 { nextRefL1 = l1s[0] } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index a400f3049566..7ec574987621 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -37,8 +37,8 @@ type state struct { // The L1 block we are syncing towards, may be ahead of l1Head l1Target eth.BlockID - // Genesis starting point - Genesis rollup.Genesis + // Rollup config + Config rollup.Config } func (e *state) updateHead(l1Head eth.BlockID, l2Head eth.BlockID) { diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 61405851536b..dfd46d7b5f79 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -2,6 +2,7 @@ package driver import ( "context" + "math/big" "strconv" "strings" "testing" @@ -42,8 +43,14 @@ type testState struct { l2Head testID l2Finalized testID l1Target testID - genesisL1 testID - genesisL2 testID + + l1Next []testID + l2NextParent testID + + genesisL1 testID + genesisL2 testID + + seqWindowSize uint64 } func makeState(st testState) *state { @@ -52,9 +59,20 @@ func makeState(st testState) *state { l2Head: st.l2Head.ID(), l2Finalized: st.l2Finalized.ID(), l1Target: st.l1Target.ID(), - Genesis: rollup.Genesis{ - L1: st.genesisL1.ID(), - L2: st.genesisL2.ID(), + // TODO: improve testing config (test different seq window sizes and non-zero L2 genesis time?) + Config: rollup.Config{ + Genesis: rollup.Genesis{ + L1: st.genesisL1.ID(), + L2: st.genesisL2.ID(), + L2Time: 0, + }, + BlockTime: 2, + MaxSequencerTimeDiff: 10, + SeqWindowSize: st.seqWindowSize, + L1ChainID: big.NewInt(100), + FeeRecipientAddress: common.Address{0x0a}, + BatchInboxAddress: common.Address{0x0b}, + BatchSenderAddress: common.Address{0x0c}, }, } } diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go index 6ba0e6caf11d..7cb2d065235e 100644 --- a/opnode/rollup/types.go +++ b/opnode/rollup/types.go @@ -1,8 +1,48 @@ package rollup -import "github.com/ethereum-optimism/optimistic-specs/opnode/eth" +import ( + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) type Genesis struct { + // The L1 block that the rollup starts *after* (no derived transactions) L1 eth.BlockID + // The L2 block the rollup starts from (no transactions, pre-configured state) L2 eth.BlockID + // Timestamp of L2 block + L2Time uint64 +} + +type Config struct { + // Genesis anchor point of the rollup + Genesis Genesis + // Seconds per L2 block + BlockTime uint64 + // Sequencer batches may not be more than MaxSequencerTimeDiff seconds after + // the L1 timestamp of the sequencing window end. + // + // Note: When L1 has many 1 second consecutive blocks, and L2 grows at fixed 2 seconds, + // the L2 time may still grow beyond this difference. + MaxSequencerTimeDiff uint64 + // Number of epochs (L1 blocks) per sequencing window + SeqWindowSize uint64 + // Required to verify L1 signatures + L1ChainID *big.Int + + // L2 address receiving all L2 transaction fees + FeeRecipientAddress common.Address + // L1 address that batches are sent to + BatchInboxAddress common.Address + // Acceptable batch-sender address + BatchSenderAddress common.Address } + +func (c *Config) L1Signer() types.Signer { + return types.NewLondonSigner(c.L1ChainID) +} + +type Epoch uint64 From 512a0bee2e4bd6b995787fedcbffac1a76079bb2 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Thu, 24 Feb 2022 12:45:49 -0800 Subject: [PATCH 269/585] ref impl: Sequence Ready Payload attributes function This derives the deposits and batches from a chain window. The function is not yet used as it needs more changes to the rest of the rollup node. Co-authored-by: Joshua Gutow --- opnode/rollup/derive/invert_test.go | 13 +- opnode/rollup/derive/payload_attributes.go | 163 ++++++++++++++++++++- 2 files changed, 164 insertions(+), 12 deletions(-) diff --git a/opnode/rollup/derive/invert_test.go b/opnode/rollup/derive/invert_test.go index bb713a4aa9b7..c9a0c7c8b90f 100644 --- a/opnode/rollup/derive/invert_test.go +++ b/opnode/rollup/derive/invert_test.go @@ -10,10 +10,11 @@ import ( ) type l1MockInfo struct { - num uint64 - time uint64 - hash common.Hash - baseFee *big.Int + num uint64 + time uint64 + hash common.Hash + baseFee *big.Int + mixDigest [32]byte } func (l *l1MockInfo) NumberU64() uint64 { @@ -32,6 +33,10 @@ func (l *l1MockInfo) BaseFee() *big.Int { return l.baseFee } +func (l *l1MockInfo) MixDigest() common.Hash { + return l.mixDigest +} + func randomHash(rng *rand.Rand) (out common.Hash) { rng.Read(out[:]) return diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index c7dc7690e23e..495e9f8017bd 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -2,9 +2,12 @@ package derive import ( "encoding/binary" + "errors" "fmt" "math/big" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -115,6 +118,8 @@ type L1Info interface { Time() uint64 Hash() common.Hash BaseFee() *big.Int + // MixDigest field, reused for randomness after The Merge (Bellatrix hardfork) + MixDigest() common.Hash } // L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block @@ -176,19 +181,128 @@ func UserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, return out, nil } -type BlockInput interface { - ReceiptHash - L1Info - MixDigest() common.Hash +func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) (out []BatchData) { + l1Signer := config.L1Signer() + for _, tx := range txs { + if to := tx.To(); to != nil && *to == config.BatchInboxAddress { + seqDataSubmitter, err := l1Signer.Sender(tx) + if err != nil { + continue // bad signature, ignore + } + // some random L1 user might have sent a transaction to our batch inbox, ignore them + if seqDataSubmitter != config.BatchSenderAddress { + continue // not an authorized batch submitter, ignore + } + out = append(out, ParseBatches(tx.Data())...) + } + } + return } -// PayloadAttributes derives the pre-execution payload from the L1 block info and deposit receipts. +func FilterBatches(config *rollup.Config, epoch rollup.Epoch, minL2Time uint64, maxL2Time uint64, batches []BatchData) (out []BatchData) { + uniqueTime := make(map[uint64]struct{}) + for _, batch := range batches { + if batch.Epoch != epoch { + // Batch was tagged for past or future epoch, + // i.e. it was included too late or depends on the given L1 block to be processed first. + continue + } + if (batch.Timestamp-config.Genesis.L2Time)%config.BlockTime != 0 { + continue // bad timestamp, not a multiple of the block time + } + if batch.Timestamp < minL2Time { + continue // old batch + } + // limit timestamp upper bound to avoid huge amount of empty blocks + if batch.Timestamp >= maxL2Time { + continue // too far in future + } + // Check if we have already seen a batch for this L2 block + if _, ok := uniqueTime[batch.Timestamp]; ok { + // block already exists, batch is duplicate (first batch persists, others are ignored) + continue + } + uniqueTime[batch.Timestamp] = struct{}{} + out = append(out, batch) + } + return +} + +type L2Info interface { + Time() uint64 +} + +// PayloadAttributes derives a sequence of pre-execution payload attributes from: +// - The L1 information the L1-info deposit is derived from +// - The L1 receipts the user deposits are derived from +// - The data batches the L2 sequencer work is derived from +// - The L2 information of the block the new derived blocks build on +// // This is a pure function. -func PayloadAttributes(block BlockInput, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { - if !CheckReceipts(block, receipts) { - return nil, fmt.Errorf("receipts are not consistent with the block's receipts root: %s", block.ReceiptHash()) +func PayloadAttributesV2(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []BatchData, l2Info L2Info) ([]*l2.PayloadAttributes, error) { + // check if we have the full sequencing window + if len(seqWindow) == 0 { + return nil, errors.New("cannot derive payload attributes from empty sequencing window") + } + + // Retrieve the deposits of this epoch (all deposits from the first block) + deposits, err := DeriveDeposits(l1Info, receipts) + if err != nil { + return nil, fmt.Errorf("failed to derive deposits: %v", err) + } + + // copy L1 randomness (mix-digest becomes randao field post-merge) + // TODO: we don't have a randomness oracle on L2, what should sequencing randomness look like. + // Repeating the latest randomness of L1 might not be ideal. + randomnessSeed := l2.Bytes32(l1Info.MixDigest()) + + // Collect all L2 batches, the bathes may be out-of-order, or possibly missing. + l2Blocks := make(map[uint64]*l2.PayloadAttributes) + highestSeenTimestamp := l1Info.Time() + for _, batch := range seqWindow { + + // Track the last batch we've seen (gaps will be filled with empty L2 blocks) + if batch.Timestamp > highestSeenTimestamp { + highestSeenTimestamp = batch.Timestamp + } + + l2Blocks[batch.Timestamp] = &l2.PayloadAttributes{ + Timestamp: l2.Uint64Quantity(batch.Timestamp), + Random: randomnessSeed, + SuggestedFeeRecipient: config.FeeRecipientAddress, + Transactions: batch.Transactions, + } } + // fill the gaps and always ensure at least one L2 block + var out []*l2.PayloadAttributes + for t := l1Info.Time() + config.BlockTime; t <= highestSeenTimestamp; t += config.BlockTime { + if bl, ok := l2Blocks[t]; ok { + out = append(out, bl) + } else { + // skipped/missing L2 block, create an empty block instead + out = append(out, &l2.PayloadAttributes{ + Timestamp: l2.Uint64Quantity(t), + Random: randomnessSeed, + SuggestedFeeRecipient: config.FeeRecipientAddress, + Transactions: nil, + }) + } + } + + // Force deposits into the first block + out[0].Transactions = append(append(make([]l2.Data, 0), deposits...), out[0].Transactions...) + + return out, nil +} + +// PayloadAttributes derives the pre-execution payload from the L1 block info and deposit receipts. +// This is a pure function. +func PayloadAttributes(block L1Info, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { + // if !CheckReceipts(block, receipts) { + // return nil, fmt.Errorf("receipts are not consistent with the block's receipts root: %s", block.ReceiptHash()) + // } + l1Tx := types.NewTx(L1InfoDeposit(block)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { @@ -218,3 +332,36 @@ func PayloadAttributes(block BlockInput, receipts []*types.Receipt) (*l2.Payload Transactions: encodedTxs, }, nil } + +func DeriveDeposits(l1Info L1Info, receipts []*types.Receipt) ([]l2.Data, error) { + l1Tx := types.NewTx(L1InfoDeposit(l1Info)) + opaqueL1Tx, err := l1Tx.MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to encode L1 info tx") + } + userDeposits, err := UserDeposits(l1Info.NumberU64(), receipts) + if err != nil { + return nil, fmt.Errorf("failed to derive user deposits: %v", err) + } + encodedTxs := make([]l2.Data, 0, len(userDeposits)+1) + encodedTxs = append(encodedTxs, opaqueL1Tx) + for i, tx := range userDeposits { + opaqueTx, err := types.NewTx(tx).MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to encode user tx %d", i) + } + encodedTxs = append(encodedTxs, opaqueTx) + } + return encodedTxs, nil +} + +type BatchData struct { + Epoch rollup.Epoch // aka l1 num + Timestamp uint64 + // no feeRecipient address input, all fees go to a L2 contract + Transactions []l2.Data +} + +func ParseBatches(data l2.Data) []BatchData { + return nil // TODO +} From f54d19da3655726d2f1376b4c08a01e9af172331 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Thu, 24 Feb 2022 13:23:08 -0800 Subject: [PATCH 270/585] ref impl: Use window sequencing in the driver The driver now pulls from deposits and batches when constructing L2 from L1. Due to configuration and the driver, deposit only sequencing is still broken. Co-authored-by: Joshua Gutow --- opnode/rollup/derive/doc.go | 4 - opnode/rollup/derive/payload_attributes.go | 39 +--------- opnode/rollup/driver/driver.go | 18 +---- opnode/rollup/driver/state.go | 81 ++++++++++++++------- opnode/rollup/driver/state_test.go | 41 +++++++---- opnode/rollup/driver/step.go | 85 ++++++++++++++++++---- 6 files changed, 155 insertions(+), 113 deletions(-) diff --git a/opnode/rollup/derive/doc.go b/opnode/rollup/derive/doc.go index 6bd1e39ee9a7..e0b46265c0cd 100644 --- a/opnode/rollup/derive/doc.go +++ b/opnode/rollup/derive/doc.go @@ -14,7 +14,3 @@ // // The steps should be keep separate to enable easier testing. package derive - -// Mock interfaces. TODO: Remove -type BatchData interface{} -type L2Info interface{} diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 495e9f8017bd..8d58dacdba74 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -239,7 +239,7 @@ type L2Info interface { // - The L2 information of the block the new derived blocks build on // // This is a pure function. -func PayloadAttributesV2(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []BatchData, l2Info L2Info) ([]*l2.PayloadAttributes, error) { +func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []BatchData, l2Info L2Info) ([]*l2.PayloadAttributes, error) { // check if we have the full sequencing window if len(seqWindow) == 0 { return nil, errors.New("cannot derive payload attributes from empty sequencing window") @@ -296,43 +296,6 @@ func PayloadAttributesV2(config *rollup.Config, l1Info L1Info, receipts []*types return out, nil } -// PayloadAttributes derives the pre-execution payload from the L1 block info and deposit receipts. -// This is a pure function. -func PayloadAttributes(block L1Info, receipts []*types.Receipt) (*l2.PayloadAttributes, error) { - // if !CheckReceipts(block, receipts) { - // return nil, fmt.Errorf("receipts are not consistent with the block's receipts root: %s", block.ReceiptHash()) - // } - - l1Tx := types.NewTx(L1InfoDeposit(block)) - opaqueL1Tx, err := l1Tx.MarshalBinary() - if err != nil { - return nil, fmt.Errorf("failed to encode L1 info tx") - } - - userDeposits, err := UserDeposits(block.NumberU64(), receipts) - if err != nil { - return nil, fmt.Errorf("failed to derive user deposits: %v", err) - } - - encodedTxs := make([]l2.Data, 0, len(userDeposits)+1) - encodedTxs = append(encodedTxs, opaqueL1Tx) - - for i, tx := range userDeposits { - opaqueTx, err := types.NewTx(tx).MarshalBinary() - if err != nil { - return nil, fmt.Errorf("failed to encode user tx %d", i) - } - encodedTxs = append(encodedTxs, opaqueTx) - } - - return &l2.PayloadAttributes{ - Timestamp: l2.Uint64Quantity(block.Time()), - Random: l2.Bytes32(block.MixDigest()), - SuggestedFeeRecipient: common.Address{}, // nobody gets tx fees for deposits - Transactions: encodedTxs, - }, nil -} - func DeriveDeposits(l1Info L1Info, receipts []*types.Receipt) ([]l2.Data, error) { l1Tx := types.NewTx(L1InfoDeposit(l1Info)) opaqueL1Tx, err := l1Tx.MarshalBinary() diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 8909013494e6..5e993ae300b1 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -22,10 +21,6 @@ const cold = time.Second * 8 // at least try every minute to sync, even if things are going well const max = time.Minute -type Downloader interface { - Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) -} - type Driver struct { log log.Logger rpc DriverAPI @@ -127,15 +122,10 @@ func (e *Driver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL return l2Head.L1Parent, l2Head.Self, err } -func (e *Driver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { - var l1s []eth.BlockID - l1s, refL2, err = rollupSync.FindSyncStart(ctx, e.chainSource, &e.Config.Genesis) - if err != nil && len(l1s) > 0 { - nextRefL1 = l1s[0] - } - return +func (e *Driver) findSyncStart(ctx context.Context) (nextRefL1s []eth.BlockID, refL2 eth.BlockID, err error) { + return rollupSync.FindSyncStart(ctx, e.chainSource, &e.Config.Genesis) } -func (e *Driver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { - return e.step(ctx, nextRefL1, refL2, finalized.Hash) +func (e *Driver) driverStep(ctx context.Context, l1Input []eth.BlockID, l2Parent eth.BlockID, l2Finalized eth.BlockID) (l2ID eth.BlockID, err error) { + return e.step(ctx, l1Input, l2Parent, l2Finalized.Hash) } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 7ec574987621..6dfd8f83519c 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -16,11 +16,11 @@ type internalDriver interface { // findSyncStart statelessly finds the next L1 block to derive, and on which L2 block it applies. // If the engine is fully synced, then the last derived L1 block, and parent L2 block, is repeated. // An error is returned if the sync starting point could not be determined (due to timeouts, wrong-chain, etc.) - findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) + findSyncStart(ctx context.Context) (nextRefL1s []eth.BlockID, refL2 eth.BlockID, err error) // driverStep explicitly calls the engine to derive a L1 block into a L2 block, and apply it on top of the given L2 block. // The finalized L2 block is provided to update the engine with finality, but does not affect the derivation step itself. // The resulting L2 block ID is returned, or an error if the derivation fails. - driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) + driverStep(ctx context.Context, nextRefL1s []eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) } type state struct { @@ -34,6 +34,12 @@ type state struct { // (a week for disputes, or maybe shorter if we see L1 finalize and take the derived L2 chain up till there) l2Finalized eth.BlockID + // l1Next buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. + l1Next []eth.BlockID + // l2NextParent buffers the L2 Block ID to build on with l1Next. + // This may not be in sync with the l2Head in case of reorgs. + l2NextParent eth.BlockID + // The L1 block we are syncing towards, may be ahead of l1Head l1Target eth.BlockID @@ -63,29 +69,57 @@ func (e *state) requestUpdate(ctx context.Context, log log.Logger, driver intern // requestSync tries to sync the provided driver towards the sync target of the state-machine. // If the L2 syncs a step, but is not finished yet, it will return true. False otherwise. func (e *state) requestSync(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { + log = log.New("l1_head", e.l1Head, "l2_head", e.l2Head) if e.l1Head == e.l1Target { - log.Debug("Engine is fully synced", "l1_head", e.l1Head, "l2_head", e.l2Head) + log.Debug("Engine is fully synced") // TODO: even though we are fully synced, it may be worth attempting anyway, // in case the e.l1Head is not updating (failed/broken L1 head subscription) return false } - log.Debug("finding next sync step, engine syncing", "l2", e.l2Head, "l1", e.l1Head) - nextRefL1, refL2, err := driver.findSyncStart(ctx) - if err != nil { - log.Error("Failed to find sync starting point", "err", err) - return false + // If the engine is not in sync with our previous sync preparation, then we need to reconstruct the buffered L1 ids + if e.l2Head != e.l2NextParent { + log.Debug("finding next sync step, engine syncing", "buffered_l2", e.l2NextParent) + nextL1s, refL2, err := driver.findSyncStart(ctx) + if err != nil { + log.Error("Failed to find sync starting point", "err", err) + return false + } + e.l1Next = nextL1s + e.l2NextParent = refL2 + } else { + log.Debug("attempting new sync step") } - if nextRefL1 == e.l1Head { - log.Debug("Engine is already synced, aborting sync", "l1_head", e.l1Head, "l2_head", e.l2Head) + + return e.applyNextWindow(ctx, log, driver) +} + +func (e *state) applyNextWindow(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { + // If the engine moved faster than our buffer try to move the buffer forward, do not get stuck. + for i, id := range e.l1Next { + if e.l1Head == id { + log.Debug("Engine is ahead of rollup node, skipping forward and aborting sync") + e.l1Next = e.l1Next[i+1:] + e.l2NextParent = e.l2Head + return true + } + } + if uint64(len(e.l1Next)) < e.Config.SeqWindowSize { + log.Warn("Not enough known L1 blocks for sequencing window, skipping sync") return false } - if l2ID, err := driver.driverStep(ctx, nextRefL1, refL2, e.l2Finalized); err != nil { - log.Error("Failed to sync L2 chain with new L1 block", "l1", nextRefL1, "onto_l2", refL2, "err", err) + seqWindow := e.l1Next[:e.Config.SeqWindowSize] + log = log.New("l1_window_start", seqWindow[0], "onto_l2", e.l2NextParent) + if l2ID, err := driver.driverStep(ctx, seqWindow, e.l2NextParent, e.l2Finalized); err != nil { + log.Error("Failed to sync L2 chain with new L1 block", "stopped_at", l2ID, "err", err) return false } else { - e.updateHead(nextRefL1, l2ID) // l2ID is derived from the nextRefL1 + log.Debug("Finished driver step", "l1_head", seqWindow[0], "l2_head", l2ID) + e.updateHead(seqWindow[0], l2ID) // l2ID is derived from the nextRefL1 + // shift sequencing window: batches overlap, but we continue deposit/l1info processing from the next block. + e.l1Next = e.l1Next[1:] + e.l2NextParent = l2ID + return true } - return e.l1Head != e.l1Target } // notifyL1Head updates the state-machine with the L1 signal, @@ -96,24 +130,19 @@ func (e *state) notifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth. log.Debug("Received L1 head signal, already synced to it, ignoring event", "l1_head", e.l1Head) return } - if e.l1Head == l1HeadSig.Parent { - // Simple extend, a linear life is easy - if l2ID, err := driver.driverStep(ctx, l1HeadSig.Self, e.l2Head, e.l2Finalized); err != nil { - log.Error("Failed to extend L2 chain with new L1 block", "l1", l1HeadSig.Self, "l2", e.l2Head, "err", err) - // Retry sync later - e.l1Target = l1HeadSig.Self - return false - } else { - e.updateHead(l1HeadSig.Self, l2ID) - return true + e.l1Target = l1HeadSig.Self + // Check if this is a simple extension on top of previous buffered L1 chain we already know of + if len(e.l1Next) > 0 && e.l1Next[len(e.l1Next)-1] == l1HeadSig.Parent { + // don't buffer more than 20 sequencing windows (TBD, sanity limit) + if uint64(len(e.l1Next)) < e.Config.SeqWindowSize*20 { + e.l1Next = append(e.l1Next, l1HeadSig.Self) } + return e.applyNextWindow(ctx, log, driver) } if e.l1Head.Number < l1HeadSig.Parent.Number { log.Debug("Received new L1 head, engine is out of sync, cannot immediately process", "l1", l1HeadSig.Self, "l2", e.l2Head) } else { log.Warn("Received a L1 reorg, syncing new alternative chain", "l1", l1HeadSig.Self, "l2", e.l2Head) } - - e.l1Target = l1HeadSig.Self return false } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index dfd46d7b5f79..a6a432ab73ca 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -54,11 +54,17 @@ type testState struct { } func makeState(st testState) *state { + next := make([]eth.BlockID, len(st.l1Next)) + for i, id := range st.l1Next { + next[i] = id.ID() + } return &state{ - l1Head: st.l1Head.ID(), - l2Head: st.l2Head.ID(), - l2Finalized: st.l2Finalized.ID(), - l1Target: st.l1Target.ID(), + l1Head: st.l1Head.ID(), + l2Head: st.l2Head.ID(), + l2Finalized: st.l2Finalized.ID(), + l1Target: st.l1Target.ID(), + l1Next: next, + l2NextParent: st.l2NextParent.ID(), // TODO: improve testing config (test different seq window sizes and non-zero L2 genesis time?) Config: rollup.Config{ Genesis: rollup.Genesis{ @@ -89,16 +95,16 @@ func (m *mockDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, return } -func (m *mockDriver) findSyncStart(ctx context.Context) (nextRefL1 eth.BlockID, refL2 eth.BlockID, err error) { +func (m *mockDriver) findSyncStart(ctx context.Context) (nextL1s []eth.BlockID, refL2 eth.BlockID, err error) { returnArgs := m.Called(ctx) - nextRefL1 = returnArgs.Get(0).(eth.BlockID) + nextL1s = returnArgs.Get(0).([]eth.BlockID) refL2 = returnArgs.Get(1).(eth.BlockID) err, _ = returnArgs.Get(2).(error) return } -func (m *mockDriver) driverStep(ctx context.Context, nextRefL1 eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { - returnArgs := m.Called(ctx, nextRefL1, refL2, finalized) +func (m *mockDriver) driverStep(ctx context.Context, seqWindow []eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { + returnArgs := m.Called(ctx, seqWindow, refL2, finalized) l2ID = returnArgs.Get(0).(eth.BlockID) err, _ = returnArgs.Get(1).(error) return @@ -112,15 +118,18 @@ func TestEngineDriverState_RequestSync(t *testing.T) { ctx := context.Background() state := makeState(testState{ - l1Head: "c:2", - l2Head: "C:2", - l2Finalized: "B:1", - l1Target: "e:4", - genesisL1: "a:0", - genesisL2: "b:0", + l1Head: "c:2", + l2Head: "C:2", + l2Finalized: "B:1", + l1Target: "e:4", + l1Next: []testID{"d:3", "e:4", "c:5"}, // TODO: multiple batches per L1 block + l2NextParent: "C:2", + genesisL1: "a:0", + genesisL2: "b:0", + seqWindowSize: 1, // TODO: test larger sequencing sizes (requires updating test below) }) - driver.On("findSyncStart", ctx).Return(testID("d:3").ID(), testID("C:2").ID(), nil) - driver.On("driverStep", ctx, testID("d:3").ID(), testID("C:2").ID(), testID("B:1").ID()).Return(testID("D:3").ID(), nil) + driver.On("findSyncStart", ctx).Return([]eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), nil) + driver.On("driverStep", ctx, []eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), testID("B:1").ID()).Return(testID("D:3").ID(), nil) l2Updated := state.requestSync(ctx, log, driver) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index e8dc1f3ebc6c..914ddc38ab4b 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -7,9 +7,12 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" ) type DriverAPI interface { @@ -17,43 +20,95 @@ type DriverAPI interface { l2.EthBackend } -// step takes an L1 block id and then creates and executes the L2 block. The forkchoice is updated as well. -func (d *Driver) step(ctx context.Context, l1Input eth.BlockID, l2Parent eth.BlockID, l2Finalized common.Hash) (eth.BlockID, error) { - logger := d.log.New("input_l1", l1Input, "input_l2_parent", l2Parent, "finalized_l2", l2Finalized) +type Downloader interface { + // FetchL1Info fetches the L1 header information corresponding to a L1 block ID + FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) + // FetchReceipts of a L1 block + FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) + // FetchBatches from the given window of L1 blocks + FetchBatches(ctx context.Context, window []eth.BlockID) ([]derive.BatchData, error) + // FetchL2Info fetches the L2 header information corresponding to a L2 block ID + FetchL2Info(ctx context.Context, id eth.BlockID) (derive.L2Info, error) +} + +// DriverStep derives and processes one or more L2 blocks from the given sequencing window of L1 blocks. +// An incomplete sequencing window will result in an incomplete L2 chain if so. +// +// After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. +func (d *Driver) step(ctx context.Context, l1Input []eth.BlockID, l2Parent eth.BlockID, l2Finalized common.Hash) (out eth.BlockID, err error) { + + if len(l1Input) == 0 { + return l2Parent, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Parent) + } + + logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], + "input_l2_parent", l2Parent, "finalized_l2", l2Finalized) + + epoch := rollup.Epoch(l1Input[0].Number) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - bl, receipts, err := d.dl.Fetch(fetchCtx, l1Input) + + l2Info, err := d.dl.FetchL2Info(fetchCtx, l2Parent) if err != nil { - return eth.BlockID{}, fmt.Errorf("failed to fetch block with receipts: %v", err) + return l2Parent, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Parent, err) + } + l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Input[0]) + if err != nil { + return l2Parent, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Input[0], err) + } + receipts, err := d.dl.FetchReceipts(fetchCtx, l1Input[0]) + if err != nil { + return l2Parent, fmt.Errorf("failed to fetch receipts of %s: %v", l1Input[0], err) + } + // TODO: with sharding the blobs may be identified in more detail than L1 block hashes + batches, err := d.dl.FetchBatches(fetchCtx, l1Input) + if err != nil { + return l2Parent, fmt.Errorf("failed to fetch batches from %s: %v", l1Input, err) } - logger.Debug("fetched L1 data for driver") - attrs, err := derive.PayloadAttributes(bl, receipts) + attrsList, err := derive.PayloadAttributes(&d.Config, l1Info, receipts, batches, l2Info) if err != nil { - return eth.BlockID{}, fmt.Errorf("failed to derive execution payload inputs: %v", err) + return l2Parent, fmt.Errorf("failed to derive execution payload inputs: %v", err) } logger.Debug("derived L2 block inputs") - payload, err := derive.ExecutionPayload(ctx, d.rpc, l2Parent.Hash, l2Finalized, attrs) + last := l2Parent + for i, attrs := range attrsList { + last, err := AddBlock(ctx, logger, d.rpc, last, l2Finalized, attrs) + if err != nil { + return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %v", i, len(attrsList), epoch, err) + } + } + + return last, nil +} + +// AddBlock extends the L2 chain by deriving the full execution payload from inputs, +// and then executing and persisting it. +// +// After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. +func AddBlock(ctx context.Context, logger log.Logger, rpc DriverAPI, + l2Parent eth.BlockID, l2Finalized common.Hash, attrs *l2.PayloadAttributes) (eth.BlockID, error) { + + payload, err := derive.ExecutionPayload(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) if err != nil { - return eth.BlockID{}, fmt.Errorf("failed to derive execution payload: %v", err) + return l2Parent, fmt.Errorf("failed to derive execution payload: %v", err) } logger = logger.New("derived_l2", payload.ID()) logger.Info("derived full block") - err = l2.ExecutePayload(ctx, d.rpc, payload) + err = l2.ExecutePayload(ctx, rpc, payload) if err != nil { - return eth.BlockID{}, fmt.Errorf("failed to apply execution payload: %v", err) + return l2Parent, fmt.Errorf("failed to apply execution payload: %v", err) } logger.Info("executed block") - err = l2.ForkchoiceUpdate(ctx, d.rpc, payload.BlockHash, l2Finalized) + err = l2.ForkchoiceUpdate(ctx, rpc, payload.BlockHash, l2Finalized) if err != nil { - return eth.BlockID{}, fmt.Errorf("failed to persist execution payload: %v", err) + return payload.ID(), fmt.Errorf("failed to persist execution payload: %v", err) } logger.Info("updated fork-choice with block") - return payload.ID(), nil } From 8f0982f33c9256553a4a8adc369584d114c353d3 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 24 Feb 2022 13:30:32 -0800 Subject: [PATCH 271/585] ref impl: Lift rollup configuration It was previously hardcoded in node.Start, but it is now part of the node config to enable easier handling. --- opnode/cmd/main.go | 15 ++++++++++++++- opnode/node/node.go | 19 ++++--------------- opnode/test/system_test.go | 14 +++++++++++++- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 1c331009f5f6..e2ea7c555905 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -3,11 +3,13 @@ package main import ( "context" "fmt" + "math/big" "os" "os/signal" "syscall" "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -120,7 +122,18 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) { L2Hash: L2Hash, L1Hash: L1Hash, L1Num: ctx.GlobalUint64(GenesisL2Hash.Name), - } + Rollup: rollup.Config{ + BlockTime: 2, + MaxSequencerTimeDiff: 10, + SeqWindowSize: 64, + L1ChainID: big.NewInt(901), + // TODO pick defaults + FeeRecipientAddress: common.Address{0xff, 0x01}, + BatchInboxAddress: common.Address{0xff, 0x02}, + BatchSenderAddress: common.Address{0xff, 0x03}, + }, + } + cfg.Rollup.Genesis = cfg.GetGenesis() if err := cfg.Check(); err != nil { return nil, err } diff --git a/opnode/node/node.go b/opnode/node/node.go index 7ae227b61b61..4aaaccbe0f8f 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -3,7 +3,6 @@ package node import ( "context" "fmt" - "math/big" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -29,6 +28,8 @@ type Config struct { L2Hash common.Hash // Genesis block hash of L2 L1Hash common.Hash // Block hash of L1 after (not incl.) which L1 starts deriving blocks L1Num uint64 // Block number of L1 matching the l1-hash + + Rollup rollup.Config } // Check verifies that the given configuration makes sense @@ -69,20 +70,8 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { // TODO: we may need to authenticate the connection with L1 // l1Node.SetHeader() l1Source := l1.NewSource(ethclient.NewClient(l1Node)) - genesis := cfg.GetGenesis() var l2Engines []*driver.Driver - // TODO: Merge into node.Config? - config := rollup.Config{ - Genesis: genesis, - BlockTime: 2, - MaxSequencerTimeDiff: 10, - SeqWindowSize: 64, - L1ChainID: big.NewInt(901), - // TODO pick defaults - FeeRecipientAddress: common.Address{0xff, 0x01}, - BatchInboxAddress: common.Address{0xff, 0x02}, - BatchSenderAddress: common.Address{0xff, 0x03}, - } + for i, addr := range cfg.L2EngineAddrs { // L2 exec engine: updated by this OpNode (L2 consensus layer node) backend, err := rpc.DialContext(ctx, addr) @@ -99,7 +88,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { EthBackend: ethclient.NewClient(backend), Log: log.New("engine_client", i), } - engine := driver.NewDriver(config, client, l1Source, log.New("engine", i)) + engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i)) l2Engines = append(l2Engines, engine) } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index a894531b5083..a716731ecd66 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" + "github.com/stretchr/testify/require" ) func getGenesisHash(client *ethclient.Client) common.Hash { @@ -120,7 +121,18 @@ func TestSystemE2E(t *testing.T) { L1Num: 0, L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, + Rollup: rollup.Config{ + BlockTime: 1, + MaxSequencerTimeDiff: 10, + SeqWindowSize: 1, + L1ChainID: big.NewInt(901), + // TODO pick defaults + FeeRecipientAddress: common.Address{0xff, 0x01}, + BatchInboxAddress: common.Address{0xff, 0x02}, + BatchSenderAddress: common.Address{0xff, 0x03}, + }, } + nodeCfg.Rollup.Genesis = nodeCfg.GetGenesis() node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlTrace)) require.Nil(t, err) From dea0296829834fce1ec79bedb2bb137a4deb4743 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 25 Feb 2022 14:05:34 -0800 Subject: [PATCH 272/585] ref impl: Refactor the rollup driver The rollup driver is similar in structure, but has some fields renamed or moved. The biggest change is in how the driver/state are laid out. Now uses the more complex graph node types instead of eth.BlockID --- opnode/rollup/driver/driver.go | 123 +++---------- opnode/rollup/driver/state.go | 285 ++++++++++++++++++----------- opnode/rollup/driver/state_test.go | 274 +++++++++++++-------------- opnode/rollup/driver/step.go | 45 +++-- 4 files changed, 366 insertions(+), 361 deletions(-) diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 5e993ae300b1..47172c3ab601 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -2,130 +2,53 @@ package driver import ( "context" - "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - rollupSync "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" - + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum/log" ) -// keep making many sync steps if we can make sync progress -const hot = time.Millisecond * 30 - -// check on sync regularly, but prioritize sync triggers with head updates etc. -const cold = time.Second * 8 - -// at least try every minute to sync, even if things are going well -const max = time.Minute - type Driver struct { - log log.Logger - rpc DriverAPI - chainSource rollupSync.ChainSource - dl Downloader - l1Heads <-chan eth.HeadSignal - done chan struct{} - state // embedded engine state + s *state } func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger) *Driver { + input := &inputImpl{ + chainSource: sync.NewChainSource(l1, l2, &cfg.Genesis), + } + output := &outputImpl{ + Config: cfg, + dl: l1, + log: log, + rpc: l2, + } return &Driver{ - log: log, - rpc: l2, - chainSource: rollupSync.NewChainSource(l1, l2, &cfg.Genesis), - dl: l1, - done: make(chan struct{}), - state: state{Config: cfg}, + s: NewState(log, cfg, input, output), } } func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error { - d.l1Heads = l1Heads - if !d.requestUpdate(ctx, d.log, d) { - d.log.Error("failed to fetch engine head, defaulting to genesis") - d.updateHead(d.state.Config.Genesis.L1, d.state.Config.Genesis.L2) - } - go d.loop() - return nil + return d.s.Start(ctx, l1Heads) } func (d *Driver) Close() error { - close(d.done) - return nil + return d.s.Close() } -func (d *Driver) loop() { - ctx := context.Background() - backoff := cold - syncTicker := time.NewTicker(cold) - l2HeadPoll := time.NewTicker(time.Second * 14) - - // exponential backoff, add 10% each step, up to max. - syncBackoff := func() { - backoff += backoff / 10 - if backoff > max { - backoff = max - } - syncTicker.Reset(backoff) - } - syncQuickly := func() { - syncTicker.Reset(hot) - backoff = cold - } - onL2Update := func() { - // And we want to slow down requesting the L2 engine for its head (we just changed it ourselves) - // Request head if we don't successfully change it in the next 14 seconds. - l2HeadPoll.Reset(time.Second * 14) - } - defer syncTicker.Stop() - defer l2HeadPoll.Stop() - - for { - select { - case <-d.done: - return - case <-l2HeadPoll.C: - ctx, cancel := context.WithTimeout(ctx, time.Second*4) - if d.requestUpdate(ctx, d.log, d) { - onL2Update() - } - cancel() - continue - case l1HeadSig := <-d.l1Heads: - ctx, cancel := context.WithTimeout(ctx, time.Second*4) - if d.notifyL1Head(ctx, d.log, l1HeadSig, d) { - syncQuickly() - } - cancel() - continue - case <-syncTicker.C: - // If already synced, or in case of failure, we slow down - syncBackoff() - ctx, cancel := context.WithTimeout(ctx, time.Second*4) - if d.requestSync(ctx, d.log, d) { - // Successfully stepped toward target. Continue quickly if we are not there yet - syncQuickly() - onL2Update() - } - cancel() - } - } - +type inputImpl struct { + chainSource sync.ChainSource } -// Fulfill the `internalDriver` interface - -func (e *Driver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { - l2Head, err := e.chainSource.L2NodeByNumber(ctx, nil) - return l2Head.L1Parent, l2Head.Self, err +func (i *inputImpl) L1Head(ctx context.Context) (eth.L1Node, error) { + return i.chainSource.L1HeadNode(ctx) } -func (e *Driver) findSyncStart(ctx context.Context) (nextRefL1s []eth.BlockID, refL2 eth.BlockID, err error) { - return rollupSync.FindSyncStart(ctx, e.chainSource, &e.Config.Genesis) +func (i *inputImpl) L2Head(ctx context.Context) (eth.L2Node, error) { + return i.chainSource.L2NodeByNumber(ctx, nil) + } -func (e *Driver) driverStep(ctx context.Context, l1Input []eth.BlockID, l2Parent eth.BlockID, l2Finalized eth.BlockID) (l2ID eth.BlockID, err error) { - return e.step(ctx, l1Input, l2Parent, l2Finalized.Hash) +func (i *inputImpl) L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) { + return sync.FindL1Range(ctx, i.chainSource, base) } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 6dfd8f83519c..f9465d66ef4a 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -2,147 +2,218 @@ package driver import ( "context" + "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/log" ) -// internalDriver exposes the driver functionality that maintains the external execution-engine. -type internalDriver interface { - // requestEngineHead retrieves the L2 he```d reference of the engine, as well as the L1 reference it was derived from. - // An error is returned when the L2 head information could not be retrieved (timeout or connection issue) - requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) - // findSyncStart statelessly finds the next L1 block to derive, and on which L2 block it applies. - // If the engine is fully synced, then the last derived L1 block, and parent L2 block, is repeated. - // An error is returned if the sync starting point could not be determined (due to timeouts, wrong-chain, etc.) - findSyncStart(ctx context.Context) (nextRefL1s []eth.BlockID, refL2 eth.BlockID, err error) - // driverStep explicitly calls the engine to derive a L1 block into a L2 block, and apply it on top of the given L2 block. - // The finalized L2 block is provided to update the engine with finality, but does not affect the derivation step itself. - // The resulting L2 block ID is returned, or an error if the derivation fails. - driverStep(ctx context.Context, nextRefL1s []eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) +type inputInterface interface { + L1Head(ctx context.Context) (eth.L1Node, error) + L2Head(ctx context.Context) (eth.L2Node, error) + L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) +} + +type outputInterface interface { + step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) } type state struct { - // l1Head tracks the L1 block corresponding to the l2Head - l1Head eth.BlockID + // Chain State + l1Head eth.BlockID // Latest recorded head of the L1 Chain + l1Base eth.BlockID // L1 Parent of L2 Head block + l2Head eth.BlockID // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) + l2Finalized eth.BlockID // L2 Block that will never be reversed + l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. - // l2Head tracks the head-block of the engine - l2Head eth.BlockID + // Rollup config + Config rollup.Config - // l2Finalized tracks the block the engine can safely regard as irreversible - // (a week for disputes, or maybe shorter if we see L1 finalize and take the derived L2 chain up till there) - l2Finalized eth.BlockID + // Connections (in/out) + l1Heads <-chan eth.HeadSignal + input inputInterface + output outputInterface - // l1Next buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. - l1Next []eth.BlockID - // l2NextParent buffers the L2 Block ID to build on with l1Next. - // This may not be in sync with the l2Head in case of reorgs. - l2NextParent eth.BlockID + log log.Logger + done chan struct{} +} - // The L1 block we are syncing towards, may be ahead of l1Head - l1Target eth.BlockID +// l1WindowEnd returns the last block that should be used as `base` to L1ChainWindow +// This is either the last block of the window, or the L1 base block if the window is not populated +func (s *state) l1WindowEnd() eth.BlockID { + if len(s.l1Window) == 0 { + return s.l1Base + } + return s.l1Window[len(s.l1Window)-1] +} - // Rollup config - Config rollup.Config +// TODO: Split this function into populate window & SequencingWindow +func (s *state) getNextWindow(ctx context.Context) ([]eth.BlockID, error) { + + if uint64(len(s.l1Window)) < s.Config.SeqWindowSize { + nexts, err := s.input.L1ChainWindow(ctx, s.l1WindowEnd()) + if err != nil { + return nil, err + } + s.l1Window = append(s.l1Window, nexts...) + } + l := uint64(len(s.l1Window)) + if l > s.Config.SeqWindowSize { + l = s.Config.SeqWindowSize + } + return s.l1Window[:l], nil } -func (e *state) updateHead(l1Head eth.BlockID, l2Head eth.BlockID) { - e.l1Head = l1Head - e.l2Head = l2Head +func NewState(log log.Logger, config rollup.Config, input inputInterface, output outputInterface) *state { + return &state{ + Config: config, + done: make(chan struct{}), + log: log, + input: input, + output: output, + } } -// requestUpdate tries to update the state-machine with the driver head information. -// If the state-machine changed, considering the engine L1 and L2 head, it will return true. False otherwise. -func (e *state) requestUpdate(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { - refL1, refL2, err := driver.requestEngineHead(ctx) +func (s *state) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error { + l1Head, err := s.input.L1Head(ctx) + if err != nil { + return err + } + l2Head, err := s.input.L2Head(ctx) if err != nil { - log.Error("failed to request engine head", "err", err) - return false + return err } - e.l1Head = refL1 - e.l2Head = refL2 - return e.l1Head != refL1 || e.l2Head != refL2 + s.l1Head = l1Head.Self + s.l2Head = l2Head.Self + s.l1Base = l2Head.L1Parent + s.l1Heads = l1Heads + + go s.loop() + return nil } -// requestSync tries to sync the provided driver towards the sync target of the state-machine. -// If the L2 syncs a step, but is not finished yet, it will return true. False otherwise. -func (e *state) requestSync(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { - log = log.New("l1_head", e.l1Head, "l2_head", e.l2Head) - if e.l1Head == e.l1Target { - log.Debug("Engine is fully synced") - // TODO: even though we are fully synced, it may be worth attempting anyway, - // in case the e.l1Head is not updating (failed/broken L1 head subscription) - return false +func (s *state) Close() error { + close(s.done) + return nil +} + +func (s *state) handleReorg(ctx context.Context, head eth.HeadSignal) error { + log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", head.Parent, "new_l1_head", head.Self) + nextL2Head, err := s.input.L2Head(ctx) + if err != nil { + log.Error("Could not get new L2 head when trying to handle a re-org", "err", err) + // TODO: How do you handle this error - it seems to break everything + return err } - // If the engine is not in sync with our previous sync preparation, then we need to reconstruct the buffered L1 ids - if e.l2Head != e.l2NextParent { - log.Debug("finding next sync step, engine syncing", "buffered_l2", e.l2NextParent) - nextL1s, refL2, err := driver.findSyncStart(ctx) + s.l1Head = head.Parent + s.l1Window = nil + s.l1Base = nextL2Head.L1Parent + s.l2Head = nextL2Head.Self + return nil +} + +// newL1Head takes the new head and updates the internal state to reflect the new chain state. +// Returns true if it is a re-org, false otherwise (linear extension, no-op, or other simple case). +// If there is a re-org, this updates the internal state to handle the re-org. +// Note that `ctx` is only used in a re-org and that handling a re-org may take a long period of time. +// The L2 engine is not modified in this function. +func (s *state) newL1Head(ctx context.Context, head eth.HeadSignal) (bool, error) { + // Already have head + if s.l1Head == head.Self { + log.Trace("Received L1 head signal that is the same as the current head", "l1_head", head.Self) + return false, nil + } + // Re-org (maybe also a skip) + if s.l1Head != head.Parent { + err := s.handleReorg(ctx, head) if err != nil { - log.Error("Failed to find sync starting point", "err", err) - return false + return false, err } - e.l1Next = nextL1s - e.l2NextParent = refL2 - } else { - log.Debug("attempting new sync step") + } + // Linear extension + s.l1Head = head.Self + if len(s.l1Window) > 0 && s.l1Window[len(s.l1Window)-1] == head.Parent { + // // don't buffer more than 20 sequencing windows (TBD, sanity limit) + // if uint64(len(e.l1Next)) < e.Config.SeqWindowSize*20 { + // e.l1Next = append(e.l1Next, l1HeadSig.Self) + // } + s.l1Window = append(s.l1Window, head.Self) } - return e.applyNextWindow(ctx, log, driver) + return false, nil + } -func (e *state) applyNextWindow(ctx context.Context, log log.Logger, driver internalDriver) (l2Updated bool) { - // If the engine moved faster than our buffer try to move the buffer forward, do not get stuck. - for i, id := range e.l1Next { - if e.l1Head == id { - log.Debug("Engine is ahead of rollup node, skipping forward and aborting sync") - e.l1Next = e.l1Next[i+1:] - e.l2NextParent = e.l2Head - return true - } - } - if uint64(len(e.l1Next)) < e.Config.SeqWindowSize { - log.Warn("Not enough known L1 blocks for sequencing window, skipping sync") - return false - } - seqWindow := e.l1Next[:e.Config.SeqWindowSize] - log = log.New("l1_window_start", seqWindow[0], "onto_l2", e.l2NextParent) - if l2ID, err := driver.driverStep(ctx, seqWindow, e.l2NextParent, e.l2Finalized); err != nil { - log.Error("Failed to sync L2 chain with new L1 block", "stopped_at", l2ID, "err", err) - return false - } else { - log.Debug("Finished driver step", "l1_head", seqWindow[0], "l2_head", l2ID) - e.updateHead(seqWindow[0], l2ID) // l2ID is derived from the nextRefL1 - // shift sequencing window: batches overlap, but we continue deposit/l1info processing from the next block. - e.l1Next = e.l1Next[1:] - e.l2NextParent = l2ID - return true +func (s *state) newSafeL2Head(head eth.BlockID) { + s.log.Trace("New L2 head", "head", head) + s.l2Head = head + // TODO: Update L1 base here. + + // Remove the processed L1 block from the window + if len(s.l1Window) > 0 { + s.l1Window = s.l1Window[:1] } } -// notifyL1Head updates the state-machine with the L1 signal, -// and attempts to sync the driver if the update extends the previous head. -// Returns true if the driver successfully derived and synced the L2 block to match L1. False otherwise. -func (e *state) notifyL1Head(ctx context.Context, log log.Logger, l1HeadSig eth.HeadSignal, driver internalDriver) (l2Updated bool) { - if e.l1Head == l1HeadSig.Self { - log.Debug("Received L1 head signal, already synced to it, ignoring event", "l1_head", e.l1Head) - return - } - e.l1Target = l1HeadSig.Self - // Check if this is a simple extension on top of previous buffered L1 chain we already know of - if len(e.l1Next) > 0 && e.l1Next[len(e.l1Next)-1] == l1HeadSig.Parent { - // don't buffer more than 20 sequencing windows (TBD, sanity limit) - if uint64(len(e.l1Next)) < e.Config.SeqWindowSize*20 { - e.l1Next = append(e.l1Next, l1HeadSig.Self) +func (s *state) loop() { + s.log.Info("State loop started") + ctx := context.Background() + // l1Poll := time.NewTicker(1 * time.Second) + // l2Poll := time.NewTicker(1 * time.Second) + stepRequest := make(chan struct{}, 1) + // defer l1Poll.Stop() + // defer l2Poll.Stop() + + requestStep := func() { + select { + case stepRequest <- struct{}{}: + default: } - return e.applyNextWindow(ctx, log, driver) } - if e.l1Head.Number < l1HeadSig.Parent.Number { - log.Debug("Received new L1 head, engine is out of sync, cannot immediately process", "l1", l1HeadSig.Self, "l2", e.l2Head) - } else { - log.Warn("Received a L1 reorg, syncing new alternative chain", "l1", l1HeadSig.Self, "l2", e.l2Head) + + requestStep() + + for { + select { + // TODO: Poll cases (and move to bottom) + // case <-l1Poll.C: + // case <-l2Poll.C: + case <-s.done: + return + case l1HeadSig := <-s.l1Heads: + s.log.Trace("L1 Head Update", "new_head", l1HeadSig.Self) + // Set a long timeout because the timeout is for running sync.L2Head + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + _, err := s.newL1Head(ctx, l1HeadSig) + if err != nil { + panic(err) + } + requestStep() + cancel() + + case <-stepRequest: + s.log.Trace("Step request") + window, err := s.getNextWindow(ctx) + if err != nil { + panic(err) + } + if len(window) == int(s.Config.SeqWindowSize) { + s.log.Trace("Running step") + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + newL2Head, err := s.output.step(ctx, s.l2Head, s.l2Finalized, window) + cancel() + s.log.Trace("step output", "head", newL2Head, "err", err) + if err != nil { + panic(err) + } + s.newSafeL2Head(newL2Head) + } else { + s.log.Trace("Not enough saved blocks to run step") + } + + } } - return false + } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index a6a432ab73ca..ef8d60936a76 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -1,139 +1,139 @@ package driver -import ( - "context" - "math/big" - "strconv" - "strings" - "testing" - - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -type testID string - -func (id testID) ID() eth.BlockID { - parts := strings.Split(string(id), ":") - if len(parts) != 2 { - panic("bad id") - } - if len(parts[0]) > 32 { - panic("test ID hash too long") - } - var h common.Hash - copy(h[:], parts[0]) - v, err := strconv.ParseUint(parts[1], 0, 64) - if err != nil { - panic(err) - } - return eth.BlockID{ - Hash: h, - Number: v, - } -} - -type testState struct { - l1Head testID - l2Head testID - l2Finalized testID - l1Target testID - - l1Next []testID - l2NextParent testID - - genesisL1 testID - genesisL2 testID - - seqWindowSize uint64 -} - -func makeState(st testState) *state { - next := make([]eth.BlockID, len(st.l1Next)) - for i, id := range st.l1Next { - next[i] = id.ID() - } - return &state{ - l1Head: st.l1Head.ID(), - l2Head: st.l2Head.ID(), - l2Finalized: st.l2Finalized.ID(), - l1Target: st.l1Target.ID(), - l1Next: next, - l2NextParent: st.l2NextParent.ID(), - // TODO: improve testing config (test different seq window sizes and non-zero L2 genesis time?) - Config: rollup.Config{ - Genesis: rollup.Genesis{ - L1: st.genesisL1.ID(), - L2: st.genesisL2.ID(), - L2Time: 0, - }, - BlockTime: 2, - MaxSequencerTimeDiff: 10, - SeqWindowSize: st.seqWindowSize, - L1ChainID: big.NewInt(100), - FeeRecipientAddress: common.Address{0x0a}, - BatchInboxAddress: common.Address{0x0b}, - BatchSenderAddress: common.Address{0x0c}, - }, - } -} - -type mockDriver struct { - mock.Mock -} - -func (m *mockDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { - returnArgs := m.Called(ctx) - refL1 = returnArgs.Get(0).(eth.BlockID) - refL2 = returnArgs.Get(1).(eth.BlockID) - err = returnArgs.Get(2).(error) - return -} - -func (m *mockDriver) findSyncStart(ctx context.Context) (nextL1s []eth.BlockID, refL2 eth.BlockID, err error) { - returnArgs := m.Called(ctx) - nextL1s = returnArgs.Get(0).([]eth.BlockID) - refL2 = returnArgs.Get(1).(eth.BlockID) - err, _ = returnArgs.Get(2).(error) - return -} - -func (m *mockDriver) driverStep(ctx context.Context, seqWindow []eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { - returnArgs := m.Called(ctx, seqWindow, refL2, finalized) - l2ID = returnArgs.Get(0).(eth.BlockID) - err, _ = returnArgs.Get(1).(error) - return -} - -var _ internalDriver = (*mockDriver)(nil) - -func TestEngineDriverState_RequestSync(t *testing.T) { - log := testlog.Logger(t, log.LvlTrace) - driver := new(mockDriver) - ctx := context.Background() - - state := makeState(testState{ - l1Head: "c:2", - l2Head: "C:2", - l2Finalized: "B:1", - l1Target: "e:4", - l1Next: []testID{"d:3", "e:4", "c:5"}, // TODO: multiple batches per L1 block - l2NextParent: "C:2", - genesisL1: "a:0", - genesisL2: "b:0", - seqWindowSize: 1, // TODO: test larger sequencing sizes (requires updating test below) - }) - driver.On("findSyncStart", ctx).Return([]eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), nil) - driver.On("driverStep", ctx, []eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), testID("B:1").ID()).Return(testID("D:3").ID(), nil) - - l2Updated := state.requestSync(ctx, log, driver) - - assert.Equal(t, state.l1Head, testID("d:3").ID()) - assert.Equal(t, state.l2Head, testID("D:3").ID()) - assert.True(t, l2Updated) -} +// import ( +// "context" +// "math/big" +// "strconv" +// "strings" +// "testing" + +// "github.com/ethereum-optimism/optimistic-specs/opnode/eth" +// "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" +// "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" +// "github.com/ethereum/go-ethereum/common" +// "github.com/ethereum/go-ethereum/log" +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/mock" +// ) + +// type testID string + +// func (id testID) ID() eth.BlockID { +// parts := strings.Split(string(id), ":") +// if len(parts) != 2 { +// panic("bad id") +// } +// if len(parts[0]) > 32 { +// panic("test ID hash too long") +// } +// var h common.Hash +// copy(h[:], parts[0]) +// v, err := strconv.ParseUint(parts[1], 0, 64) +// if err != nil { +// panic(err) +// } +// return eth.BlockID{ +// Hash: h, +// Number: v, +// } +// } + +// type testState struct { +// l1Head testID +// l1Base testID +// l2Head testID +// l2Finalized testID + +// l1Window []testID +// l1WindowEnd testID + +// genesisL1 testID +// genesisL2 testID + +// seqWindowSize uint64 +// } + +// func makeState(st testState) *state { +// window := make([]eth.BlockID, len(st.l1Window)) +// for i, id := range st.l1Window { +// window[i] = id.ID() +// } +// return &state{ +// l1Head: st.l1Head.ID(), +// l2Head: st.l2Head.ID(), +// l2Finalized: st.l2Finalized.ID(), +// l1Base: st.l1Base.ID(), +// l1Window: window, +// l1WindowEnd: st.l1WindowEnd.ID(), +// // TODO: improve testing config (test different seq window sizes and non-zero L2 genesis time?) +// Config: rollup.Config{ +// Genesis: rollup.Genesis{ +// L1: st.genesisL1.ID(), +// L2: st.genesisL2.ID(), +// L2Time: 0, +// }, +// BlockTime: 2, +// MaxSequencerTimeDiff: 10, +// SeqWindowSize: st.seqWindowSize, +// L1ChainID: big.NewInt(100), +// FeeRecipientAddress: common.Address{0x0a}, +// BatchInboxAddress: common.Address{0x0b}, +// BatchSenderAddress: common.Address{0x0c}, +// }, +// } +// } + +// type mockDriver struct { +// mock.Mock +// } + +// func (m *mockDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { +// returnArgs := m.Called(ctx) +// refL1 = returnArgs.Get(0).(eth.BlockID) +// refL2 = returnArgs.Get(1).(eth.BlockID) +// err = returnArgs.Get(2).(error) +// return +// } + +// func (m *mockDriver) findSyncStart(ctx context.Context) (nextL1s []eth.BlockID, refL2 eth.BlockID, err error) { +// returnArgs := m.Called(ctx) +// nextL1s = returnArgs.Get(0).([]eth.BlockID) +// refL2 = returnArgs.Get(1).(eth.BlockID) +// err, _ = returnArgs.Get(2).(error) +// return +// } + +// func (m *mockDriver) driverStep(ctx context.Context, seqWindow []eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { +// returnArgs := m.Called(ctx, seqWindow, refL2, finalized) +// l2ID = returnArgs.Get(0).(eth.BlockID) +// err, _ = returnArgs.Get(1).(error) +// return +// } + +// var _ internalDriver = (*mockDriver)(nil) + +// func TestEngineDriverState_RequestSync(t *testing.T) { +// log := testlog.Logger(t, log.LvlTrace) +// driver := new(mockDriver) +// ctx := context.Background() + +// state := makeState(testState{ +// l1Head: "e:4", +// l1Base: "c:2", +// l2Head: "C:2", +// l2Finalized: "B:1", +// l1Window: []testID{"d:3", "e:4", "c:5"}, // TODO: multiple batches per L1 block +// l1WindowEnd: "c:5", +// genesisL1: "a:0", +// genesisL2: "b:0", +// seqWindowSize: 1, // TODO: test larger sequencing sizes (requires updating test below) +// }) +// driver.On("findSyncStart", ctx).Return([]eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), nil) +// driver.On("driverStep", ctx, []eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), testID("B:1").ID()).Return(testID("D:3").ID(), nil) + +// l2Updated := state.requestSync(ctx, log, driver) + +// assert.Equal(t, state.l1Head, testID("d:3").ID()) +// assert.Equal(t, state.l2Head, testID("D:3").ID()) +// assert.True(t, l2Updated) +// } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 914ddc38ab4b..eeb52e2b073c 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -15,11 +15,6 @@ import ( "github.com/ethereum/go-ethereum/log" ) -type DriverAPI interface { - l2.EngineAPI - l2.EthBackend -} - type Downloader interface { // FetchL1Info fetches the L1 header information corresponding to a L1 block ID FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) @@ -31,51 +26,67 @@ type Downloader interface { FetchL2Info(ctx context.Context, id eth.BlockID) (derive.L2Info, error) } +type DriverAPI interface { + l2.EngineAPI + l2.EthBackend +} + +type outputImpl struct { + dl Downloader + rpc DriverAPI + log log.Logger + Config rollup.Config +} + // DriverStep derives and processes one or more L2 blocks from the given sequencing window of L1 blocks. // An incomplete sequencing window will result in an incomplete L2 chain if so. // // After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. -func (d *Driver) step(ctx context.Context, l1Input []eth.BlockID, l2Parent eth.BlockID, l2Finalized common.Hash) (out eth.BlockID, err error) { - +func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Input []eth.BlockID) (out eth.BlockID, err error) { if len(l1Input) == 0 { - return l2Parent, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Parent) + return l2Head, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Head) } logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], - "input_l2_parent", l2Parent, "finalized_l2", l2Finalized) + "input_l2_parent", l2Head, "finalized_l2", l2Finalized) + logger.Trace("Running update step on the L2 node") epoch := rollup.Epoch(l1Input[0].Number) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - l2Info, err := d.dl.FetchL2Info(fetchCtx, l2Parent) + l2Info, err := d.dl.FetchL2Info(fetchCtx, l2Head) if err != nil { - return l2Parent, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Parent, err) + return l2Head, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Head, err) } + logger.Trace("Got l2 info") l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Input[0]) if err != nil { - return l2Parent, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Input[0], err) + return l2Head, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Input[0], err) } + logger.Trace("Got l1 info") receipts, err := d.dl.FetchReceipts(fetchCtx, l1Input[0]) if err != nil { - return l2Parent, fmt.Errorf("failed to fetch receipts of %s: %v", l1Input[0], err) + return l2Head, fmt.Errorf("failed to fetch receipts of %s: %v", l1Input[0], err) } + logger.Trace("Got receipts") // TODO: with sharding the blobs may be identified in more detail than L1 block hashes batches, err := d.dl.FetchBatches(fetchCtx, l1Input) if err != nil { - return l2Parent, fmt.Errorf("failed to fetch batches from %s: %v", l1Input, err) + return l2Head, fmt.Errorf("failed to fetch batches from %s: %v", l1Input, err) } + logger.Trace("Got batches") attrsList, err := derive.PayloadAttributes(&d.Config, l1Info, receipts, batches, l2Info) if err != nil { - return l2Parent, fmt.Errorf("failed to derive execution payload inputs: %v", err) + return l2Head, fmt.Errorf("failed to derive execution payload inputs: %v", err) } logger.Debug("derived L2 block inputs") - last := l2Parent + last := l2Head for i, attrs := range attrsList { - last, err := AddBlock(ctx, logger, d.rpc, last, l2Finalized, attrs) + last, err := AddBlock(ctx, logger, d.rpc, last, l2Finalized.Hash, attrs) if err != nil { return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %v", i, len(attrsList), epoch, err) } From 5b197d263308a4e6e40c780a309c672c1e249517 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 16:36:54 -0800 Subject: [PATCH 273/585] ref impl: Fix L2 derivation in the case of 0 batches In the case that there were no batches derive.PayloadAttributes would not be able to derive a block. This is incorrect because deposit blocks should still be able to force updates even while the sequencer is down. --- opnode/rollup/derive/payload_attributes.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 8d58dacdba74..444b1198ce21 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -2,7 +2,6 @@ package derive import ( "encoding/binary" - "errors" "fmt" "math/big" @@ -240,11 +239,6 @@ type L2Info interface { // // This is a pure function. func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []BatchData, l2Info L2Info) ([]*l2.PayloadAttributes, error) { - // check if we have the full sequencing window - if len(seqWindow) == 0 { - return nil, errors.New("cannot derive payload attributes from empty sequencing window") - } - // Retrieve the deposits of this epoch (all deposits from the first block) deposits, err := DeriveDeposits(l1Info, receipts) if err != nil { @@ -274,7 +268,13 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R } } + // If there are no submitted batches, at least derive the deposit block. + if len(seqWindow) == 0 { + highestSeenTimestamp += config.BlockTime + } + // fill the gaps and always ensure at least one L2 block + // TODO: What happens if `highestSeenTimestamp` start rolling into the next epoch (higher than the next L1 block timestamp) var out []*l2.PayloadAttributes for t := l1Info.Time() + config.BlockTime; t <= highestSeenTimestamp; t += config.BlockTime { if bl, ok := l2Blocks[t]; ok { From 555d6c7a81a750f7f8f0c2131d0c5d1f333cb82b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 15:57:12 -0800 Subject: [PATCH 274/585] ref impl: Switch HeadSignal to L1Node These are functionally the same so I merged them into one. --- opnode/eth/heads.go | 9 ++------- opnode/node/node.go | 8 ++++---- opnode/rollup/driver/driver.go | 2 +- opnode/rollup/driver/state.go | 8 ++++---- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/opnode/eth/heads.go b/opnode/eth/heads.go index b2774e2a5ed3..2776d1f38fa7 100644 --- a/opnode/eth/heads.go +++ b/opnode/eth/heads.go @@ -8,13 +8,8 @@ import ( "github.com/ethereum/go-ethereum/event" ) -type HeadSignal struct { - Parent BlockID - Self BlockID -} - // HeadSignalFn is used as callback function to accept head-signals -type HeadSignalFn func(sig HeadSignal) +type HeadSignalFn func(sig L1Node) type NewHeadSource interface { SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) @@ -39,7 +34,7 @@ func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) ( if height > 0 { parent = BlockID{Hash: header.ParentHash, Number: height - 1} } - fn(HeadSignal{Parent: parent, Self: self}) + fn(L1Node{Parent: parent, Self: self}) case err := <-sub.Err(): return err case <-ctx.Done(): diff --git a/opnode/node/node.go b/opnode/node/node.go index 4aaaccbe0f8f..5f3a94cfa27b 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -119,7 +119,7 @@ func (c *OpNode) Start(ctx context.Context) error { c.log.Info("Fetching rollup starting point") - // Feed of eth.HeadSignal + // Feed of eth.L1Node var l1HeadsFeed event.Feed c.log.Info("Attaching execution engine(s)") @@ -128,7 +128,7 @@ func (c *OpNode) Start(ctx context.Context) error { reqCtx, reqCancel := context.WithTimeout(ctx, time.Second*10) // driver subscribes to L1 head changes - l1SubCh := make(chan eth.HeadSignal, 10) + l1SubCh := make(chan eth.L1Node, 10) l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine err := eng.Start(reqCtx, l1SubCh) @@ -144,14 +144,14 @@ func (c *OpNode) Start(ctx context.Context) error { if err != nil { c.log.Warn("resubscribing after failed L1 subscription", "err", err) } - return eth.WatchHeadChanges(context.Background(), c.l1Source, func(sig eth.HeadSignal) { + return eth.WatchHeadChanges(context.Background(), c.l1Source, func(sig eth.L1Node) { l1HeadsFeed.Send(sig) }) }) handleUnsubscribe(l1HeadsSub, "l1 heads subscription failed") // subscribe to L1 heads for info - l1Heads := make(chan eth.HeadSignal, 10) + l1Heads := make(chan eth.L1Node, 10) l1HeadsFeed.Subscribe(l1Heads) c.log.Info("Start-up complete!") diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 47172c3ab601..01cdb33ee3cf 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -29,7 +29,7 @@ func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger) *D } } -func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error { +func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.L1Node) error { return d.s.Start(ctx, l1Heads) } func (d *Driver) Close() error { diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index f9465d66ef4a..9f3c8de3766d 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -31,7 +31,7 @@ type state struct { Config rollup.Config // Connections (in/out) - l1Heads <-chan eth.HeadSignal + l1Heads <-chan eth.L1Node input inputInterface output outputInterface @@ -75,7 +75,7 @@ func NewState(log log.Logger, config rollup.Config, input inputInterface, output } } -func (s *state) Start(ctx context.Context, l1Heads <-chan eth.HeadSignal) error { +func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1Node) error { l1Head, err := s.input.L1Head(ctx) if err != nil { return err @@ -99,7 +99,7 @@ func (s *state) Close() error { return nil } -func (s *state) handleReorg(ctx context.Context, head eth.HeadSignal) error { +func (s *state) handleReorg(ctx context.Context, head eth.L1Node) error { log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", head.Parent, "new_l1_head", head.Self) nextL2Head, err := s.input.L2Head(ctx) if err != nil { @@ -119,7 +119,7 @@ func (s *state) handleReorg(ctx context.Context, head eth.HeadSignal) error { // If there is a re-org, this updates the internal state to handle the re-org. // Note that `ctx` is only used in a re-org and that handling a re-org may take a long period of time. // The L2 engine is not modified in this function. -func (s *state) newL1Head(ctx context.Context, head eth.HeadSignal) (bool, error) { +func (s *state) newL1Head(ctx context.Context, head eth.L1Node) (bool, error) { // Already have head if s.l1Head == head.Self { log.Trace("Received L1 head signal that is the same as the current head", "l1_head", head.Self) From 4d1eb0fe32d8ea50e9d60283991472752c487406 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 2 Mar 2022 16:45:10 -0800 Subject: [PATCH 275/585] ref impl: Increase timeout in e2e test This is now needed to wait for blocks to show up on L2 because the rollup is one sequence window behind the deposits on L1. --- opnode/test/system_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index a716731ecd66..e5a565bf1e58 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -248,7 +248,7 @@ func TestSystemE2E(t *testing.T) { require.Nil(t, err, "Could not get transaction receipt") // Wait (or timeout) for that block to show up on L2 - timeoutCh := time.After(3 * time.Second) + timeoutCh := time.After(6 * time.Second) loop: for { select { From e205a4d0787fd651a2d11345046eb97011b81a56 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Mar 2022 10:58:54 -0800 Subject: [PATCH 276/585] ref impl: Small fix for L1Range function Issues discovered while testing the driver. --- opnode/rollup/sync/start.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index b963b4d72f3e..325938f1d4c0 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -137,6 +137,10 @@ func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([] maxBlocks = l1head.Self.Number - begin.Number } + if maxBlocks == 0 { + return nil, nil + } + prevHash := begin.Hash var res []eth.BlockID for i := begin.Number + 1; i < begin.Number+maxBlocks+1; i++ { From 1636ca96eb6da190a1b62d05f2e9734c93c61c64 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Mar 2022 10:59:39 -0800 Subject: [PATCH 277/585] ref impl: Small fixes to driver/state Found while testing. --- opnode/rollup/driver/state.go | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 9f3c8de3766d..96abd485619a 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -52,10 +52,12 @@ func (s *state) l1WindowEnd() eth.BlockID { func (s *state) getNextWindow(ctx context.Context) ([]eth.BlockID, error) { if uint64(len(s.l1Window)) < s.Config.SeqWindowSize { + s.log.Trace("Pulling chain window from L1", "cached_size", len(s.l1Window), "window_end", s.l1WindowEnd()) nexts, err := s.input.L1ChainWindow(ctx, s.l1WindowEnd()) if err != nil { return nil, err } + s.log.Trace("Window from l1", "nexts", nexts) s.l1Window = append(s.l1Window, nexts...) } l := uint64(len(s.l1Window)) @@ -134,7 +136,8 @@ func (s *state) newL1Head(ctx context.Context, head eth.L1Node) (bool, error) { } // Linear extension s.l1Head = head.Self - if len(s.l1Window) > 0 && s.l1Window[len(s.l1Window)-1] == head.Parent { + // Check if the new block extends the L1 window and save it if so. + if s.l1WindowEnd() == head.Parent { // // don't buffer more than 20 sequencing windows (TBD, sanity limit) // if uint64(len(e.l1Next)) < e.Config.SeqWindowSize*20 { // e.l1Next = append(e.l1Next, l1HeadSig.Self) @@ -146,17 +149,6 @@ func (s *state) newL1Head(ctx context.Context, head eth.L1Node) (bool, error) { } -func (s *state) newSafeL2Head(head eth.BlockID) { - s.log.Trace("New L2 head", "head", head) - s.l2Head = head - // TODO: Update L1 base here. - - // Remove the processed L1 block from the window - if len(s.l1Window) > 0 { - s.l1Window = s.l1Window[:1] - } -} - func (s *state) loop() { s.log.Info("State loop started") ctx := context.Background() @@ -194,11 +186,11 @@ func (s *state) loop() { cancel() case <-stepRequest: - s.log.Trace("Step request") window, err := s.getNextWindow(ctx) if err != nil { panic(err) } + s.log.Trace("Step request", "window", window) if len(window) == int(s.Config.SeqWindowSize) { s.log.Trace("Running step") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) @@ -208,7 +200,11 @@ func (s *state) loop() { if err != nil { panic(err) } - s.newSafeL2Head(newL2Head) + s.l2Head = newL2Head + s.l1Base = s.l1Window[0] + s.l1Window = s.l1Window[1:] + // TODO: l2Finalized/l2Safe. + } else { s.log.Trace("Not enough saved blocks to run step") } From 65cf5362b4ff95f6aa14aa2b7571f952b777eb67 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Mar 2022 11:00:04 -0800 Subject: [PATCH 278/585] ref impl: Better driver testing This adds a framework to create a fake L1 and L2 chain. The chain can be advanced & re-orged. The state_test uses this chain as the chainsource to the `state` object. It advances the L1 block and ensures that the resulting L2 state is as expected. --- opnode/rollup/driver/fake_chain.go | 163 +++++++++++++++ opnode/rollup/driver/state_test.go | 315 ++++++++++++++++------------- 2 files changed, 341 insertions(+), 137 deletions(-) create mode 100644 opnode/rollup/driver/fake_chain.go diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go new file mode 100644 index 000000000000..10622e51f651 --- /dev/null +++ b/opnode/rollup/driver/fake_chain.go @@ -0,0 +1,163 @@ +package driver + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" +) + +func fakeID(id rune, num uint64) eth.BlockID { + var h common.Hash + copy(h[:], string(id)) + return eth.BlockID{Hash: h, Number: uint64(num)} +} + +func fakeL1Block(self rune, parent rune, num uint64) eth.L1Node { + var parentID eth.BlockID + if num != 0 { + parentID = fakeID(parent, num-1) + } + return eth.L1Node{Self: fakeID(self, num), Parent: parentID} +} + +func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2Node { + var parentID eth.BlockID + if num != 0 { + parentID = fakeID(parent, num-1) + } + return eth.L2Node{Self: fakeID(self, num), L2Parent: parentID, L1Parent: l1parent} +} + +func chainL1(offset uint64, ids string) (out []eth.L1Node) { + var prevID rune + for i, id := range ids { + out = append(out, fakeL1Block(id, prevID, offset+uint64(i))) + prevID = id + } + return +} + +func chainL2(l1 []eth.L1Node, ids string) (out []eth.L2Node) { + var prevID rune + for i, id := range ids { + out = append(out, fakeL2Block(id, prevID, l1[i].Self, uint64(i))) + prevID = id + } + return +} + +func NewFakeChainSource(l1 []string, l2 []string, log log.Logger) *fakeChainSource { + var l1s [][]eth.L1Node + for _, l1string := range l1 { + l1s = append(l1s, chainL1(0, l1string)) + } + var l2s [][]eth.L2Node + for i, l2string := range l2 { + l2s = append(l2s, chainL2(l1s[i], l2string)) + } + return &fakeChainSource{ + l1s: l1s, + l2s: l2s, + log: log, + } +} + +// fakeChainSource implements the ChainSource interface with the ability to control +// what the head block is of the L1 and L2 chains. In addition, it enables re-orgs +// to easily be implemented +type fakeChainSource struct { + reorg int // Index of which chain to be operating on + l1head int // Head block of the L1 chain + l2head int // Head block of the L2 chain + l1s [][]eth.L1Node // l1s[reorg] is the L1 chain in that specific re-org configuration + l2s [][]eth.L2Node // l2s[reorg] is the L2 chain in that specific re-org configuration + log log.Logger +} + +func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { + m.log.Trace("L1NodeByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.reorg) + if l1Num > uint64(m.l1head) { + return eth.L1Node{}, ethereum.NotFound + } + return m.l1s[m.reorg][l1Num], nil +} + +func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1Node, error) { + m.log.Trace("L1HeadNode", "l1Head", m.l1head, "reorg", m.reorg) + l := len(m.l1s[m.reorg]) + if l == 0 { + return eth.L1Node{}, ethereum.NotFound + } + return m.l1s[m.reorg][m.l1head], nil +} + +func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) { + m.log.Trace("L2NodeByNumber", "l2Num", l2Num, "l2Head", m.l2head, "reorg", m.reorg) + if len(m.l2s[m.reorg]) == 0 { + panic("bad test, no l2 chain") + } + if l2Num == nil { + return m.l2s[m.reorg][m.l2head], nil + } + i := int(l2Num.Int64()) + if i > m.l2head { + return eth.L2Node{}, ethereum.NotFound + } + return m.l2s[m.reorg][i], nil +} + +func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) { + m.log.Trace("L2NodeByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.reorg) + for i, bl := range m.l2s[m.reorg] { + if bl.Self.Hash == l2Hash { + return m.L2NodeByNumber(ctx, big.NewInt(int64(i))) + } + } + return eth.L2Node{}, ethereum.NotFound +} + +var _ sync.ChainSource = (*fakeChainSource)(nil) + +func (m *fakeChainSource) reorgChains(reorgBase int) { + m.log.Trace("Reorg", "new_reorg", m.reorg+1, "old_reorg", m.reorg) + m.reorg++ + if m.reorg >= len(m.l1s) { + panic("No more re-org chains available") + } + m.l2head = reorgBase +} + +func (m *fakeChainSource) advanceL1() eth.L1Node { + m.log.Trace("Advance L1", "new_head", m.l1head+1, "old_head", m.l1head) + m.l1head++ + if m.l1head >= len(m.l1s[m.reorg]) { + panic("Cannot advance L1 past end of chain") + } + return m.l1s[m.reorg][m.l1head] +} + +func (m *fakeChainSource) l1Head() eth.L1Node { + m.log.Trace("L1 Head", "head", m.l1head) + return m.l1s[m.reorg][m.l1head] +} + +func (m *fakeChainSource) advanceL2() eth.L2Node { + m.log.Trace("Advance L2", "new_head", m.l2head+1, "old_head", m.l2head) + m.l2head++ + if m.l2head >= len(m.l2s[m.reorg]) { + panic("Cannot advance L2 past end of chain") + } + return m.l2s[m.reorg][m.l2head] +} + +// unused +// func (m *fakeChainSource) l2Head() eth.L2Node { +// m.log.Trace("L2 Head", "head", m.l2head) +// return m.l2s[m.reorg][m.l2head] +// } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index ef8d60936a76..a20e397048e5 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -1,139 +1,180 @@ package driver -// import ( -// "context" -// "math/big" -// "strconv" -// "strings" -// "testing" - -// "github.com/ethereum-optimism/optimistic-specs/opnode/eth" -// "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" -// "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" -// "github.com/ethereum/go-ethereum/common" -// "github.com/ethereum/go-ethereum/log" -// "github.com/stretchr/testify/assert" -// "github.com/stretchr/testify/mock" -// ) - -// type testID string - -// func (id testID) ID() eth.BlockID { -// parts := strings.Split(string(id), ":") -// if len(parts) != 2 { -// panic("bad id") -// } -// if len(parts[0]) > 32 { -// panic("test ID hash too long") -// } -// var h common.Hash -// copy(h[:], parts[0]) -// v, err := strconv.ParseUint(parts[1], 0, 64) -// if err != nil { -// panic(err) -// } -// return eth.BlockID{ -// Hash: h, -// Number: v, -// } -// } - -// type testState struct { -// l1Head testID -// l1Base testID -// l2Head testID -// l2Finalized testID - -// l1Window []testID -// l1WindowEnd testID - -// genesisL1 testID -// genesisL2 testID - -// seqWindowSize uint64 -// } - -// func makeState(st testState) *state { -// window := make([]eth.BlockID, len(st.l1Window)) -// for i, id := range st.l1Window { -// window[i] = id.ID() -// } -// return &state{ -// l1Head: st.l1Head.ID(), -// l2Head: st.l2Head.ID(), -// l2Finalized: st.l2Finalized.ID(), -// l1Base: st.l1Base.ID(), -// l1Window: window, -// l1WindowEnd: st.l1WindowEnd.ID(), -// // TODO: improve testing config (test different seq window sizes and non-zero L2 genesis time?) -// Config: rollup.Config{ -// Genesis: rollup.Genesis{ -// L1: st.genesisL1.ID(), -// L2: st.genesisL2.ID(), -// L2Time: 0, -// }, -// BlockTime: 2, -// MaxSequencerTimeDiff: 10, -// SeqWindowSize: st.seqWindowSize, -// L1ChainID: big.NewInt(100), -// FeeRecipientAddress: common.Address{0x0a}, -// BatchInboxAddress: common.Address{0x0b}, -// BatchSenderAddress: common.Address{0x0c}, -// }, -// } -// } - -// type mockDriver struct { -// mock.Mock -// } - -// func (m *mockDriver) requestEngineHead(ctx context.Context) (refL1 eth.BlockID, refL2 eth.BlockID, err error) { -// returnArgs := m.Called(ctx) -// refL1 = returnArgs.Get(0).(eth.BlockID) -// refL2 = returnArgs.Get(1).(eth.BlockID) -// err = returnArgs.Get(2).(error) -// return -// } - -// func (m *mockDriver) findSyncStart(ctx context.Context) (nextL1s []eth.BlockID, refL2 eth.BlockID, err error) { -// returnArgs := m.Called(ctx) -// nextL1s = returnArgs.Get(0).([]eth.BlockID) -// refL2 = returnArgs.Get(1).(eth.BlockID) -// err, _ = returnArgs.Get(2).(error) -// return -// } - -// func (m *mockDriver) driverStep(ctx context.Context, seqWindow []eth.BlockID, refL2 eth.BlockID, finalized eth.BlockID) (l2ID eth.BlockID, err error) { -// returnArgs := m.Called(ctx, seqWindow, refL2, finalized) -// l2ID = returnArgs.Get(0).(eth.BlockID) -// err, _ = returnArgs.Get(1).(error) -// return -// } - -// var _ internalDriver = (*mockDriver)(nil) - -// func TestEngineDriverState_RequestSync(t *testing.T) { -// log := testlog.Logger(t, log.LvlTrace) -// driver := new(mockDriver) -// ctx := context.Background() - -// state := makeState(testState{ -// l1Head: "e:4", -// l1Base: "c:2", -// l2Head: "C:2", -// l2Finalized: "B:1", -// l1Window: []testID{"d:3", "e:4", "c:5"}, // TODO: multiple batches per L1 block -// l1WindowEnd: "c:5", -// genesisL1: "a:0", -// genesisL2: "b:0", -// seqWindowSize: 1, // TODO: test larger sequencing sizes (requires updating test below) -// }) -// driver.On("findSyncStart", ctx).Return([]eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), nil) -// driver.On("driverStep", ctx, []eth.BlockID{testID("d:3").ID()}, testID("C:2").ID(), testID("B:1").ID()).Return(testID("D:3").ID(), nil) - -// l2Updated := state.requestSync(ctx, log, driver) - -// assert.Equal(t, state.l1Head, testID("d:3").ID()) -// assert.Equal(t, state.l2Head, testID("D:3").ID()) -// assert.True(t, l2Updated) -// } +import ( + "context" + "strconv" + "strings" + "testing" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/assert" +) + +type testID string + +func (id testID) ID() eth.BlockID { + parts := strings.Split(string(id), ":") + if len(parts) != 2 { + panic("bad id") + } + if len(parts[0]) > 32 { + panic("test ID hash too long") + } + var h common.Hash + copy(h[:], parts[0]) + v, err := strconv.ParseUint(parts[1], 0, 64) + if err != nil { + panic(err) + } + return eth.BlockID{ + Hash: h, + Number: v, + } +} + +type outputHandlerFn func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) + +func (fn outputHandlerFn) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { + return fn(ctx, l2Head, l2Finalized, l1Window) +} + +type outputArgs struct { + l2Head eth.BlockID + l2Finalized eth.BlockID + l1Window []eth.BlockID +} + +type outputReturnArgs struct { + l2Head eth.BlockID + err error +} + +type stateTestCaseStep struct { + expectedL1Head testID + expectedL2Head testID + expectedWindow []testID + + l1action func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) + l2action func(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) + reorgBase int +} + +func advanceL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { + l1Heads <- src.advanceL1() +} + +func stutterL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { + l1Heads <- src.l1Head() +} + +func reorg__L1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { + src.reorgChains(reorgBase) + l1Heads <- src.l1Head() +} + +func stutterL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { + select { + case <-outputIn: + t.Error("Got a step when no step should have occurred (l1 only advance)") + default: + } +} + +func advanceL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { + args := <-outputIn + assert.Equal(t, int(s.Config.SeqWindowSize), len(args.l1Window), "Invalid L1 window size") + assert.Equal(t, len(expectedWindow), len(args.l1Window), "L1 Window size does not match expectedWindow") + for i := range expectedWindow { + assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") + } + outputReturn <- outputReturnArgs{l2Head: src.advanceL2().Self, err: nil} +} + +type stateTestCase struct { + name string + l1Chains []string + l2Chains []string + steps []stateTestCaseStep + seqWindow int +} + +func (tc *stateTestCase) Run(t *testing.T) { + log := testlog.Logger(t, log.LvlTrace) + chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) + l1headsCh := make(chan eth.L1Node, 10) + outputIn := make(chan outputArgs, 10) + outputReturn := make(chan outputReturnArgs, 10) + outputHandler := func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { + outputIn <- outputArgs{l2Head: l2Head, l2Finalized: l2Finalized, l1Window: l1Window} + r := <-outputReturn + return r.l2Head, r.err + } + config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow)} + state := NewState(log, config, &inputImpl{chainSource: chainSource}, outputHandlerFn(outputHandler)) + defer func() { + assert.NoError(t, state.Close(), "Error closing state") + }() + + err := state.Start(context.Background(), l1headsCh) + assert.NoError(t, err, "Error starting the state object") + + for _, step := range tc.steps { + step.l1action(t, state, chainSource, l1headsCh, step.reorgBase) + <-time.After(5 * time.Millisecond) + step.l2action(t, step.expectedWindow, state, chainSource, outputIn, outputReturn) + <-time.After(5 * time.Millisecond) + + assert.Equal(t, step.expectedL1Head.ID(), state.l1Head, "l1 head") + assert.Equal(t, step.expectedL2Head.ID(), state.l2Head, "l2 head") + } +} + +func TestDriver(t *testing.T) { + cases := []stateTestCase{ + { + name: "Simple extensions", + l1Chains: []string{"abcdefgh"}, + l2Chains: []string{"ABCDEF"}, + seqWindow: 2, + steps: []stateTestCaseStep{ + {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, + {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "c:2", expectedL2Head: "B:1", expectedWindow: []testID{"b:1", "c:2"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "d:3", expectedL2Head: "C:2", expectedWindow: []testID{"c:2", "d:3"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "e:4", expectedL2Head: "D:3", expectedWindow: []testID{"d:3", "e:4"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "f:5", expectedL2Head: "E:4", expectedWindow: []testID{"e:4", "f:5"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "g:6", expectedL2Head: "F:5", expectedWindow: []testID{"f:5", "g:6"}}, + }, + }, + { + name: "Include re-org", + l1Chains: []string{"abcdefg", "abcxyzw"}, + l2Chains: []string{"ABCDEF", "ABCXYZ"}, + seqWindow: 2, + steps: []stateTestCaseStep{ + {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, + {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "c:2", expectedL2Head: "B:1", expectedWindow: []testID{"b:1", "c:2"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "d:3", expectedL2Head: "C:2", expectedWindow: []testID{"c:2", "d:3"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "e:4", expectedL2Head: "D:3", expectedWindow: []testID{"d:3", "e:4"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "f:5", expectedL2Head: "E:4", expectedWindow: []testID{"e:4", "f:5"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "g:6", expectedL2Head: "F:5", expectedWindow: []testID{"f:5", "g:6"}}, + {l1action: reorg__L1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "X:3", expectedWindow: []testID{"x:3", "y:4"}, reorgBase: 2}, + {l1action: stutterL1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "Y:4", expectedWindow: []testID{"y:4", "z:5"}}, + {l1action: stutterL1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, + {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, + {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, tc.Run) + } + +} From b19346bb2c0a2f2c00b7e838d5fa27bc6401c7de Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Mar 2022 14:39:15 -0800 Subject: [PATCH 279/585] ref impl: Driver cleanup --- opnode/rollup/derive/payload_attributes.go | 2 +- opnode/rollup/driver/state.go | 81 ++++++++++++---------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 444b1198ce21..b0afa25c0e5d 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -250,7 +250,7 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R // Repeating the latest randomness of L1 might not be ideal. randomnessSeed := l2.Bytes32(l1Info.MixDigest()) - // Collect all L2 batches, the bathes may be out-of-order, or possibly missing. + // Collect all L2 batches, the batches may be out-of-order, or possibly missing. l2Blocks := make(map[uint64]*l2.PayloadAttributes) highestSeenTimestamp := l1Info.Time() for _, batch := range seqWindow { diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 96abd485619a..193d4c94e44c 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -39,34 +39,6 @@ type state struct { done chan struct{} } -// l1WindowEnd returns the last block that should be used as `base` to L1ChainWindow -// This is either the last block of the window, or the L1 base block if the window is not populated -func (s *state) l1WindowEnd() eth.BlockID { - if len(s.l1Window) == 0 { - return s.l1Base - } - return s.l1Window[len(s.l1Window)-1] -} - -// TODO: Split this function into populate window & SequencingWindow -func (s *state) getNextWindow(ctx context.Context) ([]eth.BlockID, error) { - - if uint64(len(s.l1Window)) < s.Config.SeqWindowSize { - s.log.Trace("Pulling chain window from L1", "cached_size", len(s.l1Window), "window_end", s.l1WindowEnd()) - nexts, err := s.input.L1ChainWindow(ctx, s.l1WindowEnd()) - if err != nil { - return nil, err - } - s.log.Trace("Window from l1", "nexts", nexts) - s.l1Window = append(s.l1Window, nexts...) - } - l := uint64(len(s.l1Window)) - if l > s.Config.SeqWindowSize { - l = s.Config.SeqWindowSize - } - return s.l1Window[:l], nil -} - func NewState(log log.Logger, config rollup.Config, input inputInterface, output outputInterface) *state { return &state{ Config: config, @@ -101,6 +73,36 @@ func (s *state) Close() error { return nil } +// l1WindowEnd returns the last block that should be used as `base` to L1ChainWindow +// This is either the last block of the window, or the L1 base block if the window is not populated +func (s *state) l1WindowEnd() eth.BlockID { + if len(s.l1Window) == 0 { + return s.l1Base + } + return s.l1Window[len(s.l1Window)-1] +} + +// sequencingWindow returns the next sequencing window and true if it exists, (nil, false) if +// there are not enough saved blocks. +func (s *state) sequencingWindow() ([]eth.BlockID, bool) { + if len(s.l1Window) < int(s.Config.SeqWindowSize) { + return nil, false + } + return s.l1Window[:int(s.Config.SeqWindowSize)], true +} + +// extendL1Window extends the cached L1 window by pulling blocks from L1. +// It starts just after `l1WindowEnd()` +func (s *state) extendL1Window(ctx context.Context) error { + s.log.Trace("Extending the cached window from L1", "cached_size", len(s.l1Window), "window_end", s.l1WindowEnd()) + nexts, err := s.input.L1ChainWindow(ctx, s.l1WindowEnd()) + if err != nil { + return err + } + s.l1Window = append(s.l1Window, nexts...) + return nil +} + func (s *state) handleReorg(ctx context.Context, head eth.L1Node) error { log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", head.Parent, "new_l1_head", head.Self) nextL2Head, err := s.input.L2Head(ctx) @@ -186,17 +188,23 @@ func (s *state) loop() { cancel() case <-stepRequest: - window, err := s.getNextWindow(ctx) - if err != nil { - panic(err) + log := s.log.New("action", "step_request", "cached_window_len", len(s.l1Window), "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Base", s.l1Base) + // Extended cached window if we do not have enough saved blocks + if len(s.l1Window) < int(s.Config.SeqWindowSize) { + err := s.extendL1Window(context.Background()) + log.Trace("Extended window", "new_cached_window_len", len(s.l1Window)) + if err != nil { + panic(err) + } } - s.log.Trace("Step request", "window", window) - if len(window) == int(s.Config.SeqWindowSize) { - s.log.Trace("Running step") + + // Get next window (& ensure that it exists) + if window, ok := s.sequencingWindow(); ok { + log.Trace("Running step") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) newL2Head, err := s.output.step(ctx, s.l2Head, s.l2Finalized, window) cancel() - s.log.Trace("step output", "head", newL2Head, "err", err) + log.Trace("Ran step", "head", newL2Head, "err", err) if err != nil { panic(err) } @@ -204,9 +212,8 @@ func (s *state) loop() { s.l1Base = s.l1Window[0] s.l1Window = s.l1Window[1:] // TODO: l2Finalized/l2Safe. - } else { - s.log.Trace("Not enough saved blocks to run step") + log.Trace("Not enough saved blocks to run step") } } From f9ac55fa623816e0f1e16fa6a54fd113db0399fe Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Mar 2022 15:14:13 -0800 Subject: [PATCH 280/585] ref impl: More logging --- opnode/rollup/driver/state.go | 1 + opnode/rollup/driver/step.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 193d4c94e44c..5e295b55182f 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -189,6 +189,7 @@ func (s *state) loop() { case <-stepRequest: log := s.log.New("action", "step_request", "cached_window_len", len(s.l1Window), "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Base", s.l1Base) + log.Trace("Got step request") // Extended cached window if we do not have enough saved blocks if len(s.l1Window) < int(s.Config.SeqWindowSize) { err := s.extendL1Window(context.Background()) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index eeb52e2b073c..ae25e7becbe5 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -108,7 +108,7 @@ func AddBlock(ctx context.Context, logger log.Logger, rpc DriverAPI, } logger = logger.New("derived_l2", payload.ID()) - logger.Info("derived full block") + logger.Info("derived full block", "l2Parent", l2Parent, "attrs", attrs, "payload", payload) err = l2.ExecutePayload(ctx, rpc, payload) if err != nil { From 68b4f20cb64ccc601b8dcda23de8829a6af6cae7 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Mar 2022 15:48:38 -0800 Subject: [PATCH 281/585] ref impl: Add new driver testcase This test case sends a bunch of step requests to the driver loop at once. --- opnode/rollup/driver/state_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index a20e397048e5..d30d26106b2d 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -72,6 +72,16 @@ func stutterL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1 l1Heads <- src.l1Head() } +func stutterAdvance(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { + l1Heads <- src.l1Head() + l1Heads <- src.l1Head() + l1Heads <- src.l1Head() + l1Heads <- src.advanceL1() + l1Heads <- src.l1Head() + l1Heads <- src.l1Head() + l1Heads <- src.l1Head() +} + func reorg__L1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { src.reorgChains(reorgBase) l1Heads <- src.l1Head() @@ -171,6 +181,21 @@ func TestDriver(t *testing.T) { {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, }, }, + { + name: "Simple extensions with multi-step", + l1Chains: []string{"abcdefgh"}, + l2Chains: []string{"ABCDEF"}, + seqWindow: 2, + steps: []stateTestCaseStep{ + {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, + {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, + {l1action: stutterAdvance, l2action: advanceL2, expectedL1Head: "c:2", expectedL2Head: "B:1", expectedWindow: []testID{"b:1", "c:2"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "d:3", expectedL2Head: "C:2", expectedWindow: []testID{"c:2", "d:3"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "e:4", expectedL2Head: "D:3", expectedWindow: []testID{"d:3", "e:4"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "f:5", expectedL2Head: "E:4", expectedWindow: []testID{"e:4", "f:5"}}, + {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "g:6", expectedL2Head: "F:5", expectedWindow: []testID{"f:5", "g:6"}}, + }, + }, } for _, tc := range cases { From a92606df3785706b4c591ebc141d995c12cb33de Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Mar 2022 15:50:25 -0800 Subject: [PATCH 282/585] ref impl: Fix bug in driver.step The step function was returning the previous L2 head, not the L2 block that it submitted to the L2 node. As such, the driver relied on the out of date L2 head and when it got another L1 head, created a second L2 block with the same number (but with deposits referring to a higher L2 block). As such it was causing the block execution to (properly) fail. --- opnode/rollup/driver/step.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index ae25e7becbe5..17b1446b1301 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -86,7 +86,7 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e last := l2Head for i, attrs := range attrsList { - last, err := AddBlock(ctx, logger, d.rpc, last, l2Finalized.Hash, attrs) + last, err = AddBlock(ctx, logger, d.rpc, last, l2Finalized.Hash, attrs) if err != nil { return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %v", i, len(attrsList), epoch, err) } From e666a50c063fa624d389ca8ae62a91ba91527e7d Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 7 Mar 2022 14:08:13 -0800 Subject: [PATCH 283/585] ref impl: Handle re-orgs in the rollup driver The driver was not using sync.FindSyncStart and thus not walking back correctly in the case of an L2 reorg. This also brings more of the logic into a single loop. --- opnode/rollup/driver/driver.go | 6 ++ opnode/rollup/driver/state.go | 124 +++++++++++++-------------------- 2 files changed, 56 insertions(+), 74 deletions(-) diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 01cdb33ee3cf..610407c4336a 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -17,6 +17,7 @@ type Driver struct { func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger) *Driver { input := &inputImpl{ chainSource: sync.NewChainSource(l1, l2, &cfg.Genesis), + genesis: &cfg.Genesis, } output := &outputImpl{ Config: cfg, @@ -38,6 +39,7 @@ func (d *Driver) Close() error { type inputImpl struct { chainSource sync.ChainSource + genesis *rollup.Genesis } func (i *inputImpl) L1Head(ctx context.Context) (eth.L1Node, error) { @@ -52,3 +54,7 @@ func (i *inputImpl) L2Head(ctx context.Context) (eth.L2Node, error) { func (i *inputImpl) L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) { return sync.FindL1Range(ctx, i.chainSource, base) } + +func (i *inputImpl) SafeL2Head(ctx context.Context) (eth.L2Node, error) { + return sync.FindSafeL2Head(ctx, i.chainSource, i.genesis) +} diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 5e295b55182f..c7571b31f5fc 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -13,6 +13,8 @@ type inputInterface interface { L1Head(ctx context.Context) (eth.L1Node, error) L2Head(ctx context.Context) (eth.L2Node, error) L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) + // SafeL2Head is the L2 Head found via the sync algorithm + SafeL2Head(ctx context.Context) (eth.L2Node, error) } type outputInterface interface { @@ -73,8 +75,8 @@ func (s *state) Close() error { return nil } -// l1WindowEnd returns the last block that should be used as `base` to L1ChainWindow -// This is either the last block of the window, or the L1 base block if the window is not populated +// l1WindowEnd returns the last block that should be used as `base` to L1ChainWindow. +// This is either the last block of the window, or the L1 base block if the window is not populated. func (s *state) l1WindowEnd() eth.BlockID { if len(s.l1Window) == 0 { return s.l1Base @@ -82,17 +84,8 @@ func (s *state) l1WindowEnd() eth.BlockID { return s.l1Window[len(s.l1Window)-1] } -// sequencingWindow returns the next sequencing window and true if it exists, (nil, false) if -// there are not enough saved blocks. -func (s *state) sequencingWindow() ([]eth.BlockID, bool) { - if len(s.l1Window) < int(s.Config.SeqWindowSize) { - return nil, false - } - return s.l1Window[:int(s.Config.SeqWindowSize)], true -} - // extendL1Window extends the cached L1 window by pulling blocks from L1. -// It starts just after `l1WindowEnd()` +// It starts just after `s.l1WindowEnd()`. func (s *state) extendL1Window(ctx context.Context) error { s.log.Trace("Extending the cached window from L1", "cached_size", len(s.l1Window), "window_end", s.l1WindowEnd()) nexts, err := s.input.L1ChainWindow(ctx, s.l1WindowEnd()) @@ -103,52 +96,13 @@ func (s *state) extendL1Window(ctx context.Context) error { return nil } -func (s *state) handleReorg(ctx context.Context, head eth.L1Node) error { - log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", head.Parent, "new_l1_head", head.Self) - nextL2Head, err := s.input.L2Head(ctx) - if err != nil { - log.Error("Could not get new L2 head when trying to handle a re-org", "err", err) - // TODO: How do you handle this error - it seems to break everything - return err - } - s.l1Head = head.Parent - s.l1Window = nil - s.l1Base = nextL2Head.L1Parent - s.l2Head = nextL2Head.Self - return nil -} - -// newL1Head takes the new head and updates the internal state to reflect the new chain state. -// Returns true if it is a re-org, false otherwise (linear extension, no-op, or other simple case). -// If there is a re-org, this updates the internal state to handle the re-org. -// Note that `ctx` is only used in a re-org and that handling a re-org may take a long period of time. -// The L2 engine is not modified in this function. -func (s *state) newL1Head(ctx context.Context, head eth.L1Node) (bool, error) { - // Already have head - if s.l1Head == head.Self { - log.Trace("Received L1 head signal that is the same as the current head", "l1_head", head.Self) - return false, nil - } - // Re-org (maybe also a skip) - if s.l1Head != head.Parent { - err := s.handleReorg(ctx, head) - if err != nil { - return false, err - } - } - // Linear extension - s.l1Head = head.Self - // Check if the new block extends the L1 window and save it if so. - if s.l1WindowEnd() == head.Parent { - // // don't buffer more than 20 sequencing windows (TBD, sanity limit) - // if uint64(len(e.l1Next)) < e.Config.SeqWindowSize*20 { - // e.l1Next = append(e.l1Next, l1HeadSig.Self) - // } - s.l1Window = append(s.l1Window, head.Self) +// sequencingWindow returns the next sequencing window and true if it exists, (nil, false) if +// there are not enough saved blocks. +func (s *state) sequencingWindow() ([]eth.BlockID, bool) { + if len(s.l1Window) < int(s.Config.SeqWindowSize) { + return nil, false } - - return false, nil - + return s.l1Window[:int(s.Config.SeqWindowSize)], true } func (s *state) loop() { @@ -176,45 +130,67 @@ func (s *state) loop() { // case <-l2Poll.C: case <-s.done: return - case l1HeadSig := <-s.l1Heads: - s.log.Trace("L1 Head Update", "new_head", l1HeadSig.Self) - // Set a long timeout because the timeout is for running sync.L2Head - ctx, cancel := context.WithTimeout(ctx, 30*time.Second) - _, err := s.newL1Head(ctx, l1HeadSig) - if err != nil { - panic(err) + case newL1Head := <-s.l1Heads: + s.log.Trace("Received new L1 Head", "new_head", newL1Head.Self, "old_head", s.l1Head) + // Check if we have a stutter step. May be due to a L1 Poll operation. + if s.l1Head == newL1Head.Self { + log.Trace("Received L1 head signal that is the same as the current head", "l1_head", newL1Head.Self) + continue + } + + // Typically get linear extension, but if not, handle a re-org + if s.l1Head == newL1Head.Parent { + s.log.Trace("Linear extension") + s.l1Head = newL1Head.Self + if s.l1WindowEnd() == newL1Head.Parent { + s.l1Window = append(s.l1Window, newL1Head.Self) + } + } else { + s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.Parent, "new_l1_head", newL1Head.Self) + nextL2Head, err := s.input.SafeL2Head(ctx) + if err != nil { + s.log.Error("Could not get new L2 head when trying to handle a re-org", "err", err) + continue + } + s.l1Head = newL1Head.Self + s.l1Window = nil + s.l1Base = nextL2Head.L1Parent + s.l2Head = nextL2Head.Self } requestStep() - cancel() case <-stepRequest: - log := s.log.New("action", "step_request", "cached_window_len", len(s.l1Window), "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Base", s.l1Base) - log.Trace("Got step request") - // Extended cached window if we do not have enough saved blocks + s.log.Trace("Got step request") + // Extend cached window if we do not have enough saved blocks if len(s.l1Window) < int(s.Config.SeqWindowSize) { err := s.extendL1Window(context.Background()) - log.Trace("Extended window", "new_cached_window_len", len(s.l1Window)) if err != nil { - panic(err) + s.log.Error("Could not extend the cached L1 window", "err", err, "l1Head", s.l1Head, "l1Base", s.l1Base, "window_end", s.l1WindowEnd()) + continue } } // Get next window (& ensure that it exists) if window, ok := s.sequencingWindow(); ok { - log.Trace("Running step") + s.log.Trace("Have enough cached blocks to run step.") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) newL2Head, err := s.output.step(ctx, s.l2Head, s.l2Finalized, window) cancel() - log.Trace("Ran step", "head", newL2Head, "err", err) if err != nil { - panic(err) + s.log.Error("Error in running the output step.", "err", err, "l2Head", s.l2Head, "l2Finalized", s.l2Finalized, "window", window) + continue } s.l2Head = newL2Head s.l1Base = s.l1Window[0] s.l1Window = s.l1Window[1:] // TODO: l2Finalized/l2Safe. } else { - log.Trace("Not enough saved blocks to run step") + s.log.Trace("Not enough cached blocks to run step", "cached_window_len", len(s.l1Window)) + } + + // Immediately run next step if we have enough blocks. + if s.l1Head.Number-s.l1Base.Number >= s.Config.SeqWindowSize { + requestStep() } } From 47b832a19bb8a5f90932e159bf94e25e2f09896e Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 7 Mar 2022 14:09:39 -0800 Subject: [PATCH 284/585] ref impl: Fix rollup driver tests This re-orgs in the correct spot. The fake chain now re-orgs L1 and L2 separately. This is done such that the sync.FindSyncStart can be ran on the new L1 and old L2. The other option would be to have the fakeChainSource fake out the creation of the L2 chain. As it stands, the fakeChainSource expects a certain pattern of blocks. --- opnode/rollup/driver/fake_chain.go | 94 +++++++++++++++++++----------- opnode/rollup/driver/state_test.go | 54 ++++++++++------- 2 files changed, 93 insertions(+), 55 deletions(-) diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 10622e51f651..844ef035c72b 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -9,9 +9,17 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" ) +func fakeGenesis(l1 rune, l2 rune, l2offset int) rollup.Genesis { + return rollup.Genesis{ + L1: fakeID(l1, 0), + L2: fakeID(l2, uint64(l2offset)), + } +} + func fakeID(id rune, num uint64) eth.BlockID { var h common.Hash copy(h[:], string(id)) @@ -72,49 +80,50 @@ func NewFakeChainSource(l1 []string, l2 []string, log log.Logger) *fakeChainSour // what the head block is of the L1 and L2 chains. In addition, it enables re-orgs // to easily be implemented type fakeChainSource struct { - reorg int // Index of which chain to be operating on - l1head int // Head block of the L1 chain - l2head int // Head block of the L2 chain - l1s [][]eth.L1Node // l1s[reorg] is the L1 chain in that specific re-org configuration - l2s [][]eth.L2Node // l2s[reorg] is the L2 chain in that specific re-org configuration - log log.Logger + l1reorg int // Index of the L1 chain to be operating on + l2reorg int // Index of the L2 chain to be operating on + l1head int // Head block of the L1 chain + l2head int // Head block of the L2 chain + l1s [][]eth.L1Node // l1s[reorg] is the L1 chain in that specific re-org configuration + l2s [][]eth.L2Node // l2s[reorg] is the L2 chain in that specific re-org configuration + log log.Logger } func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { - m.log.Trace("L1NodeByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.reorg) + m.log.Trace("L1NodeByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.l1reorg) if l1Num > uint64(m.l1head) { return eth.L1Node{}, ethereum.NotFound } - return m.l1s[m.reorg][l1Num], nil + return m.l1s[m.l1reorg][l1Num], nil } func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1Node, error) { - m.log.Trace("L1HeadNode", "l1Head", m.l1head, "reorg", m.reorg) - l := len(m.l1s[m.reorg]) + m.log.Trace("L1HeadNode", "l1Head", m.l1head, "reorg", m.l1reorg) + l := len(m.l1s[m.l1reorg]) if l == 0 { return eth.L1Node{}, ethereum.NotFound } - return m.l1s[m.reorg][m.l1head], nil + return m.l1s[m.l1reorg][m.l1head], nil } func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) { - m.log.Trace("L2NodeByNumber", "l2Num", l2Num, "l2Head", m.l2head, "reorg", m.reorg) - if len(m.l2s[m.reorg]) == 0 { + m.log.Trace("L2NodeByNumber", "l2Num", l2Num, "l2Head", m.l2head, "reorg", m.l2reorg) + if len(m.l2s[m.l2reorg]) == 0 { panic("bad test, no l2 chain") } if l2Num == nil { - return m.l2s[m.reorg][m.l2head], nil + return m.l2s[m.l2reorg][m.l2head], nil } i := int(l2Num.Int64()) if i > m.l2head { return eth.L2Node{}, ethereum.NotFound } - return m.l2s[m.reorg][i], nil + return m.l2s[m.l2reorg][i], nil } func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) { - m.log.Trace("L2NodeByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.reorg) - for i, bl := range m.l2s[m.reorg] { + m.log.Trace("L2NodeByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.l2reorg) + for i, bl := range m.l2s[m.l2reorg] { if bl.Self.Hash == l2Hash { return m.L2NodeByNumber(ctx, big.NewInt(int64(i))) } @@ -124,39 +133,54 @@ func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) var _ sync.ChainSource = (*fakeChainSource)(nil) -func (m *fakeChainSource) reorgChains(reorgBase int) { - m.log.Trace("Reorg", "new_reorg", m.reorg+1, "old_reorg", m.reorg) - m.reorg++ - if m.reorg >= len(m.l1s) { +func (m *fakeChainSource) reorgL1() { + m.log.Trace("Reorg L1", "new_reorg", m.l1reorg+1, "old_reorg", m.l1reorg) + m.l1reorg++ + if m.l1reorg >= len(m.l1s) { + panic("No more re-org chains available") + } +} + +func (m *fakeChainSource) reorgL2() { + m.log.Trace("Reorg L2", "new_reorg", m.l2reorg+1, "old_reorg", m.l2reorg) + m.l2reorg++ + if m.l2reorg >= len(m.l2s) { panic("No more re-org chains available") } - m.l2head = reorgBase +} + +func (m *fakeChainSource) setL2Head(head int) eth.L2Node { + m.log.Trace("Set L2 head", "new_head", head, "old_head", m.l2head) + m.l2head = head + if m.l2head >= len(m.l2s[m.l2reorg]) { + panic("Cannot advance L2 past end of chain") + } + return m.l2s[m.l2reorg][m.l2head] } func (m *fakeChainSource) advanceL1() eth.L1Node { m.log.Trace("Advance L1", "new_head", m.l1head+1, "old_head", m.l1head) m.l1head++ - if m.l1head >= len(m.l1s[m.reorg]) { + if m.l1head >= len(m.l1s[m.l1reorg]) { panic("Cannot advance L1 past end of chain") } - return m.l1s[m.reorg][m.l1head] + return m.l1s[m.l1reorg][m.l1head] } func (m *fakeChainSource) l1Head() eth.L1Node { m.log.Trace("L1 Head", "head", m.l1head) - return m.l1s[m.reorg][m.l1head] -} - -func (m *fakeChainSource) advanceL2() eth.L2Node { - m.log.Trace("Advance L2", "new_head", m.l2head+1, "old_head", m.l2head) - m.l2head++ - if m.l2head >= len(m.l2s[m.reorg]) { - panic("Cannot advance L2 past end of chain") - } - return m.l2s[m.reorg][m.l2head] + return m.l1s[m.l1reorg][m.l1head] } -// unused +// Unused functions +// func (m *fakeChainSource) advanceL2() eth.L2Node { +// m.log.Trace("Advance L2", "new_head", m.l2head+1, "old_head", m.l2head) +// m.l2head++ +// if m.l2head >= len(m.l2s[m.l1reorg]) { +// panic("Cannot advance L2 past end of chain") +// } +// return m.l2s[m.l1reorg][m.l2head] +// } // func (m *fakeChainSource) l2Head() eth.L2Node { // m.log.Trace("L2 Head", "head", m.l2head) // return m.l2s[m.reorg][m.l2head] diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index d30d26106b2d..c68c216a5b04 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -59,20 +59,20 @@ type stateTestCaseStep struct { expectedL2Head testID expectedWindow []testID - l1action func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) - l2action func(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) - reorgBase int + l1action func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) + l2action func(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) + reorg bool } -func advanceL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { +func advanceL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) { l1Heads <- src.advanceL1() } -func stutterL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { +func stutterL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) { l1Heads <- src.l1Head() } -func stutterAdvance(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { +func stutterAdvance(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) { l1Heads <- src.l1Head() l1Heads <- src.l1Head() l1Heads <- src.l1Head() @@ -82,11 +82,6 @@ func stutterAdvance(t *testing.T, s *state, src *fakeChainSource, l1Heads chan e l1Heads <- src.l1Head() } -func reorg__L1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node, reorgBase int) { - src.reorgChains(reorgBase) - l1Heads <- src.l1Head() -} - func stutterL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { select { case <-outputIn: @@ -102,7 +97,18 @@ func advanceL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo for i := range expectedWindow { assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") } - outputReturn <- outputReturnArgs{l2Head: src.advanceL2().Self, err: nil} + outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1).Self, err: nil} +} + +func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { + args := <-outputIn + assert.Equal(t, int(s.Config.SeqWindowSize), len(args.l1Window), "Invalid L1 window size") + assert.Equal(t, len(expectedWindow), len(args.l1Window), "L1 Window size does not match expectedWindow") + for i := range expectedWindow { + assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") + } + src.reorgL2() + outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1).Self, err: nil} } type stateTestCase struct { @@ -111,21 +117,23 @@ type stateTestCase struct { l2Chains []string steps []stateTestCaseStep seqWindow int + genesis rollup.Genesis } func (tc *stateTestCase) Run(t *testing.T) { log := testlog.Logger(t, log.LvlTrace) chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) l1headsCh := make(chan eth.L1Node, 10) - outputIn := make(chan outputArgs, 10) - outputReturn := make(chan outputReturnArgs, 10) + // Unbuffered channels to force a sync point between + outputIn := make(chan outputArgs) + outputReturn := make(chan outputReturnArgs) outputHandler := func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { outputIn <- outputArgs{l2Head: l2Head, l2Finalized: l2Finalized, l1Window: l1Window} r := <-outputReturn return r.l2Head, r.err } - config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow)} - state := NewState(log, config, &inputImpl{chainSource: chainSource}, outputHandlerFn(outputHandler)) + config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis} + state := NewState(log, config, &inputImpl{chainSource: chainSource, genesis: &tc.genesis}, outputHandlerFn(outputHandler)) defer func() { assert.NoError(t, state.Close(), "Error closing state") }() @@ -134,7 +142,10 @@ func (tc *stateTestCase) Run(t *testing.T) { assert.NoError(t, err, "Error starting the state object") for _, step := range tc.steps { - step.l1action(t, state, chainSource, l1headsCh, step.reorgBase) + if step.reorg { + chainSource.reorgL1() + } + step.l1action(t, state, chainSource, l1headsCh) <-time.After(5 * time.Millisecond) step.l2action(t, step.expectedWindow, state, chainSource, outputIn, outputReturn) <-time.After(5 * time.Millisecond) @@ -151,6 +162,7 @@ func TestDriver(t *testing.T) { l1Chains: []string{"abcdefgh"}, l2Chains: []string{"ABCDEF"}, seqWindow: 2, + genesis: fakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, @@ -162,10 +174,11 @@ func TestDriver(t *testing.T) { }, }, { - name: "Include re-org", + name: "Reorg", l1Chains: []string{"abcdefg", "abcxyzw"}, l2Chains: []string{"ABCDEF", "ABCXYZ"}, seqWindow: 2, + genesis: fakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, @@ -174,7 +187,7 @@ func TestDriver(t *testing.T) { {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "e:4", expectedL2Head: "D:3", expectedWindow: []testID{"d:3", "e:4"}}, {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "f:5", expectedL2Head: "E:4", expectedWindow: []testID{"e:4", "f:5"}}, {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "g:6", expectedL2Head: "F:5", expectedWindow: []testID{"f:5", "g:6"}}, - {l1action: reorg__L1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "X:3", expectedWindow: []testID{"x:3", "y:4"}, reorgBase: 2}, + {l1action: stutterL1, l2action: reorg__L2, expectedL1Head: "w:6", expectedL2Head: "X:3", expectedWindow: []testID{"x:3", "y:4"}, reorg: true}, {l1action: stutterL1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "Y:4", expectedWindow: []testID{"y:4", "z:5"}}, {l1action: stutterL1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, @@ -182,10 +195,11 @@ func TestDriver(t *testing.T) { }, }, { - name: "Simple extensions with multi-step", + name: "Simple extensions with multi-step stutter", l1Chains: []string{"abcdefgh"}, l2Chains: []string{"ABCDEF"}, seqWindow: 2, + genesis: fakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, From 6a572763bac99383a569eb4b6aa382f5db244c98 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 7 Mar 2022 15:16:04 -0800 Subject: [PATCH 285/585] ref impl: Cleanup comments Small code/comment fixes. --- opnode/rollup/driver/state.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index c7571b31f5fc..f51ea97f7c9d 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -149,7 +149,7 @@ func (s *state) loop() { s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.Parent, "new_l1_head", newL1Head.Self) nextL2Head, err := s.input.SafeL2Head(ctx) if err != nil { - s.log.Error("Could not get new L2 head when trying to handle a re-org", "err", err) + s.log.Error("Could not get new safe L2 head when trying to handle a re-org", "err", err) continue } s.l1Head = newL1Head.Self @@ -157,8 +157,10 @@ func (s *state) loop() { s.l1Base = nextL2Head.L1Parent s.l2Head = nextL2Head.Self } - requestStep() - + // Run step if we are able to + if s.l1Head.Number-s.l1Base.Number >= s.Config.SeqWindowSize { + requestStep() + } case <-stepRequest: s.log.Trace("Got step request") // Extend cached window if we do not have enough saved blocks @@ -183,7 +185,7 @@ func (s *state) loop() { s.l2Head = newL2Head s.l1Base = s.l1Window[0] s.l1Window = s.l1Window[1:] - // TODO: l2Finalized/l2Safe. + // TODO: l2Finalized } else { s.log.Trace("Not enough cached blocks to run step", "cached_window_len", len(s.l1Window)) } From 4deacf89486f2271d2bd40982960204f63ad558c Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 7 Mar 2022 15:44:01 -0800 Subject: [PATCH 286/585] ref impl: Rename eth L1/L2 Node struct It is now called BlockRef to avoid confusion with ethereum nodes. --- opnode/eth/heads.go | 4 +-- opnode/eth/id.go | 16 ++++----- opnode/node/node.go | 8 ++--- opnode/rollup/derive/invert.go | 12 +++---- opnode/rollup/driver/driver.go | 8 ++--- opnode/rollup/driver/fake_chain.go | 54 +++++++++++++++--------------- opnode/rollup/driver/state.go | 14 ++++---- opnode/rollup/driver/state_test.go | 10 +++--- opnode/rollup/sync/reference.go | 26 +++++++------- opnode/rollup/sync/start.go | 20 +++++------ opnode/rollup/sync/start_test.go | 30 ++++++++--------- 11 files changed, 101 insertions(+), 101 deletions(-) diff --git a/opnode/eth/heads.go b/opnode/eth/heads.go index 2776d1f38fa7..d9c6ad2b35de 100644 --- a/opnode/eth/heads.go +++ b/opnode/eth/heads.go @@ -9,7 +9,7 @@ import ( ) // HeadSignalFn is used as callback function to accept head-signals -type HeadSignalFn func(sig L1Node) +type HeadSignalFn func(sig L1BlockRef) type NewHeadSource interface { SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) @@ -34,7 +34,7 @@ func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) ( if height > 0 { parent = BlockID{Hash: header.ParentHash, Number: height - 1} } - fn(L1Node{Parent: parent, Self: self}) + fn(L1BlockRef{Parent: parent, Self: self}) case err := <-sub.Err(): return err case <-ctx.Done(): diff --git a/opnode/eth/id.go b/opnode/eth/id.go index bd795d181496..359726727bd4 100644 --- a/opnode/eth/id.go +++ b/opnode/eth/id.go @@ -21,33 +21,33 @@ func (id BlockID) TerminalString() string { return fmt.Sprintf("%s:%d", id.Hash.TerminalString(), id.Number) } -type L2Node struct { +type L2BlockRef struct { Self BlockID - L2Parent BlockID - L1Parent BlockID + Parent BlockID + L1Origin BlockID } -func (id L2Node) String() string { +func (id L2BlockRef) String() string { return fmt.Sprintf("%s:%d", id.Self.Hash.String(), id.Self.Number) } // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. -func (id L2Node) TerminalString() string { +func (id L2BlockRef) TerminalString() string { return fmt.Sprintf("%s:%d", id.Self.Hash.TerminalString(), id.Self.Number) } -type L1Node struct { +type L1BlockRef struct { Self BlockID Parent BlockID } -func (id L1Node) String() string { +func (id L1BlockRef) String() string { return fmt.Sprintf("%s:%d", id.Self.Hash.String(), id.Self.Number) } // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. -func (id L1Node) TerminalString() string { +func (id L1BlockRef) TerminalString() string { return fmt.Sprintf("%s:%d", id.Self.Hash.TerminalString(), id.Self.Number) } diff --git a/opnode/node/node.go b/opnode/node/node.go index 5f3a94cfa27b..2ba804c404fa 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -119,7 +119,7 @@ func (c *OpNode) Start(ctx context.Context) error { c.log.Info("Fetching rollup starting point") - // Feed of eth.L1Node + // Feed of eth.L1BlockRef var l1HeadsFeed event.Feed c.log.Info("Attaching execution engine(s)") @@ -128,7 +128,7 @@ func (c *OpNode) Start(ctx context.Context) error { reqCtx, reqCancel := context.WithTimeout(ctx, time.Second*10) // driver subscribes to L1 head changes - l1SubCh := make(chan eth.L1Node, 10) + l1SubCh := make(chan eth.L1BlockRef, 10) l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine err := eng.Start(reqCtx, l1SubCh) @@ -144,14 +144,14 @@ func (c *OpNode) Start(ctx context.Context) error { if err != nil { c.log.Warn("resubscribing after failed L1 subscription", "err", err) } - return eth.WatchHeadChanges(context.Background(), c.l1Source, func(sig eth.L1Node) { + return eth.WatchHeadChanges(context.Background(), c.l1Source, func(sig eth.L1BlockRef) { l1HeadsFeed.Send(sig) }) }) handleUnsubscribe(l1HeadsSub, "l1 heads subscription failed") // subscribe to L1 heads for info - l1Heads := make(chan eth.L1Node, 10) + l1Heads := make(chan eth.L1BlockRef, 10) l1HeadsFeed.Subscribe(l1Heads) c.log.Info("Start-up complete!") diff --git a/opnode/rollup/derive/invert.go b/opnode/rollup/derive/invert.go index cb8a531e9ef5..58c1b01a729d 100644 --- a/opnode/rollup/derive/invert.go +++ b/opnode/rollup/derive/invert.go @@ -36,24 +36,24 @@ type Block interface { } // BlockReferences takes a L2 block and determines which L1 block it was derived from, its L2 parent id, and its own id. -func BlockReferences(l2Block Block, genesis *rollup.Genesis) (eth.L2Node, error) { +func BlockReferences(l2Block Block, genesis *rollup.Genesis) (eth.L2BlockRef, error) { self := eth.BlockID{Hash: l2Block.Hash(), Number: l2Block.NumberU64()} if self.Number <= genesis.L2.Number { if self.Hash != genesis.L2.Hash { - return eth.L2Node{}, fmt.Errorf("unexpected L2 genesis block: %s, expected %s", self, genesis.L2) + return eth.L2BlockRef{}, fmt.Errorf("unexpected L2 genesis block: %s, expected %s", self, genesis.L2) } - return eth.L2Node{Self: self, L1Parent: genesis.L1}, nil + return eth.L2BlockRef{Self: self, L1Origin: genesis.L1}, nil } l2Parent := eth.BlockID{Hash: l2Block.ParentHash(), Number: l2Block.NumberU64() - 1} txs := l2Block.Transactions() if len(txs) == 0 || txs[0].Type() != types.DepositTxType { - return eth.L2Node{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", l2Block.Hash()) + return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", l2Block.Hash()) } l1Number, _, _, l1Hash, err := L1InfoDepositTxData(txs[0].Data()) if err != nil { - return eth.L2Node{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) + return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) } - return eth.L2Node{Self: self, L2Parent: l2Parent, L1Parent: eth.BlockID{Hash: l1Hash, Number: l1Number}}, nil + return eth.L2BlockRef{Self: self, Parent: l2Parent, L1Origin: eth.BlockID{Hash: l1Hash, Number: l1Number}}, nil } diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 610407c4336a..51db4d9e4f20 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -30,7 +30,7 @@ func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger) *D } } -func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.L1Node) error { +func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error { return d.s.Start(ctx, l1Heads) } func (d *Driver) Close() error { @@ -42,11 +42,11 @@ type inputImpl struct { genesis *rollup.Genesis } -func (i *inputImpl) L1Head(ctx context.Context) (eth.L1Node, error) { +func (i *inputImpl) L1Head(ctx context.Context) (eth.L1BlockRef, error) { return i.chainSource.L1HeadNode(ctx) } -func (i *inputImpl) L2Head(ctx context.Context) (eth.L2Node, error) { +func (i *inputImpl) L2Head(ctx context.Context) (eth.L2BlockRef, error) { return i.chainSource.L2NodeByNumber(ctx, nil) } @@ -55,6 +55,6 @@ func (i *inputImpl) L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth. return sync.FindL1Range(ctx, i.chainSource, base) } -func (i *inputImpl) SafeL2Head(ctx context.Context) (eth.L2Node, error) { +func (i *inputImpl) SafeL2Head(ctx context.Context) (eth.L2BlockRef, error) { return sync.FindSafeL2Head(ctx, i.chainSource, i.genesis) } diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 844ef035c72b..2d9599efe0cc 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -26,23 +26,23 @@ func fakeID(id rune, num uint64) eth.BlockID { return eth.BlockID{Hash: h, Number: uint64(num)} } -func fakeL1Block(self rune, parent rune, num uint64) eth.L1Node { +func fakeL1Block(self rune, parent rune, num uint64) eth.L1BlockRef { var parentID eth.BlockID if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L1Node{Self: fakeID(self, num), Parent: parentID} + return eth.L1BlockRef{Self: fakeID(self, num), Parent: parentID} } -func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2Node { +func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2BlockRef { var parentID eth.BlockID if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L2Node{Self: fakeID(self, num), L2Parent: parentID, L1Parent: l1parent} + return eth.L2BlockRef{Self: fakeID(self, num), Parent: parentID, L1Origin: l1parent} } -func chainL1(offset uint64, ids string) (out []eth.L1Node) { +func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { var prevID rune for i, id := range ids { out = append(out, fakeL1Block(id, prevID, offset+uint64(i))) @@ -51,7 +51,7 @@ func chainL1(offset uint64, ids string) (out []eth.L1Node) { return } -func chainL2(l1 []eth.L1Node, ids string) (out []eth.L2Node) { +func chainL2(l1 []eth.L1BlockRef, ids string) (out []eth.L2BlockRef) { var prevID rune for i, id := range ids { out = append(out, fakeL2Block(id, prevID, l1[i].Self, uint64(i))) @@ -61,11 +61,11 @@ func chainL2(l1 []eth.L1Node, ids string) (out []eth.L2Node) { } func NewFakeChainSource(l1 []string, l2 []string, log log.Logger) *fakeChainSource { - var l1s [][]eth.L1Node + var l1s [][]eth.L1BlockRef for _, l1string := range l1 { l1s = append(l1s, chainL1(0, l1string)) } - var l2s [][]eth.L2Node + var l2s [][]eth.L2BlockRef for i, l2string := range l2 { l2s = append(l2s, chainL2(l1s[i], l2string)) } @@ -80,33 +80,33 @@ func NewFakeChainSource(l1 []string, l2 []string, log log.Logger) *fakeChainSour // what the head block is of the L1 and L2 chains. In addition, it enables re-orgs // to easily be implemented type fakeChainSource struct { - l1reorg int // Index of the L1 chain to be operating on - l2reorg int // Index of the L2 chain to be operating on - l1head int // Head block of the L1 chain - l2head int // Head block of the L2 chain - l1s [][]eth.L1Node // l1s[reorg] is the L1 chain in that specific re-org configuration - l2s [][]eth.L2Node // l2s[reorg] is the L2 chain in that specific re-org configuration + l1reorg int // Index of the L1 chain to be operating on + l2reorg int // Index of the L2 chain to be operating on + l1head int // Head block of the L1 chain + l2head int // Head block of the L2 chain + l1s [][]eth.L1BlockRef // l1s[reorg] is the L1 chain in that specific re-org configuration + l2s [][]eth.L2BlockRef // l2s[reorg] is the L2 chain in that specific re-org configuration log log.Logger } -func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { +func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { m.log.Trace("L1NodeByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.l1reorg) if l1Num > uint64(m.l1head) { - return eth.L1Node{}, ethereum.NotFound + return eth.L1BlockRef{}, ethereum.NotFound } return m.l1s[m.l1reorg][l1Num], nil } -func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1Node, error) { +func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) { m.log.Trace("L1HeadNode", "l1Head", m.l1head, "reorg", m.l1reorg) l := len(m.l1s[m.l1reorg]) if l == 0 { - return eth.L1Node{}, ethereum.NotFound + return eth.L1BlockRef{}, ethereum.NotFound } return m.l1s[m.l1reorg][m.l1head], nil } -func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) { +func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { m.log.Trace("L2NodeByNumber", "l2Num", l2Num, "l2Head", m.l2head, "reorg", m.l2reorg) if len(m.l2s[m.l2reorg]) == 0 { panic("bad test, no l2 chain") @@ -116,19 +116,19 @@ func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (e } i := int(l2Num.Int64()) if i > m.l2head { - return eth.L2Node{}, ethereum.NotFound + return eth.L2BlockRef{}, ethereum.NotFound } return m.l2s[m.l2reorg][i], nil } -func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) { +func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { m.log.Trace("L2NodeByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.l2reorg) for i, bl := range m.l2s[m.l2reorg] { if bl.Self.Hash == l2Hash { return m.L2NodeByNumber(ctx, big.NewInt(int64(i))) } } - return eth.L2Node{}, ethereum.NotFound + return eth.L2BlockRef{}, ethereum.NotFound } var _ sync.ChainSource = (*fakeChainSource)(nil) @@ -149,7 +149,7 @@ func (m *fakeChainSource) reorgL2() { } } -func (m *fakeChainSource) setL2Head(head int) eth.L2Node { +func (m *fakeChainSource) setL2Head(head int) eth.L2BlockRef { m.log.Trace("Set L2 head", "new_head", head, "old_head", m.l2head) m.l2head = head if m.l2head >= len(m.l2s[m.l2reorg]) { @@ -158,7 +158,7 @@ func (m *fakeChainSource) setL2Head(head int) eth.L2Node { return m.l2s[m.l2reorg][m.l2head] } -func (m *fakeChainSource) advanceL1() eth.L1Node { +func (m *fakeChainSource) advanceL1() eth.L1BlockRef { m.log.Trace("Advance L1", "new_head", m.l1head+1, "old_head", m.l1head) m.l1head++ if m.l1head >= len(m.l1s[m.l1reorg]) { @@ -167,13 +167,13 @@ func (m *fakeChainSource) advanceL1() eth.L1Node { return m.l1s[m.l1reorg][m.l1head] } -func (m *fakeChainSource) l1Head() eth.L1Node { +func (m *fakeChainSource) l1Head() eth.L1BlockRef { m.log.Trace("L1 Head", "head", m.l1head) return m.l1s[m.l1reorg][m.l1head] } // Unused functions -// func (m *fakeChainSource) advanceL2() eth.L2Node { +// func (m *fakeChainSource) advanceL2() eth.L2BlockRef { // m.log.Trace("Advance L2", "new_head", m.l2head+1, "old_head", m.l2head) // m.l2head++ // if m.l2head >= len(m.l2s[m.l1reorg]) { @@ -181,7 +181,7 @@ func (m *fakeChainSource) l1Head() eth.L1Node { // } // return m.l2s[m.l1reorg][m.l2head] // } -// func (m *fakeChainSource) l2Head() eth.L2Node { +// func (m *fakeChainSource) l2Head() eth.L2BlockRef { // m.log.Trace("L2 Head", "head", m.l2head) // return m.l2s[m.reorg][m.l2head] // } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index f51ea97f7c9d..34340f095605 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -10,11 +10,11 @@ import ( ) type inputInterface interface { - L1Head(ctx context.Context) (eth.L1Node, error) - L2Head(ctx context.Context) (eth.L2Node, error) + L1Head(ctx context.Context) (eth.L1BlockRef, error) + L2Head(ctx context.Context) (eth.L2BlockRef, error) L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) // SafeL2Head is the L2 Head found via the sync algorithm - SafeL2Head(ctx context.Context) (eth.L2Node, error) + SafeL2Head(ctx context.Context) (eth.L2BlockRef, error) } type outputInterface interface { @@ -33,7 +33,7 @@ type state struct { Config rollup.Config // Connections (in/out) - l1Heads <-chan eth.L1Node + l1Heads <-chan eth.L1BlockRef input inputInterface output outputInterface @@ -51,7 +51,7 @@ func NewState(log log.Logger, config rollup.Config, input inputInterface, output } } -func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1Node) error { +func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error { l1Head, err := s.input.L1Head(ctx) if err != nil { return err @@ -63,7 +63,7 @@ func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1Node) error { s.l1Head = l1Head.Self s.l2Head = l2Head.Self - s.l1Base = l2Head.L1Parent + s.l1Base = l2Head.L1Origin s.l1Heads = l1Heads go s.loop() @@ -154,7 +154,7 @@ func (s *state) loop() { } s.l1Head = newL1Head.Self s.l1Window = nil - s.l1Base = nextL2Head.L1Parent + s.l1Base = nextL2Head.L1Origin s.l2Head = nextL2Head.Self } // Run step if we are able to diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index c68c216a5b04..957c57aeeb3b 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -59,20 +59,20 @@ type stateTestCaseStep struct { expectedL2Head testID expectedWindow []testID - l1action func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) + l1action func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) l2action func(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) reorg bool } -func advanceL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) { +func advanceL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) { l1Heads <- src.advanceL1() } -func stutterL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) { +func stutterL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) { l1Heads <- src.l1Head() } -func stutterAdvance(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1Node) { +func stutterAdvance(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) { l1Heads <- src.l1Head() l1Heads <- src.l1Head() l1Heads <- src.l1Head() @@ -123,7 +123,7 @@ type stateTestCase struct { func (tc *stateTestCase) Run(t *testing.T) { log := testlog.Logger(t, log.LvlTrace) chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) - l1headsCh := make(chan eth.L1Node, 10) + l1headsCh := make(chan eth.L1BlockRef, 10) // Unbuffered channels to force a sync point between outputIn := make(chan outputArgs) outputReturn := make(chan outputReturnArgs) diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index 9c6b9ccf7472..65a6d3877018 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -26,10 +26,10 @@ type L2Client interface { // ChainSource provides access to the L1 and L2 block graph type ChainSource interface { - L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) - L1HeadNode(ctx context.Context) (eth.L1Node, error) - L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) - L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) + L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) + L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) + L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) + L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) } func NewChainSource(l1 L1Client, l2 L2Client, genesis *rollup.Genesis) *chainSourceImpl { @@ -43,50 +43,50 @@ type chainSourceImpl struct { } // L1NodeByNumber returns the canonical block and parent ids. -func (src chainSourceImpl) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { +func (src chainSourceImpl) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { return src.l1NodeByNumber(ctx, new(big.Int).SetUint64(l1Num)) } // L1NodeByNumber returns the canonical head block and parent ids. -func (src chainSourceImpl) L1HeadNode(ctx context.Context) (eth.L1Node, error) { +func (src chainSourceImpl) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) { return src.l1NodeByNumber(ctx, nil) } // l1NodeByNumber wraps l1.HeaderByNumber to return an eth.L1Node // This is internal because the exposed L1NodeByNumber takes uint64 instead of big.Ints -func (src chainSourceImpl) l1NodeByNumber(ctx context.Context, number *big.Int) (eth.L1Node, error) { +func (src chainSourceImpl) l1NodeByNumber(ctx context.Context, number *big.Int) (eth.L1BlockRef, error) { header, err := src.l1.HeaderByNumber(ctx, number) if err != nil { // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L1Node{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", number, err) + return eth.L1BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", number, err) } l1Num := header.Number.Uint64() parentNum := l1Num if parentNum > 0 { parentNum -= 1 } - return eth.L1Node{ + return eth.L1BlockRef{ Self: eth.BlockID{Hash: header.Hash(), Number: l1Num}, Parent: eth.BlockID{Hash: header.ParentHash, Number: parentNum}, }, nil } // L2NodeByNumber returns the canonical block and parent ids. -func (src chainSourceImpl) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) { +func (src chainSourceImpl) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { block, err := src.l2.BlockByNumber(ctx, l2Num) if err != nil { // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L2Node{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) + return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) } return derive.BlockReferences(block, src.genesis) } // L2NodeByHash returns the block & parent ids based on the supplied hash. The returned node may not be in the canonical chain -func (src chainSourceImpl) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) { +func (src chainSourceImpl) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { block, err := src.l2.BlockByHash(ctx, l2Hash) if err != nil { // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L2Node{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) + return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) } return derive.BlockReferences(block, src.genesis) } diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 325938f1d4c0..561d2560350b 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -63,7 +63,7 @@ func FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Gene if err != nil { return nil, eth.BlockID{}, err } - l1blocks, err := FindL1Range(ctx, source, l2Head.L1Parent) + l1blocks, err := FindL1Range(ctx, source, l2Head.L1Origin) if err != nil { return nil, eth.BlockID{}, fmt.Errorf("failed to fetch l1 range: %w", err) } @@ -75,25 +75,25 @@ func FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Gene // FindSafeL2Head takes the current L2 Head and then finds the topmost L2 head that is valid // In the case that there are no re-orgs, this is just the L2 head. Otherwise it has to walk back // until it finds the first L2 block that is based on a canonical L1 block. -func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (eth.L2Node, error) { +func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (eth.L2BlockRef, error) { // Starting point l2Head, err := source.L2NodeByNumber(ctx, nil) if err != nil { - return eth.L2Node{}, fmt.Errorf("failed to fetch L2 head: %w", err) + return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 head: %w", err) } reorgDepth := 0 // Walk L2 chain from L2 head to first L2 block which has a L1 Parent that is canonical. May walk to L2 genesis for n := l2Head; ; { - l1header, err := source.L1NodeByNumber(ctx, n.L1Parent.Number) + l1header, err := source.L1NodeByNumber(ctx, n.L1Origin.Number) if err != nil { // Generic error, bail out. if !errors.Is(err, ethereum.NotFound) { - return eth.L2Node{}, fmt.Errorf("failed to fetch L1 block %v: %w", n.L1Parent.Number, err) + return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L1 block %v: %w", n.L1Origin.Number, err) } // L1 block not found, keep walking chain } else { // L1 Block found, check if matches & should keep walking the chain - if l1header.Self.Hash == n.L1Parent.Hash { + if l1header.Self.Hash == n.L1Origin.Hash { return n, nil } } @@ -101,17 +101,17 @@ func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Gen // Don't walk past genesis. If we were at the L2 genesis, but could not find the L1 genesis // pointed to from it, we are on the wrong L1 chain. if n.Self.Hash == genesis.L2.Hash || n.Self.Number == genesis.L2.Number { - return eth.L2Node{}, WrongChainErr + return eth.L2BlockRef{}, WrongChainErr } // Pull L2 parent for next iteration - n, err = source.L2NodeByHash(ctx, n.L2Parent.Hash) + n, err = source.L2NodeByHash(ctx, n.Parent.Hash) if err != nil { - return eth.L2Node{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.L2Parent.Hash, err) + return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.Parent.Hash, err) } reorgDepth++ if reorgDepth >= MaxReorgDepth { - return eth.L2Node{}, TooDeepReorgErr + return eth.L2BlockRef{}, TooDeepReorgErr } } } diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 42e965f7f660..5304f185b583 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -13,26 +13,26 @@ import ( ) type fakeChainSource struct { - L1 []eth.L1Node - L2 []eth.L2Node + L1 []eth.L1BlockRef + L2 []eth.L2BlockRef } -func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1Node, error) { +func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { if l1Num >= uint64(len(m.L1)) { - return eth.L1Node{}, ethereum.NotFound + return eth.L1BlockRef{}, ethereum.NotFound } return m.L1[l1Num], nil } -func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1Node, error) { +func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) { l := len(m.L1) if l == 0 { - return eth.L1Node{}, ethereum.NotFound + return eth.L1BlockRef{}, ethereum.NotFound } return m.L1[l-1], nil } -func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2Node, error) { +func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { if len(m.L2) == 0 { panic("bad test, no l2 chain") } @@ -43,13 +43,13 @@ func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (e return m.L2[i], nil } -func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2Node, error) { +func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { for i, bl := range m.L2 { if bl.Self.Hash == l2Hash { return m.L2NodeByNumber(ctx, big.NewInt(int64(i))) } } - return eth.L2Node{}, ethereum.NotFound + return eth.L2BlockRef{}, ethereum.NotFound } var _ ChainSource = (*fakeChainSource)(nil) @@ -60,23 +60,23 @@ func fakeID(id rune, num uint64) eth.BlockID { return eth.BlockID{Hash: h, Number: uint64(num)} } -func fakeL1Block(self rune, parent rune, num uint64) eth.L1Node { +func fakeL1Block(self rune, parent rune, num uint64) eth.L1BlockRef { var parentID eth.BlockID if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L1Node{Self: fakeID(self, num), Parent: parentID} + return eth.L1BlockRef{Self: fakeID(self, num), Parent: parentID} } -func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2Node { +func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2BlockRef { var parentID eth.BlockID if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L2Node{Self: fakeID(self, num), L2Parent: parentID, L1Parent: l1parent} + return eth.L2BlockRef{Self: fakeID(self, num), Parent: parentID, L1Origin: l1parent} } -func chainL1(offset uint64, ids string) (out []eth.L1Node) { +func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { var prevID rune for i, id := range ids { out = append(out, fakeL1Block(id, prevID, offset+uint64(i))) @@ -85,7 +85,7 @@ func chainL1(offset uint64, ids string) (out []eth.L1Node) { return } -func chainL2(l1 []eth.L1Node, ids string) (out []eth.L2Node) { +func chainL2(l1 []eth.L1BlockRef, ids string) (out []eth.L2BlockRef) { var prevID rune for i, id := range ids { out = append(out, fakeL2Block(id, prevID, l1[i].Self, uint64(i))) From 6ce85c622da6b4015a18721fb8fa9ff19628d1b0 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 8 Mar 2022 18:41:02 +0100 Subject: [PATCH 287/585] Sequencing spec: seq window, derivation from batches, slight sync adjustment --- specs/deposits.md | 3 +- specs/glossary.md | 47 ++++++++++++---- specs/rollup-node.md | 126 ++++++++++++++++++++++++++++++++----------- 3 files changed, 134 insertions(+), 42 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 252c311896d6..7952dee69a37 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -7,7 +7,6 @@ [g-deposits]: glossary.md#deposits [g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction [g-user-deposited]: glossary.md#user-deposited-transaction -[g-deposit-block]: glossary.md#deposit-block [g-eoa]: glossary.md#eoa [Deposited transactions][g-deposited], also known as [deposits][g-deposits] are transactions which @@ -76,7 +75,7 @@ for a variable-length encoding scheme. ### Kinds of Deposited Transactions Although we define only one new transaction type, we can distinguish between two kinds of deposited -transactions, based on their positioning in the [deposit block][g-deposit-block]: +transactions, based on their positioning in the L2 block: 1. The first transaction MUST be a [L1 attributes deposited transaction][l1-attr-deposit], followed by diff --git a/specs/glossary.md b/specs/glossary.md index 7e7da6abb60f..d9f054f01f89 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -15,9 +15,12 @@ - [Receipt](#receipt) - [Transaction Type](#transaction-type) - [Fork Choice Rule](#fork-choice-rule) +- [Sequencing](#sequencing) + - [Sequencing window](#sequencing-window) + - [Sequencing epoch](#sequencing-epoch) + - [Sequencer batch](#sequencer-batch) - [Deposits](#deposits) - [Deposited Transaction](#deposited-transaction) - - [Deposit Block](#deposit-block) - [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) - [User-Deposited Transaction](#user-deposited-transaction) - [Depositing Call](#depositing-call) @@ -140,6 +143,38 @@ on-chain-confirmed head, or the on-chain-finalized head. ------------------------------------------------------------------------------------------------------------------------ +# Sequencing + +[sequencing]: glossary.md#sequencing + +Transactions in the rollup can be included in two ways: + +- Through a [deposited transaction](#deposited-transaction), enforced by the system +- Through a regular transaction, embedded in a [sequencer batch](#sequencer-batch) + +Submitting transactions for inclusion in a batch saves costs by reducing overhead, and enables the sequencer to +pre-confirm the transactions before the L1 confirms the data. + +## Sequencing window + +[sequencing-window]: glossary.md#sequencing-window + +A sequencing window is a range of L1 blocks, to parse inputs from during a derivation step. + +## Sequencing epoch + +A sequencing epoch is a number identifying the start of a [sequencing window](#sequencing-window), +equal to the L1 block number of the first block in the window. + +## Sequencer batch + +[sequencer-batch]: glossary.md#sequencer-batch + +A sequencer batch is list of L2 transactions tagged with an [`epoch`](#sequencing-epoch) and L2 block `timestamp`. +Each L2 block can have one batch of transactions, an input for the block derivation. + +------------------------------------------------------------------------------------------------------------------------ + # Deposits [deposits]: glossary.md#deposits @@ -170,8 +205,7 @@ Deposits are specified in the [deposits specification][deposits-spec]. [deposited]: glossary.md#deposited-transaction -A *deposited transaction* is a L2 transaction that was derived from L1 and is included in a [deposit -block][deposit-block]. +A *deposited transaction* is a L2 transaction that was derived from L1 and included in a L2 block. There are two kinds of deposited transactions: @@ -182,12 +216,6 @@ There are two kinds of deposited transactions: [deposits-spec]: deposits.md -## Deposit Block - -[deposit-block]: glossary.md#deposit-block - -A *deposit block* is a L2 block that contains only [deposited transactions][deposited]. - ## L1 Attributes Deposited Transaction [l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction @@ -312,6 +340,7 @@ L2 derivation inputs include: - timestamp - basefee - [deposits] (as log data) +- [sequencer batches][sequencer-batch] (as transaction data) ## Payload Attributes diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 8ce612f1fffc..87fd0dd98b05 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -12,7 +12,6 @@ [g-receipts]: glossary.md#receipt [g-deposit-contract]: glossary.md#deposit-contract [g-deposits]: glossary.md#deposits -[g-deposit-block]: glossary.md#deposit-block [g-deposited]: glossary.md#deposited-transaction [g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction [g-user-deposited]: glossary.md#user-deposited-transaction @@ -20,13 +19,18 @@ [g-depositing-call]: glossary.md#depositing-call [g-depositing-transaction]: glossary.md#depositing-transaction [g-mpt]: glossary.md#merkle-patricia-trie +[g-sequencing-window]: glossary.md#sequencing-window +[g-sequencing]: glossary.md#sequencing +[g-sequencer-batch]: glossary.md#sequencer-batch The [rollup node][g-rollup-node] is the component responsible for [deriving the L2 chain][g-derivation] from L1 blocks -(and their associated [receipts][g-receipts]). This process happens in two steps: +(and their associated [receipts][g-receipts]). This process happens in three steps: -1. Read from L1 blocks and associated receipts, in order to generate [payload attributes][g-payload-attr] (essentially - [a block without output properties][g-block]). -2. Pass the payload attributes to the [execution engine][g-exec-engine], so that the L2 block (including [output block +1. Select a [sequencing window][g-sequencing-window] from the L1 chain, on top of the last L2 block: + a list of blocks, with transactions and associated receipts. +2. Read L1 information, deposits, and sequencing batches in order to generate [payload attributes][g-payload-attr] + (essentially [a block without output properties][g-block]). +3. Pass the payload attributes to the [execution engine][g-exec-engine], so that the L2 block (including [output block properties][g-block]) may be computed. While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The @@ -41,6 +45,7 @@ currently only concerned with the specification of the rollup driver. **Table of Contents** - [L2 Chain Derivation](#l2-chain-derivation) + - [From L1 chain to Sequencing Window](#from-l1-chain-to-sequencing-window) - [From L1 Blocks to Payload Attributes](#from-l1-blocks-to-payload-attributes) - [Reading L1 inputs](#reading-l1-inputs) - [Encoding the L1 Attributes Deposited Transaction](#encoding-the-l1-attributes-deposited-transaction) @@ -59,31 +64,82 @@ currently only concerned with the specification of the rollup driver. [l2-chain-derivation]: #l2-chain-derivation -This section specifies how the [rollup driver][g-rollup-driver] derives one L2 [deposit block][g-deposit-block] per -every L1 block. The L2 block carries *[deposited transactions][g-deposited]* of two kinds: +This section specifies how the [rollup driver][g-rollup-driver] derives a sequence of L2 blocks per sequencing window. -- a single *[L1 attributes deposited transaction][g-l1-attr-deposit]* (always first) -- zero or more *[user-deposited transactions][g-user-deposited]* +Every L2 block carries transactions of two categories: + +- *[deposited transactions][g-deposited]*: two kinds: + - derived from the L1 chain: a single *[L1 attributes deposited transaction][g-l1-attr-deposit]* (always first). + - derived from [receipts][g-receipts]: zero or more *[user-deposited transactions][g-user-deposited]*. +- *[sequenced transactions][g-sequencing]*: derived from [sequencer batches][g-sequencer-batch], + zero or more regular transactions, signed by L2 users. ------------------------------------------------------------------------------------------------------------------------ +## From L1 chain to Sequencing Window + +A [sequencing window][g-sequencing-window] is a fixed number consecutive L1 blocks that a derivation step takes as +input. The window is identified by an `epoch`, equal to the block number of the first block in the window. + +As the full derivation of the L2 chain by the driver progresses each derivation step shifts the window forward by a +single L1 block: the windows overlap. + +Each sequencing window is derived into a variable number of L2 blocks, depending on the timestamps of L1 and L2. + +The L2 has a fixed block time and no more than one batch per block, +meaning that gaps between the batches (ordered by timestamp) are interpreted as batches with empty transaction-lists, +thus construing L2 blocks that only contain deposit transaction(s). + +The L2 blocks produced by a sequencing window are bounded by timestamp: + +- `min_l2_timestamp = prev_l2_timestamp + l2_block_time` +- `max_l2_timestamp = l1_timestamp + l2_block_time`, where `l1_timestamp` is the timestamp of the + first L1 block of the sequencing window. (maximum bound, may not be aligned with block time) + +If there are no batches present in the sequencing window then the L2 chain is extended up to `max_l2_timestamp` (incl.) +with empty batches, but otherwise regular block derivation. + +Note that with short block times on L1 the L2 time may increment beyond the L1 time, +but the longer target block time of L1 will correct back and allow the timestamps to align again. + ## From L1 Blocks to Payload Attributes ### Reading L1 inputs -The rollup reads the following data from each L1 block: - -- L1 block attributes - - block number - - timestamp - - basefee - - *random* (the output of the [`RANDOM` opcode][random]) -- L1 log entries emitted for [user deposits][g-deposits], augmented with - - `blockHeight`: the block-height of the L1 block - - `transactionIndex`: the transaction-index within the L2 transactions list +The rollup reads the following data from the [sequencing window][g-sequencing-window]: + +- Of the *first* block in the window only: + - L1 block attributes: + - block number + - timestamp + - basefee + - *random* (the output of the [`RANDOM` opcode][random]) + - L1 log entries emitted for [user deposits][g-deposits], augmented with + - `blockHeight`: the block-height of the L1 block + - `transactionIndex`: the transaction-index within the L2 transactions list +- Of each block in the window: + - Sequencer batches, derived from the transactions: + - The transaction receiver is the sequencer inbox address + - The transaction must be signed by a recognized sequencer account + - The calldata may contain any number of batches. *(calldata will be substituted with blob data in the future.)* + - Batches not matching filter criteria are ignored: + - `batch.epoch == sequencing_window.epoch`, i.e. for this sequencing window + - `(batch.timestamp - genesis_l2_timestamp) % block_time == 0`, i.e. timestamp is aligned + - `min_l2_timestamp < batch.timestamp < max_l2_timestamp`, i.e. timestamp is within range + - The batch is the first batch with `batch.timestamp` in this sequencing window, + i.e. one batch per L2 block number [random]: https://eips.ethereum.org/EIPS/eip-4399 +Batches are formatted as: `type ++ RLP([epoch, timestamp, transaction_list])` + +- `type` is a single `byte` identifying the batch format +- `epoch` is the sequencing window epoch, i.e. the first L1 block number +- `timestamp` is the L2 timestamp of the block +- `transaction_list` is an RLP encoded list of [EIP-2718] encoded transactions + +[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 + > Design note: The extra log entry metadata will be used to ensure that deposited transactions will be unique. Without > them, two different deposited transaction could have the same exact hash. > @@ -96,6 +152,11 @@ entries. [deposit-contract-spec]: deposits.md#deposit-contract +Each of the derived `PayloadAttributes` starts with a L1 Attributes transaction. + +The [User-deposited] transactions are all put in the first of the derived `PayloadAttributes`, +inserted after the L1 Attributes transaction, before any [sequenced][g-sequencing] transactions. + ### Encoding the L1 Attributes Deposited Transaction The [L1 attributes deposited transaction][g-l1-attr-deposit] is a call that submits the L1 block attributes (listed @@ -125,14 +186,14 @@ To encode user-deposited transactions, refer to the following sections of the de [payload attributes]: #building-the-payload-attributes From the data read from L1 and the encoded transactions, the rollup node constructs the [payload -attributes][g-payload-attr] as an [expanded version][expanded-paylod] of the [`PayloadAttributesV1`] object, which +attributes][g-payload-attr] as an [expanded version][expanded-payload] of the [`PayloadAttributesV1`] object, which includes an additional `transactions` field. The object's properties must be set as follows: - `timestamp` is set to the timestamp of the L1 block. - `random` is set to the *random* L1 block attribute -- `suggestedFeeRecipient` is set to the zero-address for deposit-blocks, since there is no sequencer. +- `suggestedFeeRecipient` is set to an address determined by the system - `transactions` is an array of the derived deposits, encoded as per the two preceding sections. [expanded-payload]: exec-engine.md#extended-payloadattributesv1 @@ -259,12 +320,13 @@ However, they can still be challenged by a fault proof until the end of the faul ## Whole L2 Chain Derivation The [block derivation](#from-l1-blocks-to-payload-attributes) presents an inductive process: -given that we know the "current" L2 block, well as the next L1 block, -then we can derive [payload attributes] for the next L1 block, and from that the next L2 block. +given that we know the last L2 block derived from the previous [sequencing window][g-sequencing-window], as well as the +next [sequencing window][g-sequencing-window], then we can derive [payload attributes] of the next L2 blocks. -To derive the whole L2 chain from scratch, we simply start with the L2 genesis block as the current L2 block, and the -block at height `L2_CHAIN_INCEPTION + 1` as the next L1 block. Then we iteratively apply the derivation process from the -previous section to each successive L1 block until we have caught up with the L1 head. +To derive the whole L2 chain from scratch, we simply start with the L2 genesis block as the last L2 block, and the +block at height `L2_CHAIN_INCEPTION + 1` as the start of the next sequencing window. +Then we iteratively apply the derivation process from the previous section by shifting the sequencing window one L1 +block forward each step, until there is an insufficient number of L1 blocks left for a complete sequencing window. > **TODO** specify genesis block @@ -286,11 +348,14 @@ ancestor, and can re-derive the L2 chain from that L1 block and onwards. The starting point of the re-derivation is a pair `(refL2, nextRefL1)` where `refL2` refers to the L2 block to build upon and `nextRefL1` refers to the next L1 block to derive from (i.e. if `refL2` is derived from L1 block `refL1`, -`nextRefL1` is the canonicla L1 block at height `l1Number(refL1) + 1`). +`nextRefL1` is the canonical L1 block at height `l1Number(refL1) + 1`). In practice, the happy path (no re-org) and the re-org paths are merged. The happy path is simply a special case of the re-org path where the starting point of the re-derivation is `(currentL2Head, newL1Block)`. +After a `(currentL2Head, newL1Block)` starting point is found, derivation can continue when a complete sequencing window +of canonical L1 blocks following the starting point is retrieved. + This re-derivation starting point can be found by applying the following algorithm: 1. (Initialization) Set the initial `refL2` to the head block of the L2 execution engine. @@ -300,14 +365,13 @@ This re-derivation starting point can be found by applying the following algorit - If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the re-derivation. - - It is necessary to ensure that no L1 re-org occured during this lookup, i.e. that `nextRefL1.parent == refL1`. + - It is necessary to ensure that no L1 re-org occurred during this lookup, i.e. that `nextRefL1.parent == refL1`. - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the process. - Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that - requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis - configuration) (\*) + requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration) (\*) - Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this - algorithm from step 2. + algorithm from step 2. - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an extra lookup. From 520ba01bb67d6ddb596eb58ae20061e3ea17437f Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Mar 2022 12:27:27 -0800 Subject: [PATCH 288/585] ref impl: Clean up testing code Short names and removing dead code. --- opnode/rollup/driver/fake_chain.go | 14 ------ opnode/rollup/driver/state_test.go | 78 +++++++++++++++--------------- 2 files changed, 40 insertions(+), 52 deletions(-) diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 2d9599efe0cc..8b88e4b06748 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -171,17 +171,3 @@ func (m *fakeChainSource) l1Head() eth.L1BlockRef { m.log.Trace("L1 Head", "head", m.l1head) return m.l1s[m.l1reorg][m.l1head] } - -// Unused functions -// func (m *fakeChainSource) advanceL2() eth.L2BlockRef { -// m.log.Trace("Advance L2", "new_head", m.l2head+1, "old_head", m.l2head) -// m.l2head++ -// if m.l2head >= len(m.l2s[m.l1reorg]) { -// panic("Cannot advance L2 past end of chain") -// } -// return m.l2s[m.l1reorg][m.l2head] -// } -// func (m *fakeChainSource) l2Head() eth.L2BlockRef { -// m.log.Trace("L2 Head", "head", m.l2head) -// return m.l2s[m.reorg][m.l2head] -// } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 957c57aeeb3b..81de6883ae5e 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -55,13 +55,15 @@ type outputReturnArgs struct { } type stateTestCaseStep struct { - expectedL1Head testID - expectedL2Head testID - expectedWindow []testID - - l1action func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) - l2action func(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) - reorg bool + // Expect l1head, l2head, and sequence window + l1head testID + l2head testID + window []testID + + // l1act and l2act are ran at each step + l1act func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) + l2act func(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) + reorg bool } func advanceL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) { @@ -124,7 +126,7 @@ func (tc *stateTestCase) Run(t *testing.T) { log := testlog.Logger(t, log.LvlTrace) chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) l1headsCh := make(chan eth.L1BlockRef, 10) - // Unbuffered channels to force a sync point between + // Unbuffered channels to force a sync point between the test and the state loop. outputIn := make(chan outputArgs) outputReturn := make(chan outputReturnArgs) outputHandler := func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { @@ -145,13 +147,13 @@ func (tc *stateTestCase) Run(t *testing.T) { if step.reorg { chainSource.reorgL1() } - step.l1action(t, state, chainSource, l1headsCh) + step.l1act(t, state, chainSource, l1headsCh) <-time.After(5 * time.Millisecond) - step.l2action(t, step.expectedWindow, state, chainSource, outputIn, outputReturn) + step.l2act(t, step.window, state, chainSource, outputIn, outputReturn) <-time.After(5 * time.Millisecond) - assert.Equal(t, step.expectedL1Head.ID(), state.l1Head, "l1 head") - assert.Equal(t, step.expectedL2Head.ID(), state.l2Head, "l2 head") + assert.Equal(t, step.l1head.ID(), state.l1Head, "l1 head") + assert.Equal(t, step.l2head.ID(), state.l2Head, "l2 head") } } @@ -164,13 +166,13 @@ func TestDriver(t *testing.T) { seqWindow: 2, genesis: fakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ - {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, - {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "c:2", expectedL2Head: "B:1", expectedWindow: []testID{"b:1", "c:2"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "d:3", expectedL2Head: "C:2", expectedWindow: []testID{"c:2", "d:3"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "e:4", expectedL2Head: "D:3", expectedWindow: []testID{"d:3", "e:4"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "f:5", expectedL2Head: "E:4", expectedWindow: []testID{"e:4", "f:5"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "g:6", expectedL2Head: "F:5", expectedWindow: []testID{"f:5", "g:6"}}, + {l1act: stutterL1, l2act: stutterL2, l1head: "a:0", l2head: "A:0"}, + {l1act: advanceL1, l2act: stutterL2, l1head: "b:1", l2head: "A:0", window: []testID{"a:0", "b:1"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "c:2", l2head: "B:1", window: []testID{"b:1", "c:2"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "d:3", l2head: "C:2", window: []testID{"c:2", "d:3"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "e:4", l2head: "D:3", window: []testID{"d:3", "e:4"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "f:5", l2head: "E:4", window: []testID{"e:4", "f:5"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "g:6", l2head: "F:5", window: []testID{"f:5", "g:6"}}, }, }, { @@ -180,18 +182,18 @@ func TestDriver(t *testing.T) { seqWindow: 2, genesis: fakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ - {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, - {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "c:2", expectedL2Head: "B:1", expectedWindow: []testID{"b:1", "c:2"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "d:3", expectedL2Head: "C:2", expectedWindow: []testID{"c:2", "d:3"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "e:4", expectedL2Head: "D:3", expectedWindow: []testID{"d:3", "e:4"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "f:5", expectedL2Head: "E:4", expectedWindow: []testID{"e:4", "f:5"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "g:6", expectedL2Head: "F:5", expectedWindow: []testID{"f:5", "g:6"}}, - {l1action: stutterL1, l2action: reorg__L2, expectedL1Head: "w:6", expectedL2Head: "X:3", expectedWindow: []testID{"x:3", "y:4"}, reorg: true}, - {l1action: stutterL1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "Y:4", expectedWindow: []testID{"y:4", "z:5"}}, - {l1action: stutterL1, l2action: advanceL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, - {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, - {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "w:6", expectedL2Head: "Z:5", expectedWindow: []testID{"z:5", "w:6"}}, + {l1act: stutterL1, l2act: stutterL2, l1head: "a:0", l2head: "A:0"}, + {l1act: advanceL1, l2act: stutterL2, l1head: "b:1", l2head: "A:0", window: []testID{"a:0", "b:1"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "c:2", l2head: "B:1", window: []testID{"b:1", "c:2"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "d:3", l2head: "C:2", window: []testID{"c:2", "d:3"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "e:4", l2head: "D:3", window: []testID{"d:3", "e:4"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "f:5", l2head: "E:4", window: []testID{"e:4", "f:5"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "g:6", l2head: "F:5", window: []testID{"f:5", "g:6"}}, + {l1act: stutterL1, l2act: reorg__L2, l1head: "w:6", l2head: "X:3", window: []testID{"x:3", "y:4"}, reorg: true}, + {l1act: stutterL1, l2act: advanceL2, l1head: "w:6", l2head: "Y:4", window: []testID{"y:4", "z:5"}}, + {l1act: stutterL1, l2act: advanceL2, l1head: "w:6", l2head: "Z:5", window: []testID{"z:5", "w:6"}}, + {l1act: stutterL1, l2act: stutterL2, l1head: "w:6", l2head: "Z:5", window: []testID{"z:5", "w:6"}}, + {l1act: stutterL1, l2act: stutterL2, l1head: "w:6", l2head: "Z:5", window: []testID{"z:5", "w:6"}}, }, }, { @@ -201,13 +203,13 @@ func TestDriver(t *testing.T) { seqWindow: 2, genesis: fakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ - {l1action: stutterL1, l2action: stutterL2, expectedL1Head: "a:0", expectedL2Head: "A:0"}, - {l1action: advanceL1, l2action: stutterL2, expectedL1Head: "b:1", expectedL2Head: "A:0", expectedWindow: []testID{"a:0", "b:1"}}, - {l1action: stutterAdvance, l2action: advanceL2, expectedL1Head: "c:2", expectedL2Head: "B:1", expectedWindow: []testID{"b:1", "c:2"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "d:3", expectedL2Head: "C:2", expectedWindow: []testID{"c:2", "d:3"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "e:4", expectedL2Head: "D:3", expectedWindow: []testID{"d:3", "e:4"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "f:5", expectedL2Head: "E:4", expectedWindow: []testID{"e:4", "f:5"}}, - {l1action: advanceL1, l2action: advanceL2, expectedL1Head: "g:6", expectedL2Head: "F:5", expectedWindow: []testID{"f:5", "g:6"}}, + {l1act: stutterL1, l2act: stutterL2, l1head: "a:0", l2head: "A:0"}, + {l1act: advanceL1, l2act: stutterL2, l1head: "b:1", l2head: "A:0", window: []testID{"a:0", "b:1"}}, + {l1act: stutterAdvance, l2act: advanceL2, l1head: "c:2", l2head: "B:1", window: []testID{"b:1", "c:2"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "d:3", l2head: "C:2", window: []testID{"c:2", "d:3"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "e:4", l2head: "D:3", window: []testID{"d:3", "e:4"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "f:5", l2head: "E:4", window: []testID{"e:4", "f:5"}}, + {l1act: advanceL1, l2act: advanceL2, l1head: "g:6", l2head: "F:5", window: []testID{"f:5", "g:6"}}, }, }, } From b67b3deb7654b9afe72b0f8c02b29c8b4cda174c Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Mar 2022 12:57:02 -0800 Subject: [PATCH 289/585] ref impl: Implement sequence spec This uses the BatchesFromEVMTransactions and the FilterBatches functions to implement the spec. Some changes to the downloader interface have been made to suppor this. --- opnode/l1/source.go | 20 +++++++++++++------- opnode/rollup/driver/step.go | 21 +++++++++------------ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 4765dc0900f2..2f6b1eba65bd 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -72,16 +72,22 @@ func (s Source) Close() { } func (s Source) FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) { - block, _, err := s.Fetch(ctx, id) - return block, err + return s.client.BlockByHash(ctx, id.Hash) } func (s Source) FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) { _, receipts, err := s.Fetch(ctx, id) return receipts, err } -func (s Source) FetchBatches(ctx context.Context, window []eth.BlockID) ([]derive.BatchData, error) { - return nil, nil -} -func (s Source) FetchL2Info(ctx context.Context, id eth.BlockID) (derive.L2Info, error) { - return nil, nil + +func (s Source) FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) { + var txns []*types.Transaction + for _, id := range window { + block, err := s.client.BlockByHash(ctx, id.Hash) + if err != nil { + return nil, err + } + txns = append(txns, block.Transactions()...) + } + return txns, nil + } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 17b1446b1301..9d6fe67a226b 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -20,10 +20,8 @@ type Downloader interface { FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) // FetchReceipts of a L1 block FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) - // FetchBatches from the given window of L1 blocks - FetchBatches(ctx context.Context, window []eth.BlockID) ([]derive.BatchData, error) - // FetchL2Info fetches the L2 header information corresponding to a L2 block ID - FetchL2Info(ctx context.Context, id eth.BlockID) (derive.L2Info, error) + // FetchTransactions from the given window of L1 blocks + FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) } type DriverAPI interface { @@ -56,33 +54,32 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - l2Info, err := d.dl.FetchL2Info(fetchCtx, l2Head) + l2Info, err := d.rpc.BlockByHash(fetchCtx, l2Head.Hash) if err != nil { return l2Head, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Head, err) } - logger.Trace("Got l2 info") l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Input[0]) if err != nil { return l2Head, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Input[0], err) } - logger.Trace("Got l1 info") receipts, err := d.dl.FetchReceipts(fetchCtx, l1Input[0]) if err != nil { return l2Head, fmt.Errorf("failed to fetch receipts of %s: %v", l1Input[0], err) } - logger.Trace("Got receipts") // TODO: with sharding the blobs may be identified in more detail than L1 block hashes - batches, err := d.dl.FetchBatches(fetchCtx, l1Input) + transactions, err := d.dl.FetchTransactions(fetchCtx, l1Input) if err != nil { - return l2Head, fmt.Errorf("failed to fetch batches from %s: %v", l1Input, err) + return l2Head, fmt.Errorf("failed to fetch transactions from %s: %v", l1Input, err) } - logger.Trace("Got batches") + batches := derive.BatchesFromEVMTransactions(&d.Config, transactions) + minL2Time := l2Info.Time() + d.Config.BlockTime + maxL2Time := l1Info.Time() + d.Config.BlockTime + batches = derive.FilterBatches(&d.Config, epoch, minL2Time, maxL2Time, batches) attrsList, err := derive.PayloadAttributes(&d.Config, l1Info, receipts, batches, l2Info) if err != nil { return l2Head, fmt.Errorf("failed to derive execution payload inputs: %v", err) } - logger.Debug("derived L2 block inputs") last := l2Head for i, attrs := range attrsList { From 22f62f45a1d3adbb2e6d0297da77dc317170aab1 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 8 Mar 2022 13:48:56 -0800 Subject: [PATCH 290/585] ref impl: Include L1Info in every L2 block This forces the L1 Info transaction to be the first transaction of every L2 block in an epoch. --- opnode/rollup/derive/payload_attributes.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index b0afa25c0e5d..0d5419b541fe 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -245,6 +245,12 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R return nil, fmt.Errorf("failed to derive deposits: %v", err) } + l1Tx := types.NewTx(L1InfoDeposit(l1Info)) + l1InfoTx, err := l1Tx.MarshalBinary() // TODO: Issue with shared l1InfoTx? + if err != nil { + return nil, fmt.Errorf("failed to encode L1 info tx") + } + // copy L1 randomness (mix-digest becomes randao field post-merge) // TODO: we don't have a randomness oracle on L2, what should sequencing randomness look like. // Repeating the latest randomness of L1 might not be ideal. @@ -260,11 +266,15 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R highestSeenTimestamp = batch.Timestamp } + txns := make([]l2.Data, 0, len(batch.Transactions)+1) + txns = append(txns, l1InfoTx) + txns = append(txns, batch.Transactions...) + l2Blocks[batch.Timestamp] = &l2.PayloadAttributes{ Timestamp: l2.Uint64Quantity(batch.Timestamp), Random: randomnessSeed, SuggestedFeeRecipient: config.FeeRecipientAddress, - Transactions: batch.Transactions, + Transactions: txns, } } @@ -281,17 +291,19 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R out = append(out, bl) } else { // skipped/missing L2 block, create an empty block instead + txns := make([]l2.Data, 1) + txns[0] = l1InfoTx out = append(out, &l2.PayloadAttributes{ Timestamp: l2.Uint64Quantity(t), Random: randomnessSeed, SuggestedFeeRecipient: config.FeeRecipientAddress, - Transactions: nil, + Transactions: txns, }) } } - // Force deposits into the first block - out[0].Transactions = append(append(make([]l2.Data, 0), deposits...), out[0].Transactions...) + // Force deposits into the first block. TODO: Clean up L1 Info handling. + out[0].Transactions = append(append(make([]l2.Data, 0), deposits...), out[0].Transactions[1:]...) return out, nil } From 3bb8d2e338b730793c7f9ddd250bb0b428280a08 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 9 Mar 2022 10:42:22 -0800 Subject: [PATCH 291/585] ref impl: Rename Node -> BlockRef This is now done in function names in addition to the type that had been renamed. --- opnode/rollup/driver/driver.go | 4 ++-- opnode/rollup/driver/fake_chain.go | 18 ++++++++-------- opnode/rollup/sync/reference.go | 34 +++++++++++++++--------------- opnode/rollup/sync/start.go | 12 +++++------ opnode/rollup/sync/start_test.go | 10 ++++----- 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 51db4d9e4f20..15fbda18b984 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -43,11 +43,11 @@ type inputImpl struct { } func (i *inputImpl) L1Head(ctx context.Context) (eth.L1BlockRef, error) { - return i.chainSource.L1HeadNode(ctx) + return i.chainSource.L1HeadBlockRef(ctx) } func (i *inputImpl) L2Head(ctx context.Context) (eth.L2BlockRef, error) { - return i.chainSource.L2NodeByNumber(ctx, nil) + return i.chainSource.L2BlockRefByNumber(ctx, nil) } diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 8b88e4b06748..5b5475397a7b 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -89,16 +89,16 @@ type fakeChainSource struct { log log.Logger } -func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { - m.log.Trace("L1NodeByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.l1reorg) +func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { + m.log.Trace("L1BlockRefByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.l1reorg) if l1Num > uint64(m.l1head) { return eth.L1BlockRef{}, ethereum.NotFound } return m.l1s[m.l1reorg][l1Num], nil } -func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) { - m.log.Trace("L1HeadNode", "l1Head", m.l1head, "reorg", m.l1reorg) +func (m *fakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { + m.log.Trace("L1HeadBlockRef", "l1Head", m.l1head, "reorg", m.l1reorg) l := len(m.l1s[m.l1reorg]) if l == 0 { return eth.L1BlockRef{}, ethereum.NotFound @@ -106,8 +106,8 @@ func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error return m.l1s[m.l1reorg][m.l1head], nil } -func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { - m.log.Trace("L2NodeByNumber", "l2Num", l2Num, "l2Head", m.l2head, "reorg", m.l2reorg) +func (m *fakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { + m.log.Trace("L2BlockRefByNumber", "l2Num", l2Num, "l2Head", m.l2head, "reorg", m.l2reorg) if len(m.l2s[m.l2reorg]) == 0 { panic("bad test, no l2 chain") } @@ -121,11 +121,11 @@ func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (e return m.l2s[m.l2reorg][i], nil } -func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { - m.log.Trace("L2NodeByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.l2reorg) +func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { + m.log.Trace("L2BlockRefByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.l2reorg) for i, bl := range m.l2s[m.l2reorg] { if bl.Self.Hash == l2Hash { - return m.L2NodeByNumber(ctx, big.NewInt(int64(i))) + return m.L2BlockRefByNumber(ctx, big.NewInt(int64(i))) } } return eth.L2BlockRef{}, ethereum.NotFound diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go index 65a6d3877018..305258d7cfb7 100644 --- a/opnode/rollup/sync/reference.go +++ b/opnode/rollup/sync/reference.go @@ -26,10 +26,10 @@ type L2Client interface { // ChainSource provides access to the L1 and L2 block graph type ChainSource interface { - L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) - L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) - L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) - L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) + L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) + L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) + L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) + L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) } func NewChainSource(l1 L1Client, l2 L2Client, genesis *rollup.Genesis) *chainSourceImpl { @@ -42,19 +42,19 @@ type chainSourceImpl struct { genesis *rollup.Genesis } -// L1NodeByNumber returns the canonical block and parent ids. -func (src chainSourceImpl) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { - return src.l1NodeByNumber(ctx, new(big.Int).SetUint64(l1Num)) +// L1BlockRefByNumber returns the canonical block and parent ids. +func (src chainSourceImpl) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { + return src.l1BlockRefByNumber(ctx, new(big.Int).SetUint64(l1Num)) } -// L1NodeByNumber returns the canonical head block and parent ids. -func (src chainSourceImpl) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) { - return src.l1NodeByNumber(ctx, nil) +// L1BlockRefByNumber returns the canonical head block and parent ids. +func (src chainSourceImpl) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { + return src.l1BlockRefByNumber(ctx, nil) } -// l1NodeByNumber wraps l1.HeaderByNumber to return an eth.L1Node -// This is internal because the exposed L1NodeByNumber takes uint64 instead of big.Ints -func (src chainSourceImpl) l1NodeByNumber(ctx context.Context, number *big.Int) (eth.L1BlockRef, error) { +// l1BlockRefByNumber wraps l1.HeaderByNumber to return an eth.L1BlockRef +// This is internal because the exposed L1BlockRefByNumber takes uint64 instead of big.Ints +func (src chainSourceImpl) l1BlockRefByNumber(ctx context.Context, number *big.Int) (eth.L1BlockRef, error) { header, err := src.l1.HeaderByNumber(ctx, number) if err != nil { // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. @@ -71,8 +71,8 @@ func (src chainSourceImpl) l1NodeByNumber(ctx context.Context, number *big.Int) }, nil } -// L2NodeByNumber returns the canonical block and parent ids. -func (src chainSourceImpl) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { +// L2BlockRefByNumber returns the canonical block and parent ids. +func (src chainSourceImpl) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { block, err := src.l2.BlockByNumber(ctx, l2Num) if err != nil { // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. @@ -81,8 +81,8 @@ func (src chainSourceImpl) L2NodeByNumber(ctx context.Context, l2Num *big.Int) ( return derive.BlockReferences(block, src.genesis) } -// L2NodeByHash returns the block & parent ids based on the supplied hash. The returned node may not be in the canonical chain -func (src chainSourceImpl) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { +// L2BlockRefByHash returns the block & parent ids based on the supplied hash. The returned BlockRef may not be in the canonical chain +func (src chainSourceImpl) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { block, err := src.l2.BlockByHash(ctx, l2Hash) if err != nil { // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 561d2560350b..7efcb3cdfff6 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -77,14 +77,14 @@ func FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Gene // until it finds the first L2 block that is based on a canonical L1 block. func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (eth.L2BlockRef, error) { // Starting point - l2Head, err := source.L2NodeByNumber(ctx, nil) + l2Head, err := source.L2BlockRefByNumber(ctx, nil) if err != nil { return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 head: %w", err) } reorgDepth := 0 // Walk L2 chain from L2 head to first L2 block which has a L1 Parent that is canonical. May walk to L2 genesis for n := l2Head; ; { - l1header, err := source.L1NodeByNumber(ctx, n.L1Origin.Number) + l1header, err := source.L1BlockRefByNumber(ctx, n.L1Origin.Number) if err != nil { // Generic error, bail out. if !errors.Is(err, ethereum.NotFound) { @@ -105,7 +105,7 @@ func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Gen } // Pull L2 parent for next iteration - n, err = source.L2NodeByHash(ctx, n.Parent.Hash) + n, err = source.L2BlockRefByHash(ctx, n.Parent.Hash) if err != nil { return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.Parent.Hash, err) } @@ -119,7 +119,7 @@ func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Gen // FindL1Range returns a range of L1 block beginning just after `begin`. func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([]eth.BlockID, error) { // Ensure that we start on the expected chain. - if canonicalBegin, err := source.L1NodeByNumber(ctx, begin.Number); err != nil { + if canonicalBegin, err := source.L1BlockRefByNumber(ctx, begin.Number); err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) } else { if canonicalBegin.Self != begin { @@ -127,7 +127,7 @@ func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([] } } - l1head, err := source.L1HeadNode(ctx) + l1head, err := source.L1HeadBlockRef(ctx) if err != nil { return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) } @@ -144,7 +144,7 @@ func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([] prevHash := begin.Hash var res []eth.BlockID for i := begin.Number + 1; i < begin.Number+maxBlocks+1; i++ { - n, err := source.L1NodeByNumber(ctx, i) + n, err := source.L1BlockRefByNumber(ctx, i) if err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) } diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 5304f185b583..78c0ceb97718 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -17,14 +17,14 @@ type fakeChainSource struct { L2 []eth.L2BlockRef } -func (m *fakeChainSource) L1NodeByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { +func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { if l1Num >= uint64(len(m.L1)) { return eth.L1BlockRef{}, ethereum.NotFound } return m.L1[l1Num], nil } -func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error) { +func (m *fakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { l := len(m.L1) if l == 0 { return eth.L1BlockRef{}, ethereum.NotFound @@ -32,7 +32,7 @@ func (m *fakeChainSource) L1HeadNode(ctx context.Context) (eth.L1BlockRef, error return m.L1[l-1], nil } -func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { +func (m *fakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { if len(m.L2) == 0 { panic("bad test, no l2 chain") } @@ -43,10 +43,10 @@ func (m *fakeChainSource) L2NodeByNumber(ctx context.Context, l2Num *big.Int) (e return m.L2[i], nil } -func (m *fakeChainSource) L2NodeByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { +func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { for i, bl := range m.L2 { if bl.Self.Hash == l2Hash { - return m.L2NodeByNumber(ctx, big.NewInt(int64(i))) + return m.L2BlockRefByNumber(ctx, big.NewInt(int64(i))) } } return eth.L2BlockRef{}, ethereum.NotFound From b337367b2ef4460227df402576219475440a168f Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 9 Mar 2022 10:50:58 -0800 Subject: [PATCH 292/585] ref impl: Remove dead TODO comment This was resolved when actually setting the min and max L2 times in the filter batch function. --- opnode/rollup/derive/payload_attributes.go | 1 - 1 file changed, 1 deletion(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 0d5419b541fe..662117525bff 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -284,7 +284,6 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R } // fill the gaps and always ensure at least one L2 block - // TODO: What happens if `highestSeenTimestamp` start rolling into the next epoch (higher than the next L1 block timestamp) var out []*l2.PayloadAttributes for t := l1Info.Time() + config.BlockTime; t <= highestSeenTimestamp; t += config.BlockTime { if bl, ok := l2Blocks[t]; ok { From f2c64cf8b3d9bd7b1924c12c7b11458345736914 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 11 Mar 2022 15:40:47 -0500 Subject: [PATCH 293/585] Add slither to gh actions --- .github/workflows/static-analysis.yml | 48 ++++++++++++++++++++++++++ packages/contracts/package.json | 1 + packages/contracts/slither.config.json | 12 +++++++ 3 files changed, 61 insertions(+) create mode 100644 .github/workflows/static-analysis.yml create mode 100644 packages/contracts/slither.config.json diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 000000000000..1719a3543f61 --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,48 @@ +name: Contracts lint, test and static analysis + +on: + push: + branches: + - 'main' + - 'staging' + pull_request: + workflow_dispatch: + +env: + PYTEST_ADDOPTS: "--color=yes" + +jobs: + slither: + name: Slither run + runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: ./packages/contracts + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'yarn' + - run: yarn install + + - name: Build + run: yarn build + + - name: Lint + run: yarn lint:check + + - name: Test + run: yarn test + + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: '3.8' + + - name: Install Slither + run: pip3 install slither-analyzer + + - name: Run analysis + run: yarn test:slither diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 1b2174c6d207..37c3801a194d 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -9,6 +9,7 @@ }, "scripts": { "test": "hardhat test", + "test:slither": "slither .", "build": "hardhat compile", "lint:ts:check": "eslint .", "lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol'", diff --git a/packages/contracts/slither.config.json b/packages/contracts/slither.config.json new file mode 100644 index 000000000000..1acc8f4111b3 --- /dev/null +++ b/packages/contracts/slither.config.json @@ -0,0 +1,12 @@ +{ + "detectors_to_exclude": "assembly-usage,block-timestamp,naming-convention,solc-version", + "exclude_informational": false, + "exclude_low": false, + "exclude_medium": false, + "exclude_high": false, + "solc_disable_warnings": false, + "hardhat_ignore_compile": false, + "disable_color": false, + "exclude_dependencies": false, + "filter_paths": "contracts/test" +} From 3b45def0dd63fa93a8f6d7871a582bcbe955ef15 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 14 Mar 2022 15:49:57 -0400 Subject: [PATCH 294/585] Address slither warnings This commit fixes slither warnings, either by adding a disable comment or by adding the item to slither.db.json. The benefit of the json file is that it does not clutter up the code, but it also hides the fact that a warning is being disabled. In the future we could reset this by deleting the json file, and running again. --- packages/contracts/contracts/L1/MockL2OutputOracle.sol | 2 +- packages/contracts/slither.db.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 packages/contracts/slither.db.json diff --git a/packages/contracts/contracts/L1/MockL2OutputOracle.sol b/packages/contracts/contracts/L1/MockL2OutputOracle.sol index d95ccc4c91c9..171e3ffa26c5 100644 --- a/packages/contracts/contracts/L1/MockL2OutputOracle.sol +++ b/packages/contracts/contracts/L1/MockL2OutputOracle.sol @@ -62,7 +62,7 @@ contract MockL2OutputOracle { * Computes the L2 block number given a target L2 block timestamp. * @param _timestamp The L2 block timestamp of the target block. */ - function computeL2BlockNumber(uint256 _timestamp) public view returns (uint256) { + function computeL2BlockNumber(uint256 _timestamp) external view returns (uint256) { require(_timestamp >= startingBlockTimestamp, "timestamp prior to startingBlockTimestamp"); return historicalTotalBlocks + (_timestamp - startingBlockTimestamp) / l2BlockTime; } diff --git a/packages/contracts/slither.db.json b/packages/contracts/slither.db.json new file mode 100644 index 000000000000..877ba1a66143 --- /dev/null +++ b/packages/contracts/slither.db.json @@ -0,0 +1 @@ +[{"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1102, "length": 648, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-59) has payable functions:\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#38-58)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L59) has payable functions:\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L38-L58)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "be013b000d4c176d4d893619bdca725d93e4761e4b2e22fa77a64144e53abb26", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 2010, "length": 88, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 97}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}}}], "description": "MockL2OutputOracle.appendL2Output(bytes32,uint256) (contracts/L1/MockL2OutputOracle.sol#45-51) uses a dangerous strict equality:\n\t- require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/MockL2OutputOracle.sol#48)\n", "markdown": "[MockL2OutputOracle.appendL2Output(bytes32,uint256)](contracts/L1/MockL2OutputOracle.sol#L45-L51) uses a dangerous strict equality:\n\t- [require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/MockL2OutputOracle.sol#L48)\n", "first_markdown_element": "contracts/L1/MockL2OutputOracle.sol#L45-L51", "id": "74ee9955ede80e105221045625f8b4f963a0ca8422674891166ad65bdcdba57a", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}, {"type": "node", "name": "OFFSET = uint160(0x1111000000000000000000000000000000001111)", "source_mapping": {"start": 284, "length": 85, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [14], "starting_column": 5, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}}}], "description": "DepositFeed.slitherConstructorConstantVariables() (contracts/L1/DepositFeed.sol#7-59) uses literals with too many digits:\n\t- OFFSET = uint160(0x1111000000000000000000000000000000001111) (contracts/L1/DepositFeed.sol#14)\n", "markdown": "[DepositFeed.slitherConstructorConstantVariables()](contracts/L1/DepositFeed.sol#L7-L59) uses literals with too many digits:\n\t- [OFFSET = uint160(0x1111000000000000000000000000000000001111)](contracts/L1/DepositFeed.sol#L14)\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "14adc89c437b961183112ca2328ae0e07b627d12995c5555d2c2fca5d4dbe1aa", "check": "too-many-digits", "impact": "Informational", "confidence": "Medium"}] From 87b2e566c43be4ead2c1e2e66c3c6026a5fe235f Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 15 Mar 2022 14:42:40 -0700 Subject: [PATCH 295/585] Update golang version to 1.17 for CI Was previously using a matrix form without a matrix being defined. Defaulted to go 1.15. This was causing problems with building. (thank you https://twitter.com/alexellisuk/status/1363588781316661248?lang=en) --- .github/workflows/go-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index b638ff0ab015..3e6bf62223d3 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -15,7 +15,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: ${{ matrix.go-version }} + go-version: 1.17 - name: Checkout code uses: actions/checkout@v2 - name: golangci-lint From 14afdc46b78a25501fcf5e5d68ade46ca66cdde8 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 10 Mar 2022 14:41:43 -0800 Subject: [PATCH 296/585] Update golang dependencies Primarily to update to a newer version of OP's geth client. Also updates all other dependencies to their latest version. --- go.mod | 83 ++++++++++++++++----------------- go.sum | 141 +++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 140 insertions(+), 84 deletions(-) diff --git a/go.mod b/go.mod index a7e07db97e91..80da39b09564 100644 --- a/go.mod +++ b/go.mod @@ -3,66 +3,67 @@ module github.com/ethereum-optimism/optimistic-specs go 1.17 require ( - github.com/ethereum/go-ethereum v1.10.13 - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d + github.com/ethereum/go-ethereum v1.10.16 github.com/holiman/uint256 v1.2.0 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.5 - golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ) require ( - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/VictoriaMetrics/fastcache v1.6.0 // indirect - github.com/btcsuite/btcd v0.21.0-beta // indirect + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect - github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-stack/stack v1.8.0 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/uuid v1.1.5 // indirect - github.com/gorilla/websocket v1.4.2 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.0.2 // indirect - github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 // indirect - github.com/mattn/go-colorable v0.1.8 // indirect - github.com/mattn/go-isatty v0.0.12 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/tsdb v0.7.1 // indirect - github.com/rjeczalik/notify v0.9.1 // indirect - github.com/rs/cors v1.7.0 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect - github.com/stretchr/objx v0.1.1 // indirect + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef // indirect - golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect - golang.org/x/text v0.3.6 // indirect - golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/urfave/cli.v1 v1.20.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.13 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220316014451-777b9479e829 -//replace github.com/ethereum/go-ethereum v1.10.13 => ../reference-optimistic-geth +// For local debugging: +// replace github.com/ethereum/go-ethereum v1.10.16 => ../reference-optimistic-geth diff --git a/go.sum b/go.sum index ccc1a2014340..09dacfce5899 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,9 @@ 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-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +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/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= @@ -35,10 +38,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 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= @@ -62,8 +65,9 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= @@ -82,8 +86,9 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -91,8 +96,9 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= 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 h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -100,8 +106,9 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 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 v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 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= @@ -110,28 +117,32 @@ github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMa github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf h1:sh8rkQZavChcmakYiSlqu2425CHyFXLZZnvm7PDpU8M= +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/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 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 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a h1:ifL2rtsPv8plDlAucTQdLecBgLWph9HeXA0CHDKpxIE= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220107224313-7f6d88bc156a/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220316014451-777b9479e829 h1:3Ez+vrywcpoBoMo9h4UcnNqKi6d7YlS++8+97glKW6I= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220316014451-777b9479e829/go.mod h1:CCsGXufQRqVL3+3t9zMPvzcwFwYlLdZ6enPluWYM64k= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/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= @@ -145,18 +156,22 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/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/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +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= @@ -196,17 +211,22 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.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/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 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -233,8 +253,9 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y 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-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -246,12 +267,11 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 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 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 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.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +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/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= @@ -281,30 +301,36 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.0/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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= github.com/miguelmota/go-ethereum-hdwallet v0.1.1/go.mod h1:f9m9uXokAHA6WNoYOPjj4AqjJS5pquQRiYYj/XSyPYc= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= @@ -349,22 +375,28 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 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/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= 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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -373,10 +405,10 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO 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 v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -389,12 +421,15 @@ github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKk github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -404,6 +439,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ 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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 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= @@ -422,8 +459,10 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -472,12 +511,15 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= +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.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -496,6 +538,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ 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-20180926160741-c2ed4eda69e7/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= @@ -509,6 +552,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -529,24 +573,34 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/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 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/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= @@ -644,8 +698,9 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= 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= From a7b08157c3321905c82ecf0be8fd6933474ea53c Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 16 Mar 2022 03:07:36 +0100 Subject: [PATCH 297/585] update Engine API bindings to match L2 geth --- opnode/l2/api.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 21dc1c4466cf..f11a23d195cc 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -123,8 +123,10 @@ type PayloadAttributes struct { Random Bytes32 `json:"random"` // suggested value for the coinbase field of the new payload SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient"` - // Transactions to build the block with, omitted if the local tx pool of the engine should be used instead + // Transactions to force into the block (always at the start of the transactions list). Transactions []Data `json:"transactions,omitempty"` + // NoTxPool to disable adding any transactions from the transaction-pool. + NoTxPool bool `json:"noTxPool,omitempty"` } type ExecutePayloadStatus string From 05b1badb30b3e2d0cb40fd2097b31ad15662035a Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 11 Mar 2022 11:32:01 -0800 Subject: [PATCH 298/585] ref impl: Add simple batch serialization --- opnode/rollup/derive/batch.go | 70 ++++++++++++++++++++++ opnode/rollup/derive/batch_test.go | 32 ++++++++++ opnode/rollup/derive/payload_attributes.go | 19 +++--- 3 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 opnode/rollup/derive/batch.go create mode 100644 opnode/rollup/derive/batch_test.go diff --git a/opnode/rollup/derive/batch.go b/opnode/rollup/derive/batch.go new file mode 100644 index 000000000000..341fd8bacd25 --- /dev/null +++ b/opnode/rollup/derive/batch.go @@ -0,0 +1,70 @@ +package derive + +import ( + "bytes" + "errors" + + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rlp" +) + +// Batch format +// first byte is type followed by bytstring. +// +// BatchV1Type := 0 +// BatchV1Type ++ RLP([epoch, timestamp, transaction_list] + +const ( + BatchV1Type = iota +) + +type BatchV1 struct { + Epoch uint64 + Timestamp uint64 + Transactions []hexutil.Bytes +} + +type BatchData struct { + Epoch rollup.Epoch // aka l1 num + Timestamp uint64 + // no feeRecipient address input, all fees go to a L2 contract + Transactions []l2.Data +} + +func ParseBatch(data []byte) (BatchData, error) { + var v1 BatchV1 + if err := v1.UnmarshalBinary(data); err != nil { + return BatchData{}, err + } + return BatchData{Epoch: rollup.Epoch(v1.Epoch), Timestamp: v1.Timestamp, Transactions: v1.Transactions}, nil +} + +// // TODO: Is this needed? +// // EncodeRLP implements rlp.Encoder +// func (b *BatchV1) EncodeRLP(w io.Writer) error { +// return rlp.Encode(w, b) +// } + +// MarshalBinary returns the canonical encoding of the batch. +func (b *BatchV1) MarshalBinary() ([]byte, error) { + var buf bytes.Buffer + buf.WriteByte(BatchV1Type) + err := rlp.Encode(&buf, b) + return buf.Bytes(), err +} + +// // TODO: Is this needed? +// // DecodeRLP implements rlp.Decoder +// func (b *BatchV1) DecodeRLP(s *rlp.Stream) error { +// return s.Decode(b) +// } + +// UnmarshalBinary decodes the canonical encoding of batch. +func (batch *BatchV1) UnmarshalBinary(b []byte) error { + if len(b) == 0 { + return errors.New("Batch too short") + } + return rlp.DecodeBytes(b[1:], batch) +} diff --git a/opnode/rollup/derive/batch_test.go b/opnode/rollup/derive/batch_test.go new file mode 100644 index 000000000000..e4776729cae7 --- /dev/null +++ b/opnode/rollup/derive/batch_test.go @@ -0,0 +1,32 @@ +package derive + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/assert" +) + +func TestBatchRoundTrip(t *testing.T) { + batches := []BatchV1{ + { + Epoch: 0, + Timestamp: 0, + Transactions: []hexutil.Bytes{}, + }, + { + Epoch: 1, + Timestamp: 1647026951, + Transactions: []hexutil.Bytes{[]byte{0, 0, 0}, []byte{0x76, 0xfd, 0x7c}}, + }, + } + + for i, batch := range batches { + enc, err := batch.MarshalBinary() + assert.NoError(t, err) + var dec BatchV1 + err = dec.UnmarshalBinary(enc) + assert.NoError(t, err) + assert.Equal(t, batch, dec, "Batch not equal test case %v", i) + } +} diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 662117525bff..6b2ca501b633 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -186,13 +186,19 @@ func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) if to := tx.To(); to != nil && *to == config.BatchInboxAddress { seqDataSubmitter, err := l1Signer.Sender(tx) if err != nil { + // TODO: log error continue // bad signature, ignore } // some random L1 user might have sent a transaction to our batch inbox, ignore them if seqDataSubmitter != config.BatchSenderAddress { continue // not an authorized batch submitter, ignore } - out = append(out, ParseBatches(tx.Data())...) + batch, err := ParseBatch(tx.Data()) + if err != nil { + // TODO: log error + continue + } + out = append(out, batch) } } return @@ -328,14 +334,3 @@ func DeriveDeposits(l1Info L1Info, receipts []*types.Receipt) ([]l2.Data, error) } return encodedTxs, nil } - -type BatchData struct { - Epoch rollup.Epoch // aka l1 num - Timestamp uint64 - // no feeRecipient address input, all fees go to a L2 contract - Transactions []l2.Data -} - -func ParseBatches(data l2.Data) []BatchData { - return nil // TODO -} From 71ae66826d62c71dbc38a1d348977e1b61f1acf6 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 16 Mar 2022 04:11:35 +0100 Subject: [PATCH 299/585] rollup/derive: encode/decode multiple batches (l2 blocks) per sequencer transaction --- opnode/rollup/derive/batch.go | 145 ++++++++++++++++----- opnode/rollup/derive/batch_test.go | 31 +++-- opnode/rollup/derive/payload_attributes.go | 11 +- 3 files changed, 142 insertions(+), 45 deletions(-) diff --git a/opnode/rollup/derive/batch.go b/opnode/rollup/derive/batch.go index 341fd8bacd25..03517eedbf92 100644 --- a/opnode/rollup/derive/batch.go +++ b/opnode/rollup/derive/batch.go @@ -3,68 +3,151 @@ package derive import ( "bytes" "errors" + "fmt" + "io" + "sync" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rlp" ) // Batch format -// first byte is type followed by bytstring. +// first byte is type followed by bytestring. // // BatchV1Type := 0 -// BatchV1Type ++ RLP([epoch, timestamp, transaction_list] +// batchV1 := BatchV1Type ++ RLP([epoch, timestamp, transaction_list] +// +// An empty input is not a valid batch. +// +// Batch-bundle format +// first byte is type followed by bytestring +// +// payload := RLP([batch_0, batch_1, ..., batch_N]) +// bundleV1 := BatchBundleV1Type ++ payload +// bundleV2 := BatchBundleV2Type ++ compress(payload) # TODO: compressed bundle of batches +// +// An empty input is not a valid bundle. +// +// Note: the type system is based on L1 typed transactions. + +// encodeBufferPool holds temporary encoder buffers batch encoding +var encodeBufferPool = sync.Pool{ + New: func() interface{} { return new(bytes.Buffer) }, +} const ( BatchV1Type = iota ) +const ( + BatchBundleV1Type = iota + BatchBundleV2Type +) + type BatchV1 struct { - Epoch uint64 - Timestamp uint64 + Epoch rollup.Epoch // aka l1 num + Timestamp uint64 + // no feeRecipient address input, all fees go to a L2 contract Transactions []hexutil.Bytes } type BatchData struct { - Epoch rollup.Epoch // aka l1 num - Timestamp uint64 - // no feeRecipient address input, all fees go to a L2 contract - Transactions []l2.Data + BatchV1 + // batches may contain additional data with new upgrades } -func ParseBatch(data []byte) (BatchData, error) { - var v1 BatchV1 - if err := v1.UnmarshalBinary(data); err != nil { - return BatchData{}, err +func DecodeBatches(config *rollup.Config, r io.Reader) ([]*BatchData, error) { + var typeData [1]byte + if _, err := r.Read(typeData[:]); err != nil { + return nil, fmt.Errorf("failed to read batch bundle type byte: %v", err) + } + switch typeData[0] { + case BatchBundleV1Type: + var out []*BatchData + if err := rlp.Decode(r, &out); err != nil { + return nil, fmt.Errorf("failed to decode v1 batches list: %v", err) + } + return out, nil + case BatchBundleV2Type: + // TODO: implement compression of a bundle of batches + return nil, errors.New("bundle v2 not supported yet") + default: + return nil, fmt.Errorf("unrecognized batch bundle type: %d", typeData[0]) } - return BatchData{Epoch: rollup.Epoch(v1.Epoch), Timestamp: v1.Timestamp, Transactions: v1.Transactions}, nil } -// // TODO: Is this needed? -// // EncodeRLP implements rlp.Encoder -// func (b *BatchV1) EncodeRLP(w io.Writer) error { -// return rlp.Encode(w, b) -// } +func EncodeBatches(config *rollup.Config, batches []*BatchData, w io.Writer) error { + // default to encode as v1 (no compression). Config may change this in the future. + bundleType := byte(BatchBundleV1Type) + + if _, err := w.Write([]byte{bundleType}); err != nil { + return fmt.Errorf("failed to encode batch type") + } + switch bundleType { + case BatchBundleV1Type: + if err := rlp.Encode(w, batches); err != nil { + return fmt.Errorf("failed to encode RLP-list payload of v1 bundle: %v", err) + } + return nil + case BatchBundleV2Type: + return errors.New("bundle v2 not supported yet") + default: + return fmt.Errorf("unrecognized batch bundle type: %d", bundleType) + } +} + +// EncodeRLP implements rlp.Encoder +func (b *BatchData) EncodeRLP(w io.Writer) error { + buf := encodeBufferPool.Get().(*bytes.Buffer) + defer encodeBufferPool.Put(buf) + buf.Reset() + if err := b.encodeTyped(buf); err != nil { + return err + } + return rlp.Encode(w, buf.Bytes()) +} // MarshalBinary returns the canonical encoding of the batch. -func (b *BatchV1) MarshalBinary() ([]byte, error) { +func (b *BatchData) MarshalBinary() ([]byte, error) { var buf bytes.Buffer - buf.WriteByte(BatchV1Type) - err := rlp.Encode(&buf, b) + err := b.encodeTyped(&buf) return buf.Bytes(), err } -// // TODO: Is this needed? -// // DecodeRLP implements rlp.Decoder -// func (b *BatchV1) DecodeRLP(s *rlp.Stream) error { -// return s.Decode(b) -// } +func (b *BatchData) encodeTyped(buf *bytes.Buffer) error { + buf.WriteByte(BatchV1Type) + return rlp.Encode(buf, &b.BatchV1) +} + +// DecodeRLP implements rlp.Decoder +func (b *BatchData) DecodeRLP(s *rlp.Stream) error { + if b == nil { + return errors.New("cannot decode into nil BatchData") + } + v, err := s.Bytes() + if err != nil { + return err + } + return b.decodeTyped(v) +} // UnmarshalBinary decodes the canonical encoding of batch. -func (batch *BatchV1) UnmarshalBinary(b []byte) error { - if len(b) == 0 { - return errors.New("Batch too short") +func (b *BatchData) UnmarshalBinary(data []byte) error { + if b == nil { + return errors.New("cannot decode into nil BatchData") + } + return b.decodeTyped(data) +} + +func (b *BatchData) decodeTyped(data []byte) error { + if len(data) == 0 { + return fmt.Errorf("batch too short") + } + switch data[0] { + case BatchV1Type: + return rlp.DecodeBytes(data[1:], &b.BatchV1) + default: + return fmt.Errorf("unrecognized batch type: %d", data[0]) } - return rlp.DecodeBytes(b[1:], batch) } diff --git a/opnode/rollup/derive/batch_test.go b/opnode/rollup/derive/batch_test.go index e4776729cae7..4914222620fc 100644 --- a/opnode/rollup/derive/batch_test.go +++ b/opnode/rollup/derive/batch_test.go @@ -1,32 +1,45 @@ package derive import ( + "bytes" "testing" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/assert" ) func TestBatchRoundTrip(t *testing.T) { - batches := []BatchV1{ + batches := []*BatchData{ { - Epoch: 0, - Timestamp: 0, - Transactions: []hexutil.Bytes{}, + BatchV1: BatchV1{ + Epoch: 0, + Timestamp: 0, + Transactions: []hexutil.Bytes{}, + }, }, { - Epoch: 1, - Timestamp: 1647026951, - Transactions: []hexutil.Bytes{[]byte{0, 0, 0}, []byte{0x76, 0xfd, 0x7c}}, + BatchV1: BatchV1{ + Epoch: 1, + Timestamp: 1647026951, + Transactions: []hexutil.Bytes{[]byte{0, 0, 0}, []byte{0x76, 0xfd, 0x7c}}, + }, }, } for i, batch := range batches { enc, err := batch.MarshalBinary() assert.NoError(t, err) - var dec BatchV1 + var dec BatchData err = dec.UnmarshalBinary(enc) assert.NoError(t, err) - assert.Equal(t, batch, dec, "Batch not equal test case %v", i) + assert.Equal(t, batch, &dec, "Batch not equal test case %v", i) } + var buf bytes.Buffer + err := EncodeBatches(&rollup.Config{}, batches, &buf) + assert.NoError(t, err) + out, err := DecodeBatches(&rollup.Config{}, &buf) + assert.NoError(t, err) + assert.Equal(t, batches, out) } diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 6b2ca501b633..5d189812e08a 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -1,6 +1,7 @@ package derive import ( + "bytes" "encoding/binary" "fmt" "math/big" @@ -180,7 +181,7 @@ func UserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, return out, nil } -func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) (out []BatchData) { +func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) (out []*BatchData) { l1Signer := config.L1Signer() for _, tx := range txs { if to := tx.To(); to != nil && *to == config.BatchInboxAddress { @@ -193,18 +194,18 @@ func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) if seqDataSubmitter != config.BatchSenderAddress { continue // not an authorized batch submitter, ignore } - batch, err := ParseBatch(tx.Data()) + batches, err := DecodeBatches(config, bytes.NewReader(tx.Data())) if err != nil { // TODO: log error continue } - out = append(out, batch) + out = append(out, batches...) } } return } -func FilterBatches(config *rollup.Config, epoch rollup.Epoch, minL2Time uint64, maxL2Time uint64, batches []BatchData) (out []BatchData) { +func FilterBatches(config *rollup.Config, epoch rollup.Epoch, minL2Time uint64, maxL2Time uint64, batches []*BatchData) (out []*BatchData) { uniqueTime := make(map[uint64]struct{}) for _, batch := range batches { if batch.Epoch != epoch { @@ -244,7 +245,7 @@ type L2Info interface { // - The L2 information of the block the new derived blocks build on // // This is a pure function. -func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []BatchData, l2Info L2Info) ([]*l2.PayloadAttributes, error) { +func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []*BatchData, l2Info L2Info) ([]*l2.PayloadAttributes, error) { // Retrieve the deposits of this epoch (all deposits from the first block) deposits, err := DeriveDeposits(l1Info, receipts) if err != nil { From c3840830d1e7f20cc6a8f6e1bcd1591fb8c27c21 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 11 Mar 2022 14:56:51 -0800 Subject: [PATCH 300/585] ref impl: Simple batch submitter Note: very simple. --- opnode/bss/submitter.go | 103 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 opnode/bss/submitter.go diff --git a/opnode/bss/submitter.go b/opnode/bss/submitter.go new file mode 100644 index 000000000000..384adc6db150 --- /dev/null +++ b/opnode/bss/submitter.go @@ -0,0 +1,103 @@ +package bss + +import ( + "context" + "crypto/ecdsa" + "errors" + "math/big" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/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/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +type BatchSubmitter struct { + Client *ethclient.Client + ToAddress common.Address + ChainID *big.Int + PrivKey *ecdsa.PrivateKey +} + +// func NewSubmitter(client ethclient.Client, addr common.Address) *BatchSubmitter { +// return &BatchSubmitter{client: client, addr: addr} +// } + +// Submit creates & submits a batch to L1. Blocks until the transaction is included. +// Return the tx hash as well as a possible error. +func (b *BatchSubmitter) Submit(batch *derive.BatchV1) (common.Hash, error) { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + enc, err := batch.MarshalBinary() + if err != nil { + return common.Hash{}, err + } + + addr := crypto.PubkeyToAddress(b.PrivKey.PublicKey) + nonce, err := b.Client.PendingNonceAt(ctx, addr) + if err != nil { + return common.Hash{}, err + } + + tip, err := b.Client.SuggestGasTipCap(ctx) + if err != nil { + return common.Hash{}, err + } + fee, err := b.Client.SuggestGasPrice(ctx) + if err != nil { + return common.Hash{}, err + } + + rawTx := &types.DynamicFeeTx{ + ChainID: b.ChainID, + Nonce: nonce, + To: &b.ToAddress, + GasTipCap: tip, + GasFeeCap: fee, + Data: enc, + } + msg := ethereum.CallMsg{ + From: addr, + To: rawTx.To, + GasTipCap: rawTx.GasTipCap, + GasFeeCap: rawTx.GasFeeCap, + Data: rawTx.Data, + } + gas, err := b.Client.EstimateGas(ctx, msg) + if err != nil { + return common.Hash{}, err + } + rawTx.Gas = gas + + tx, err := types.SignNewTx(b.PrivKey, types.LatestSignerForChainID(b.ChainID), rawTx) + if err != nil { + return common.Hash{}, err + } + + err = b.Client.SendTransaction(ctx, tx) + if err != nil { + return common.Hash{}, err + } + + timeout := time.After(4 * time.Second) + + for { + receipt, err := b.Client.TransactionReceipt(context.Background(), tx.Hash()) + if receipt != nil { + return tx.Hash(), nil + } else if err != nil && !errors.Is(err, ethereum.NotFound) { + return common.Hash{}, err + } + <-time.After(150 * time.Millisecond) + + select { + case <-timeout: + return common.Hash{}, errors.New("timeout") + default: + } + } + +} From 7d1699efc17054b20ee8a471aa9d450f115b6d1b Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 16 Mar 2022 04:23:21 +0100 Subject: [PATCH 301/585] update batch submitter to submit bundles of batches and bundles can have compression --- opnode/bss/submitter.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/opnode/bss/submitter.go b/opnode/bss/submitter.go index 384adc6db150..3fbb3708f4e3 100644 --- a/opnode/bss/submitter.go +++ b/opnode/bss/submitter.go @@ -1,12 +1,15 @@ package bss import ( + "bytes" "context" "crypto/ecdsa" "errors" "math/big" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -26,13 +29,14 @@ type BatchSubmitter struct { // return &BatchSubmitter{client: client, addr: addr} // } -// Submit creates & submits a batch to L1. Blocks until the transaction is included. +// Submit creates & submits batches to L1. Blocks until the transaction is included. // Return the tx hash as well as a possible error. -func (b *BatchSubmitter) Submit(batch *derive.BatchV1) (common.Hash, error) { +func (b *BatchSubmitter) Submit(config *rollup.Config, batches []*derive.BatchData) (common.Hash, error) { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() - enc, err := batch.MarshalBinary() - if err != nil { + + var buf bytes.Buffer + if err := derive.EncodeBatches(config, batches, &buf); err != nil { return common.Hash{}, err } @@ -57,7 +61,7 @@ func (b *BatchSubmitter) Submit(batch *derive.BatchV1) (common.Hash, error) { To: &b.ToAddress, GasTipCap: tip, GasFeeCap: fee, - Data: enc, + Data: buf.Bytes(), } msg := ethereum.CallMsg{ From: addr, From 0256f4c6077bd1bf4228428e43482a969b113774 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 16 Mar 2022 04:52:47 +0100 Subject: [PATCH 302/585] specs/rollup-node: define encoding for bundle of batches, and how we apply compression to a whole bundle of batches (algorithm TBD) --- specs/rollup-node.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 87fd0dd98b05..29afb5048674 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -121,7 +121,7 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi - Sequencer batches, derived from the transactions: - The transaction receiver is the sequencer inbox address - The transaction must be signed by a recognized sequencer account - - The calldata may contain any number of batches. *(calldata will be substituted with blob data in the future.)* + - The calldata may contain a bundle of batches. *(calldata will be substituted with blob data in the future.)* - Batches not matching filter criteria are ignored: - `batch.epoch == sequencing_window.epoch`, i.e. for this sequencing window - `(batch.timestamp - genesis_l2_timestamp) % block_time == 0`, i.e. timestamp is aligned @@ -131,9 +131,22 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi [random]: https://eips.ethereum.org/EIPS/eip-4399 -Batches are formatted as: `type ++ RLP([epoch, timestamp, transaction_list])` +A bundle of batches is versioned by prefixing with a bundle version byte: `bundle = bundle_version ++ bundle_data`. + +Bundle versions: + +- `0`: `bundle_data = RLP([batch_0, batch_1, ..., batch_N])` +- `1`: `bundle_data = compress(RLP([batch_0, batch_1, ..., batch_N]))` (compression algorithm TBD) + +A batch is also versioned by prefixing with a version byte: `batch = batch_version ++ batch_data` +and encoded as a byte-string (including version prefix byte) in the bundle RLP list. + +Batch versions: + +- `0`: `batch_data = RLP([epoch, timestamp, transaction_list])`, where each + +Batch contents: -- `type` is a single `byte` identifying the batch format - `epoch` is the sequencing window epoch, i.e. the first L1 block number - `timestamp` is the L2 timestamp of the block - `transaction_list` is an RLP encoded list of [EIP-2718] encoded transactions From ac1708b830c0cd1fac686d9d9bc6c66f1302bddc Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 16 Mar 2022 17:27:51 +0100 Subject: [PATCH 303/585] specs/rollup-node: explicitly exclude deposit-type transactions from batches --- specs/rollup-node.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 29afb5048674..1d521adc457f 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -128,6 +128,7 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi - `min_l2_timestamp < batch.timestamp < max_l2_timestamp`, i.e. timestamp is within range - The batch is the first batch with `batch.timestamp` in this sequencing window, i.e. one batch per L2 block number + - The batch only contains sequenced transactions, i.e. it must NOT contain any Deposit-type transactions. [random]: https://eips.ethereum.org/EIPS/eip-4399 @@ -149,7 +150,7 @@ Batch contents: - `epoch` is the sequencing window epoch, i.e. the first L1 block number - `timestamp` is the L2 timestamp of the block -- `transaction_list` is an RLP encoded list of [EIP-2718] encoded transactions +- `transaction_list` is an RLP encoded list of [EIP-2718] encoded transactions. [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 @@ -207,7 +208,8 @@ The object's properties must be set as follows: - `timestamp` is set to the timestamp of the L1 block. - `random` is set to the *random* L1 block attribute - `suggestedFeeRecipient` is set to an address determined by the system -- `transactions` is an array of the derived deposits, encoded as per the two preceding sections. +- `transactions` is an array of the derived transactions: deposited transactions and sequenced transactions. + All encoded with [EIP-2718]. Sequenced transactions must exclude any Deposit-type transactions. [expanded-payload]: exec-engine.md#extended-payloadattributesv1 [`PayloadAttributesV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 From f8ccf4a14b89029deefa20a3c004185de56daff4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 16 Mar 2022 17:46:17 +0100 Subject: [PATCH 304/585] specs: clarify deposits position in block and why we repeat l1-info txs --- specs/deposits.md | 5 ++--- specs/rollup-node.md | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 7952dee69a37..98516c3aa6d9 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -77,10 +77,9 @@ for a variable-length encoding scheme. Although we define only one new transaction type, we can distinguish between two kinds of deposited transactions, based on their positioning in the L2 block: -1. The first transaction MUST be a [L1 attributes deposited transaction][l1-attr-deposit], followed - by +1. The first transaction MUST be a [L1 attributes deposited transaction][l1-attr-deposit], followed by 2. an array of zero-or-more [user-deposited transactions][user-deposited] submitted to the deposit - feed contract on L1. + feed contract on L1. User-deposited transactions are only present in the first block of a L2 epoch. We only define a single new transaction type in order to minimize modifications to L1 client software, and complexity in general. diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 1d521adc457f..56631ba485b7 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -167,6 +167,8 @@ entries. [deposit-contract-spec]: deposits.md#deposit-contract Each of the derived `PayloadAttributes` starts with a L1 Attributes transaction. +Like other derived deposits, this does not have to be batch-submitted, and exposes the required L1 information for the +process of finding the sync starting point of the L2 chain, without requiring L2 state access. The [User-deposited] transactions are all put in the first of the derived `PayloadAttributes`, inserted after the L1 Attributes transaction, before any [sequenced][g-sequencing] transactions. From 67ca957e6a3b6eb32f9356ba6bcc4ff8b50f5fcc Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 16 Mar 2022 20:02:10 +0100 Subject: [PATCH 305/585] opnode/rollup/derive: batch ReadFull and comment fix --- opnode/rollup/derive/batch.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opnode/rollup/derive/batch.go b/opnode/rollup/derive/batch.go index 03517eedbf92..7c37fe73f44e 100644 --- a/opnode/rollup/derive/batch.go +++ b/opnode/rollup/derive/batch.go @@ -31,7 +31,7 @@ import ( // // Note: the type system is based on L1 typed transactions. -// encodeBufferPool holds temporary encoder buffers batch encoding +// encodeBufferPool holds temporary encoder buffers for batch encoding var encodeBufferPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } @@ -59,7 +59,7 @@ type BatchData struct { func DecodeBatches(config *rollup.Config, r io.Reader) ([]*BatchData, error) { var typeData [1]byte - if _, err := r.Read(typeData[:]); err != nil { + if _, err := io.ReadFull(r, typeData[:]); err != nil { return nil, fmt.Errorf("failed to read batch bundle type byte: %v", err) } switch typeData[0] { From 1b19bba839e546cbadab51b2f5570fdb4af758ec Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 17 Mar 2022 11:31:06 -0700 Subject: [PATCH 306/585] ref impl: Sequencing (#249) Adds a sequencer mode that runs ahead of the verifier. Also changes the block timestamps + implements epochs correctly in the batch submission. Does not reconcile sequenced blocks with verified blocks (but does check at least one block for consistency between a full verifier and full sequencer in the e2e test) It is possible for the sequencer to get behind the L1 chain tip and it does not handle re-orgs well. --- opnode/node/node.go | 17 ++- opnode/rollup/derive/payload_attributes.go | 27 ++-- opnode/rollup/driver/driver.go | 14 +- opnode/rollup/driver/state.go | 74 +++++++++-- opnode/rollup/driver/state_test.go | 9 +- opnode/rollup/driver/step.go | 84 ++++++++++-- opnode/test/geth.go | 6 +- opnode/test/setup.go | 8 +- opnode/test/system_test.go | 143 ++++++++++++++++++--- 9 files changed, 319 insertions(+), 63 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index 2ba804c404fa..0846bd8662a3 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -2,9 +2,11 @@ package node import ( "context" + "crypto/ecdsa" "fmt" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/bss" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" @@ -29,7 +31,9 @@ type Config struct { L1Hash common.Hash // Block hash of L1 after (not incl.) which L1 starts deriving blocks L1Num uint64 // Block number of L1 matching the l1-hash - Rollup rollup.Config + Rollup rollup.Config + Sequencer bool + SubmitterPrivKey *ecdsa.PrivateKey } // Check verifies that the given configuration makes sense @@ -88,7 +92,16 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { EthBackend: ethclient.NewClient(backend), Log: log.New("engine_client", i), } - engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i)) + var submitter *bss.BatchSubmitter + if cfg.Sequencer { + submitter = &bss.BatchSubmitter{ + Client: ethclient.NewClient(l1Node), + ToAddress: cfg.Rollup.BatchInboxAddress, + ChainID: cfg.Rollup.L1ChainID, + PrivKey: cfg.SubmitterPrivKey, + } + } + engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), submitter, cfg.Sequencer) l2Engines = append(l2Engines, engine) } diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 5d189812e08a..2cd192817ece 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -181,7 +181,8 @@ func UserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, return out, nil } -func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) (out []*BatchData) { +func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) ([]*BatchData, error) { + var out []*BatchData l1Signer := config.L1Signer() for _, tx := range txs { if to := tx.To(); to != nil && *to == config.BatchInboxAddress { @@ -192,17 +193,18 @@ func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) } // some random L1 user might have sent a transaction to our batch inbox, ignore them if seqDataSubmitter != config.BatchSenderAddress { + // TODO: log/record metric continue // not an authorized batch submitter, ignore } batches, err := DecodeBatches(config, bytes.NewReader(tx.Data())) if err != nil { - // TODO: log error + // TODO: log/record metric continue } out = append(out, batches...) } } - return + return out, nil } func FilterBatches(config *rollup.Config, epoch rollup.Epoch, minL2Time uint64, maxL2Time uint64, batches []*BatchData) (out []*BatchData) { @@ -245,7 +247,7 @@ type L2Info interface { // - The L2 information of the block the new derived blocks build on // // This is a pure function. -func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []*BatchData, l2Info L2Info) ([]*l2.PayloadAttributes, error) { +func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []*BatchData, l2Info L2Info, minL2Time, maxL2Time uint64) ([]*l2.PayloadAttributes, error) { // Retrieve the deposits of this epoch (all deposits from the first block) deposits, err := DeriveDeposits(l1Info, receipts) if err != nil { @@ -265,14 +267,8 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R // Collect all L2 batches, the batches may be out-of-order, or possibly missing. l2Blocks := make(map[uint64]*l2.PayloadAttributes) - highestSeenTimestamp := l1Info.Time() for _, batch := range seqWindow { - // Track the last batch we've seen (gaps will be filled with empty L2 blocks) - if batch.Timestamp > highestSeenTimestamp { - highestSeenTimestamp = batch.Timestamp - } - txns := make([]l2.Data, 0, len(batch.Transactions)+1) txns = append(txns, l1InfoTx) txns = append(txns, batch.Transactions...) @@ -285,14 +281,9 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R } } - // If there are no submitted batches, at least derive the deposit block. - if len(seqWindow) == 0 { - highestSeenTimestamp += config.BlockTime - } - // fill the gaps and always ensure at least one L2 block var out []*l2.PayloadAttributes - for t := l1Info.Time() + config.BlockTime; t <= highestSeenTimestamp; t += config.BlockTime { + for t := minL2Time; t < maxL2Time; t += config.BlockTime { if bl, ok := l2Blocks[t]; ok { out = append(out, bl) } else { @@ -304,9 +295,13 @@ func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.R Random: randomnessSeed, SuggestedFeeRecipient: config.FeeRecipientAddress, Transactions: txns, + // we are verifying, not sequencing, we've all transactions and do not pull from the tx-pool + // (that would make the block derivation non-deterministic) + NoTxPool: true, }) } } + // TODO: Assert that this does not panic here (i.e. make sure that len(out) > 0) // Force deposits into the first block. TODO: Clean up L1 Info handling. out[0].Transactions = append(append(make([]l2.Data, 0), deposits...), out[0].Transactions[1:]...) diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 15fbda18b984..aaecc669b96e 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -6,7 +6,9 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -14,7 +16,15 @@ type Driver struct { s *state } -func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger) *Driver { +type BatchSubmitter interface { + Submit(config *rollup.Config, batches []*derive.BatchData) (common.Hash, error) +} + +func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { + if sequencer && submitter == nil { + log.Error("Bad configuration") + // TODO: return error + } input := &inputImpl{ chainSource: sync.NewChainSource(l1, l2, &cfg.Genesis), genesis: &cfg.Genesis, @@ -26,7 +36,7 @@ func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger) *D rpc: l2, } return &Driver{ - s: NewState(log, cfg, input, output), + s: NewState(log, cfg, input, output, submitter, sequencer), } } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 34340f095605..de6afcb4632c 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/log" ) @@ -19,35 +20,42 @@ type inputInterface interface { type outputInterface interface { step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) + newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) } type state struct { // Chain State - l1Head eth.BlockID // Latest recorded head of the L1 Chain - l1Base eth.BlockID // L1 Parent of L2 Head block - l2Head eth.BlockID // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) - l2Finalized eth.BlockID // L2 Block that will never be reversed - l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. + l1Head eth.BlockID // Latest recorded head of the L1 Chain + l1Base eth.BlockID // L1 Parent of L2 Head block + l2UnsafeHead eth.BlockID // L2 Unsafe Head - this is the head block from the sequencer + l1Origin eth.BlockID // L1 Origin of the L2 Unsafe head. For sequencing only. + l2Head eth.BlockID // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) + l2Finalized eth.BlockID // L2 Block that will never be reversed + l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. // Rollup config - Config rollup.Config + Config rollup.Config + sequencer bool // Connections (in/out) l1Heads <-chan eth.L1BlockRef input inputInterface output outputInterface + bss BatchSubmitter log log.Logger done chan struct{} } -func NewState(log log.Logger, config rollup.Config, input inputInterface, output outputInterface) *state { +func NewState(log log.Logger, config rollup.Config, input inputInterface, output outputInterface, submitter BatchSubmitter, sequencer bool) *state { return &state{ - Config: config, - done: make(chan struct{}), - log: log, - input: input, - output: output, + Config: config, + done: make(chan struct{}), + log: log, + input: input, + output: output, + bss: submitter, + sequencer: sequencer, } } @@ -62,6 +70,8 @@ func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error } s.l1Head = l1Head.Self + s.l1Origin = s.l1Head + s.l2UnsafeHead = l2Head.Self // TODO: Makes sense? s.l2Head = l2Head.Self s.l1Base = l2Head.L1Origin s.l1Heads = l1Heads @@ -108,6 +118,13 @@ func (s *state) sequencingWindow() ([]eth.BlockID, bool) { func (s *state) loop() { s.log.Info("State loop started") ctx := context.Background() + var l2BlockCreation <-chan time.Time + if s.sequencer { + l2BlockCreationTicker := time.NewTicker(time.Duration(s.Config.BlockTime) * time.Second) + defer l2BlockCreationTicker.Stop() + l2BlockCreation = l2BlockCreationTicker.C + } + // l1Poll := time.NewTicker(1 * time.Second) // l2Poll := time.NewTicker(1 * time.Second) stepRequest := make(chan struct{}, 1) @@ -130,6 +147,34 @@ func (s *state) loop() { // case <-l2Poll.C: case <-s.done: return + case <-l2BlockCreation: + // 1. Check if new epoch (new L1 head) + firstOfEpoch := false + if s.l1Head != s.l1Origin { + firstOfEpoch = true + s.l1Origin = s.l1Head + } + // Don't produce blocks until past the L1 genesis + if s.l1Origin.Number <= s.Config.Genesis.L1.Number { + continue + } + // 2. Ask output to create new block + newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2UnsafeHead, s.l1Origin, firstOfEpoch) + if err != nil { + s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2UnsafeHead, "l1Origin", s.l1Origin) + continue + } + // 3. Update unsafe l2 head + epoch + s.l2UnsafeHead = newUnsafeL2Head + s.log.Trace("Created new l2 block", "l2UnsafeHead", s.l2UnsafeHead) + // 4. Ask for batch submission + go func() { + _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches + if err != nil { + s.log.Error("Error submitting batch", "err", err) + } + }() + case newL1Head := <-s.l1Heads: s.log.Trace("Received new L1 Head", "new_head", newL1Head.Self, "old_head", s.l1Head) // Check if we have a stutter step. May be due to a L1 Poll operation. @@ -153,6 +198,7 @@ func (s *state) loop() { continue } s.l1Head = newL1Head.Self + // TODO: Unsafe head here s.l1Window = nil s.l1Base = nextL2Head.L1Origin s.l2Head = nextL2Head.Self @@ -162,6 +208,10 @@ func (s *state) loop() { requestStep() } case <-stepRequest: + if s.sequencer { + s.log.Trace("Skipping extension based on L1 chain as sequencer") + continue + } s.log.Trace("Got step request") // Extend cached window if we do not have enough saved blocks if len(s.l1Window) < int(s.Config.SeqWindowSize) { diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 81de6883ae5e..539baa6fd140 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" @@ -43,6 +44,10 @@ func (fn outputHandlerFn) step(ctx context.Context, l2Head eth.BlockID, l2Finali return fn(ctx, l2Head, l2Finalized, l1Window) } +func (fn outputHandlerFn) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { + panic("Unimplemented") +} + type outputArgs struct { l2Head eth.BlockID l2Finalized eth.BlockID @@ -134,8 +139,8 @@ func (tc *stateTestCase) Run(t *testing.T) { r := <-outputReturn return r.l2Head, r.err } - config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis} - state := NewState(log, config, &inputImpl{chainSource: chainSource, genesis: &tc.genesis}, outputHandlerFn(outputHandler)) + config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis, BlockTime: 2} + state := NewState(log, config, &inputImpl{chainSource: chainSource, genesis: &tc.genesis}, outputHandlerFn(outputHandler), nil, false) defer func() { assert.NoError(t, state.Close(), "Error closing state") }() diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 9d6fe67a226b..7d37d6791463 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -2,6 +2,7 @@ package driver import ( "context" + "errors" "fmt" "time" @@ -11,6 +12,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -36,6 +38,63 @@ type outputImpl struct { Config rollup.Config } +func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { + d.log.Info("creating new block", "l2Parent", l2Parent, "l1Origin", l1Origin, "includeDeposits", includeDeposits) + fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) + defer cancel() + l2Info, err := d.rpc.BlockByHash(fetchCtx, l2Parent.Hash) + if err != nil { + return l2Parent, nil, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Parent, err) + } + l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Origin) + if err != nil { + return l2Parent, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) + } + + timestamp := l2Info.Time() + d.Config.BlockTime + if timestamp >= l1Info.Time() { + return l2Parent, nil, errors.New("L2 Timestamp is too large") + } + + var receipts types.Receipts + if includeDeposits { + receipts, err = d.dl.FetchReceipts(fetchCtx, l1Origin) + if err != nil { + return l2Parent, nil, fmt.Errorf("failed to fetch receipts of %s: %v", l1Origin, err) + } + + } + deposits, err := derive.DeriveDeposits(l1Info, receipts) + d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Parent, "l1Origin", l1Origin) + if err != nil { + return l2Parent, nil, fmt.Errorf("failed to derive deposits: %v", err) + } + + depositStart := len(deposits) + + attrs := &l2.PayloadAttributes{ + Timestamp: hexutil.Uint64(timestamp), + Random: l2.Bytes32(l1Info.MixDigest()), + SuggestedFeeRecipient: d.Config.FeeRecipientAddress, + Transactions: deposits, + NoTxPool: false, + } + + payload, err := AddBlock(ctx, d.log, d.rpc, l2Parent, l2Finalized.Hash, attrs) + if err != nil { + return l2Parent, nil, fmt.Errorf("failed to extend L2 chain: %v", err) + } + batch := &derive.BatchData{ + BatchV1: derive.BatchV1{ + Epoch: rollup.Epoch(l1Info.NumberU64()), + Timestamp: uint64(payload.Timestamp), + Transactions: payload.Transactions[depositStart:], + }, + } + + return payload.ID(), batch, nil +} + // DriverStep derives and processes one or more L2 blocks from the given sequencing window of L1 blocks. // An incomplete sequencing window will result in an incomplete L2 chain if so. // @@ -44,6 +103,9 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e if len(l1Input) == 0 { return l2Head, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Head) } + if len(l1Input) != int(d.Config.SeqWindowSize) { + return l2Head, errors.New("Invalid sequencing window size") + } logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], "input_l2_parent", l2Head, "finalized_l2", l2Finalized) @@ -71,22 +133,26 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e if err != nil { return l2Head, fmt.Errorf("failed to fetch transactions from %s: %v", l1Input, err) } - batches := derive.BatchesFromEVMTransactions(&d.Config, transactions) + batches, err := derive.BatchesFromEVMTransactions(&d.Config, transactions) + if err != nil { + return l2Head, fmt.Errorf("failed to fetch create batches from transactions: %w", err) + } minL2Time := l2Info.Time() + d.Config.BlockTime - maxL2Time := l1Info.Time() + d.Config.BlockTime + maxL2Time := l1Info.Time() batches = derive.FilterBatches(&d.Config, epoch, minL2Time, maxL2Time, batches) - attrsList, err := derive.PayloadAttributes(&d.Config, l1Info, receipts, batches, l2Info) + attrsList, err := derive.PayloadAttributes(&d.Config, l1Info, receipts, batches, l2Info, minL2Time, maxL2Time) if err != nil { return l2Head, fmt.Errorf("failed to derive execution payload inputs: %v", err) } last := l2Head for i, attrs := range attrsList { - last, err = AddBlock(ctx, logger, d.rpc, last, l2Finalized.Hash, attrs) + payload, err := AddBlock(ctx, logger, d.rpc, last, l2Finalized.Hash, attrs) if err != nil { return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %v", i, len(attrsList), epoch, err) } + last = payload.ID() } return last, nil @@ -97,11 +163,11 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e // // After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. func AddBlock(ctx context.Context, logger log.Logger, rpc DriverAPI, - l2Parent eth.BlockID, l2Finalized common.Hash, attrs *l2.PayloadAttributes) (eth.BlockID, error) { + l2Parent eth.BlockID, l2Finalized common.Hash, attrs *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { payload, err := derive.ExecutionPayload(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) if err != nil { - return l2Parent, fmt.Errorf("failed to derive execution payload: %v", err) + return nil, fmt.Errorf("failed to derive execution payload: %v", err) } logger = logger.New("derived_l2", payload.ID()) @@ -109,14 +175,14 @@ func AddBlock(ctx context.Context, logger log.Logger, rpc DriverAPI, err = l2.ExecutePayload(ctx, rpc, payload) if err != nil { - return l2Parent, fmt.Errorf("failed to apply execution payload: %v", err) + return nil, fmt.Errorf("failed to apply execution payload: %v", err) } logger.Info("executed block") err = l2.ForkchoiceUpdate(ctx, rpc, payload.BlockHash, l2Finalized) if err != nil { - return payload.ID(), fmt.Errorf("failed to persist execution payload: %v", err) + return nil, fmt.Errorf("failed to persist execution payload: %v", err) } logger.Info("updated fork-choice with block") - return payload.ID(), nil + return payload, nil } diff --git a/opnode/test/geth.go b/opnode/test/geth.go index 746be4d11391..c21318d3b5e8 100644 --- a/opnode/test/geth.go +++ b/opnode/test/geth.go @@ -73,5 +73,9 @@ func l1Geth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { } func l2Geth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { - return createGethNode(true, cfg.l2.nodeConfig, cfg.l2.ethConfig, []*ecdsa.PrivateKey{}) + return createGethNode(true, cfg.l2Verifier.nodeConfig, cfg.l2Verifier.ethConfig, nil) +} + +func l2SequencerGeth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { + return createGethNode(true, cfg.l2Sequencer.nodeConfig, cfg.l2Sequencer.ethConfig, nil) } diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 44d2a3622e86..0d0c62f68953 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -44,7 +44,8 @@ type gethConfig struct { type systemConfig struct { mnemonic string l1 gethConfig - l2 gethConfig + l2Verifier gethConfig + l2Sequencer gethConfig premine map[string]int // Derivation path -> amount in ETH (not wei) cliqueSigners []string // derivation path depositContractAddress string @@ -132,7 +133,7 @@ func initializeGenesis(cfg *systemConfig) { } l2Genesis := &core.Genesis{ Config: ¶ms.ChainConfig{ - ChainID: new(big.Int).SetUint64((cfg.l2.ethConfig.NetworkId)), + ChainID: new(big.Int).SetUint64((cfg.l2Verifier.ethConfig.NetworkId)), HomesteadBlock: common.Big0, EIP150Block: common.Big0, EIP155Block: common.Big0, @@ -155,6 +156,7 @@ func initializeGenesis(cfg *systemConfig) { } cfg.l1.ethConfig.Genesis = l1Genesis - cfg.l2.ethConfig.Genesis = l2Genesis + cfg.l2Verifier.ethConfig.Genesis = l2Genesis + cfg.l2Sequencer.ethConfig.Genesis = l2Genesis cfg.wallet = wallet } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index e5a565bf1e58..711cef7d590e 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -2,6 +2,7 @@ package test import ( "context" + "errors" "fmt" "math/big" "testing" @@ -15,6 +16,7 @@ import ( rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" @@ -48,6 +50,7 @@ func TestSystemE2E(t *testing.T) { log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs const l2OutputHDPath = "m/44'/60'/0'/0/3" + const bssHDPath = "m/44'/60'/0'/0/4" // System Config cfg := &systemConfig{ @@ -62,13 +65,21 @@ func TestSystemE2E(t *testing.T) { NetworkId: 900, }, }, - l2: gethConfig{ + l2Verifier: gethConfig{ nodeConfig: &node.Config{ - Name: "l2geth", - DataDir: "", - IPCPath: "", - WSHost: "127.0.0.1", - WSPort: 9091, + Name: "l2gethVerify", + WSHost: "127.0.0.1", + WSPort: 9091, + }, + ethConfig: ðconfig.Config{ + NetworkId: 901, + }, + }, + l2Sequencer: gethConfig{ + nodeConfig: &node.Config{ + Name: "l2gethSeq", + WSHost: "127.0.0.1", + WSPort: 9092, }, ethConfig: ðconfig.Config{ NetworkId: 901, @@ -79,6 +90,7 @@ func TestSystemE2E(t *testing.T) { "m/44'/60'/0'/0/1": 10000000, "m/44'/60'/0'/0/2": 10000000, l2OutputHDPath: 10000000, + bssHDPath: 10000000, }, cliqueSigners: []string{"m/44'/60'/0'/0/0"}, depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", @@ -110,36 +122,92 @@ func TestSystemE2E(t *testing.T) { err = l2Node.Start() require.Nil(t, err) - l2Client, err := ethclient.Dial(endpoint(cfg.l2.nodeConfig)) + l2Client, err := ethclient.Dial(endpoint(cfg.l2Verifier.nodeConfig)) require.Nil(t, err) l2GenesisHash := getGenesisHash(l2Client) - // Rollup Node + // Start L2 + l2SequencerNode, _, err := l2SequencerGeth(cfg) + require.Nil(t, err) + defer l2SequencerNode.Close() + + err = l2SequencerNode.Start() + require.Nil(t, err) + + l2SequencerClient, err := ethclient.Dial(endpoint(cfg.l2Sequencer.nodeConfig)) + require.Nil(t, err) + + // BSS + bssPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: bssHDPath, + }, + }) + require.Nil(t, err) + submitterAddress := crypto.PubkeyToAddress(bssPrivKey.PublicKey) + + // Account + ethPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: "m/44'/60'/0'/0/0", + }, + }) + require.Nil(t, err) + + // Verifier Rollup Node nodeCfg := &rollupNode.Config{ L2Hash: l2GenesisHash, L1Hash: l1GenesisHash, L1Num: 0, L1NodeAddr: endpoint(cfg.l1.nodeConfig), - L2EngineAddrs: []string{endpoint(cfg.l2.nodeConfig)}, + L2EngineAddrs: []string{endpoint(cfg.l2Verifier.nodeConfig)}, Rollup: rollup.Config{ BlockTime: 1, MaxSequencerTimeDiff: 10, - SeqWindowSize: 1, - L1ChainID: big.NewInt(901), + SeqWindowSize: 2, + L1ChainID: big.NewInt(900), // TODO pick defaults FeeRecipientAddress: common.Address{0xff, 0x01}, BatchInboxAddress: common.Address{0xff, 0x02}, - BatchSenderAddress: common.Address{0xff, 0x03}, + BatchSenderAddress: submitterAddress, }, } nodeCfg.Rollup.Genesis = nodeCfg.GetGenesis() - node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlTrace)) + node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlError)) require.Nil(t, err) err = node.Start(context.Background()) require.Nil(t, err) defer node.Stop() + // Sequencer Rollup Node + sequenceCfg := &rollupNode.Config{ + L2Hash: l2GenesisHash, + L1Hash: l1GenesisHash, + L1Num: 0, + L1NodeAddr: endpoint(cfg.l1.nodeConfig), + L2EngineAddrs: []string{endpoint(cfg.l2Sequencer.nodeConfig)}, + Rollup: rollup.Config{ + BlockTime: 1, + MaxSequencerTimeDiff: 10, + SeqWindowSize: 2, + L1ChainID: big.NewInt(900), + // TODO pick defaults + FeeRecipientAddress: common.Address{0xff, 0x01}, + BatchInboxAddress: common.Address{0xff, 0x02}, + BatchSenderAddress: submitterAddress, + }, + Sequencer: true, + SubmitterPrivKey: bssPrivKey, + } + sequenceCfg.Rollup.Genesis = sequenceCfg.GetGenesis() + sequencer, err := rollupNode.New(context.Background(), sequenceCfg, testlog.Logger(t, log.LvlError)) + require.Nil(t, err) + + err = sequencer.Start(context.Background()) + require.Nil(t, err) + defer sequencer.Stop() + // Deploy StateRootOracle l2OutputPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ URL: accounts.URL{ @@ -178,13 +246,13 @@ func TestSystemE2E(t *testing.T) { // L2Output Submitter l2OutputSubmitter, err := l2os.NewL2OutputSubmitter(l2os.Config{ L1EthRpc: endpoint(cfg.l1.nodeConfig), - L2EthRpc: endpoint(cfg.l2.nodeConfig), + L2EthRpc: endpoint(cfg.l2Verifier.nodeConfig), L2OOAddress: l2ooAddr.String(), PollInterval: 5 * time.Second, NumConfirmations: 1, ResubmissionTimeout: 5 * time.Second, SafeAbortNonceTooLowCount: 3, - LogLevel: "debug", + LogLevel: "error", Mnemonic: cfg.mnemonic, L2OutputHDPath: l2OutputHDPath, }, "") @@ -246,6 +314,7 @@ func TestSystemE2E(t *testing.T) { defer cancel() receipt, err := l1Client.TransactionReceipt(ctx, tx.Hash()) require.Nil(t, err, "Could not get transaction receipt") + waitNumber := new(big.Int).Add(receipt.BlockNumber, common.Big2) // sequence window effect // Wait (or timeout) for that block to show up on L2 timeoutCh := time.After(6 * time.Second) @@ -253,7 +322,7 @@ loop: for { select { case head := <-headChan: - if head.Number.Cmp(receipt.BlockNumber) >= 0 { + if head.Number.Cmp(waitNumber) >= 0 { break loop } case err := <-l2HeadSub.Err(): @@ -311,4 +380,46 @@ loop: case <-time.After(time.Second): } } + + // Submit TX to L2 sequencer node + toAddr := common.Address{0xff, 0xff} + tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(new(big.Int).SetUint64(cfg.l2Verifier.ethConfig.NetworkId)), &types.DynamicFeeTx{ + ChainID: big.NewInt(int64(cfg.l2Verifier.ethConfig.NetworkId)), + Nonce: 1, // guess + To: &toAddr, + Value: big.NewInt(1_000_000_000), + GasTipCap: big.NewInt(10), + GasFeeCap: big.NewInt(200), + Gas: 21000, + }) + err = l2SequencerClient.SendTransaction(context.Background(), tx) + require.Nil(t, err) + + var l2IncludedBlock *big.Int + + // Wait for tx to show up in chain (on sequencer) + timeoutCh = time.After(6 * time.Second) +lastLoop: + for { + select { + case <-timeoutCh: + t.Fatal("Timeout waiting for l2 transaction") + case <-time.After(200 * time.Millisecond): + } + + receipt, err := l2Client.TransactionReceipt(context.Background(), tx.Hash()) + if receipt != nil && err == nil { + l2IncludedBlock = receipt.BlockNumber + break lastLoop + } else if err != nil && !errors.Is(err, ethereum.NotFound) { + require.Nil(t, err) + } + } + + verifBlock, err := l2Client.BlockByNumber(context.Background(), l2IncludedBlock) + require.Nil(t, err) + seqBlock, err := l2SequencerClient.BlockByNumber(context.Background(), l2IncludedBlock) + require.Nil(t, err) + require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") + } From cb5418fd8e7a5456a7aa3e4f96faeba61c11a9fc Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 17 Mar 2022 23:17:25 +0100 Subject: [PATCH 307/585] opnode: rollup config from JSON file, clean cli --- opnode/cmd/main.go | 138 ++----------------------------------- opnode/flags/flags.go | 84 ++++++++++++++++++++++ opnode/flags/flags_test.go | 28 ++++++++ opnode/node/config.go | 31 +++++++++ opnode/node/log.go | 1 - opnode/node/node.go | 31 --------- opnode/rollup/types.go | 24 +++++++ opnode/service.go | 82 ++++++++++++++++++++++ opnode/test/system_test.go | 28 ++++---- 9 files changed, 271 insertions(+), 176 deletions(-) create mode 100644 opnode/flags/flags.go create mode 100644 opnode/flags/flags_test.go create mode 100644 opnode/node/config.go create mode 100644 opnode/service.go diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index e2ea7c555905..2d571d11dc40 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -2,16 +2,14 @@ package main import ( "context" - "fmt" - "math/big" "os" "os/signal" "syscall" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode" + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum/go-ethereum/log" "github.com/urfave/cli" ) @@ -43,7 +41,7 @@ func main() { ) app := cli.NewApp() - app.Flags = Flags + app.Flags = flags.Flags app.Version = VersionWithMeta app.Name = "opnode" app.Usage = "Optimism Rollup Node" @@ -58,12 +56,12 @@ func main() { func RollupNodeMain(ctx *cli.Context) error { log.Info("Initializing Rollup Node") - cfg, err := NewConfig(ctx) + cfg, err := opnode.NewConfig(ctx) if err != nil { log.Error("Unable to create the rollup node config", "error", err) return err } - logCfg, err := NewLogConfig(ctx) + logCfg, err := opnode.NewLogConfig(ctx) if err != nil { log.Error("Unable to create the log config", "error", err) return err @@ -96,127 +94,3 @@ func RollupNodeMain(ctx *cli.Context) error { return nil } - -// HexToHash takes a `0x` prefixed hex hash string and turns it into a hash. -// Errors are reported. -func HexToHash(s string) (common.Hash, error) { - var x common.Hash - err := x.UnmarshalText([]byte(s)) - return x, err -} - -// NewConfig creates a Config from the provided flags or environment variables. -func NewConfig(ctx *cli.Context) (*node.Config, error) { - L2Hash, err := HexToHash(ctx.GlobalString(GenesisL2Hash.Name)) - if err != nil { - return nil, fmt.Errorf("Could not decode L2Hash: %w", err) - } - L1Hash, err := HexToHash(ctx.GlobalString(GenesisL1Hash.Name)) - if err != nil { - return nil, fmt.Errorf("Could not decode L1Hash: %w", err) - } - cfg := &node.Config{ - /* Required Flags */ - L1NodeAddr: ctx.GlobalString(L1NodeAddr.Name), - L2EngineAddrs: ctx.GlobalStringSlice(L2EngineAddrs.Name), - L2Hash: L2Hash, - L1Hash: L1Hash, - L1Num: ctx.GlobalUint64(GenesisL2Hash.Name), - Rollup: rollup.Config{ - BlockTime: 2, - MaxSequencerTimeDiff: 10, - SeqWindowSize: 64, - L1ChainID: big.NewInt(901), - // TODO pick defaults - FeeRecipientAddress: common.Address{0xff, 0x01}, - BatchInboxAddress: common.Address{0xff, 0x02}, - BatchSenderAddress: common.Address{0xff, 0x03}, - }, - } - cfg.Rollup.Genesis = cfg.GetGenesis() - if err := cfg.Check(); err != nil { - return nil, err - } - return cfg, nil -} - -// NewLogConfig creates a log config from the provided flags or environment variables. -func NewLogConfig(ctx *cli.Context) (node.LogConfig, error) { - cfg := node.DefaultLogConfig() // Done to set color based on terminal type - cfg.Level = ctx.GlobalString(LogLevelFlag.Name) - cfg.Format = ctx.GlobalString(LogFormatFlag.Name) - if ctx.IsSet(LogColorFlag.Name) { - cfg.Color = ctx.GlobalBool(LogColorFlag.Name) - } - - if err := cfg.Check(); err != nil { - return cfg, err - } - return cfg, nil -} - -// Flags - -// Commented out for deadcode lint -// const envVarPrefix = "ROLLUP_NODE_" -// func prefixEnvVar(name string) string { -// return envVarPrefix + name -// } - -var Flags = []cli.Flag{ - L1NodeAddr, - L2EngineAddrs, - GenesisL2Hash, - GenesisL1Hash, - GenesisL1Num, - LogLevelFlag, - LogFormatFlag, - LogColorFlag, -} - -var ( - /* Required Flags */ - L1NodeAddr = cli.StringFlag{ - Name: "l1", - Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)", - Required: true, - Value: "http://127.0.0.1:8545", - } - L2EngineAddrs = cli.StringSliceFlag{ - Name: "l2", - Usage: "Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)", - Required: true, - } - GenesisL2Hash = cli.StringFlag{ - Name: "genesis.l2-hash", - Usage: "Genesis block hash of L2", - Required: true, - } - GenesisL1Hash = cli.StringFlag{ - Name: "genesis.l1-hash", - Usage: "Block hash of L1 after (not incl.) which L1 starts deriving blocks", - Required: true, - } - GenesisL1Num = cli.Uint64Flag{ - Name: "genesis.l1-num", - Usage: "Block number of L1 matching the l1-hash", - Required: true, - } - - /* Optional Flags */ - - LogLevelFlag = cli.StringFlag{ - Name: "log.level", - Usage: "The lowest log level that will be output", - Value: "info", - } - LogFormatFlag = cli.StringFlag{ - Name: "log.format", - Usage: "Format the log output. Supported formats: 'text', 'json'", - Value: "text", - } - LogColorFlag = cli.BoolFlag{ - Name: "log.color", - Usage: "Color the log output", - } -) diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go new file mode 100644 index 000000000000..575d5d195469 --- /dev/null +++ b/opnode/flags/flags.go @@ -0,0 +1,84 @@ +package flags + +import "github.com/urfave/cli" + +// Flags + +const envVarPrefix = "ROLLUP_NODE_" + +func prefixEnvVar(name string) string { + return envVarPrefix + name +} + +var ( + /* Required Flags */ + L1NodeAddr = cli.StringFlag{ + Name: "l1", + Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)", + Required: true, + Value: "http://127.0.0.1:8545", + EnvVar: prefixEnvVar("L1_ETH_RPC"), + } + L2EngineAddrs = cli.StringSliceFlag{ + Name: "l2", + Usage: "Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)", + Required: true, + EnvVar: prefixEnvVar("L2_ENGINE_RPC"), + } + RollupConfig = cli.StringFlag{ + Name: "rollup.config", + Usage: "Rollup chain parameters", + Required: true, + EnvVar: prefixEnvVar("ROLLUP_CONFIG"), + } + + /* Optional Flags */ + + SequencingEnabledFlag = cli.BoolFlag{ + Name: "sequencing.enabled", + Usage: "enable sequencing", + EnvVar: prefixEnvVar("SEQUENCING_ENABLED"), + } + + // TODO: move batch submitter to stand-alone process + BatchSubmitterKeyFlag = cli.BoolFlag{ + Name: "batchsubmitter.key", + Usage: "key for batch submitting", + EnvVar: prefixEnvVar("BATCHSUBMITTER_KEY"), + } + + LogLevelFlag = cli.StringFlag{ + Name: "log.level", + Usage: "The lowest log level that will be output", + Value: "info", + EnvVar: prefixEnvVar("LOG_LEVEL"), + } + LogFormatFlag = cli.StringFlag{ + Name: "log.format", + Usage: "Format the log output. Supported formats: 'text', 'json'", + Value: "text", + EnvVar: prefixEnvVar("LOG_FORMAT"), + } + LogColorFlag = cli.BoolFlag{ + Name: "log.color", + Usage: "Color the log output", + EnvVar: prefixEnvVar("LOG_COLOR"), + } +) + +var requiredFlags = []cli.Flag{ + L1NodeAddr, + L2EngineAddrs, + RollupConfig, +} + +var optionalFlags = []cli.Flag{ + SequencingEnabledFlag, + BatchSubmitterKeyFlag, + LogLevelFlag, + LogFormatFlag, + LogColorFlag, +} + +// Flags contains the list of configuration options available to the binary. +var Flags = append(requiredFlags, optionalFlags...) diff --git a/opnode/flags/flags_test.go b/opnode/flags/flags_test.go new file mode 100644 index 000000000000..ae0bc3d02e37 --- /dev/null +++ b/opnode/flags/flags_test.go @@ -0,0 +1,28 @@ +package flags + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli" +) + +// TestRequiredFlagsSetRequired asserts that all flags deemed required properly +// have the Required field set to true. +func TestRequiredFlagsSetRequired(t *testing.T) { + for _, flag := range requiredFlags { + reqFlag, ok := flag.(cli.RequiredFlag) + require.True(t, ok) + require.True(t, reqFlag.IsRequired()) + } +} + +// TestOptionalFlagsDontSetRequired asserts that all flags deemed optional set +// the Required field to false. +func TestOptionalFlagsDontSetRequired(t *testing.T) { + for _, flag := range optionalFlags { + reqFlag, ok := flag.(cli.RequiredFlag) + require.True(t, ok) + require.False(t, reqFlag.IsRequired()) + } +} diff --git a/opnode/node/config.go b/opnode/node/config.go new file mode 100644 index 000000000000..79a71758d23d --- /dev/null +++ b/opnode/node/config.go @@ -0,0 +1,31 @@ +package node + +import ( + "crypto/ecdsa" + "fmt" + + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" +) + +type Config struct { + // L1 and L2 nodes + L1NodeAddr string // Address of L1 User JSON-RPC endpoint to use (eth namespace required) + L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required) + + Rollup rollup.Config + + // Sequencer flag, enables sequencing + Sequencer bool + + // SubmitterPrivKey, temporary config var while the batch-submitter is part of the rollup node + SubmitterPrivKey *ecdsa.PrivateKey +} + +// Check verifies that the given configuration makes sense +func (cfg *Config) Check() error { + if err := cfg.Rollup.Check(); err != nil { + return fmt.Errorf("rollup config error: %v", err) + } + + return nil +} diff --git a/opnode/node/log.go b/opnode/node/log.go index 7cc5fdecadcb..83030b11528f 100644 --- a/opnode/node/log.go +++ b/opnode/node/log.go @@ -13,7 +13,6 @@ type LogConfig struct { Level string // Log level: trace, debug, info, warn, error, crit. Capitals are accepted too. Color bool // Color the log output. Defaults to true if terminal is detected. Format string // Format the log output. Supported formats: 'text', 'json' - } func DefaultLogConfig() LogConfig { diff --git a/opnode/node/node.go b/opnode/node/node.go index 0846bd8662a3..b4bb7114e027 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -2,7 +2,6 @@ package node import ( "context" - "crypto/ecdsa" "fmt" "time" @@ -10,37 +9,15 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/driver" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" ) -type Config struct { - // L1 and L2 nodes - L1NodeAddr string // Address of L1 User JSON-RPC endpoint to use (eth namespace required) - L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required) - - // Genesis Information - L2Hash common.Hash // Genesis block hash of L2 - L1Hash common.Hash // Block hash of L1 after (not incl.) which L1 starts deriving blocks - L1Num uint64 // Block number of L1 matching the l1-hash - - Rollup rollup.Config - Sequencer bool - SubmitterPrivKey *ecdsa.PrivateKey -} - -// Check verifies that the given configuration makes sense -func (cfg *Config) Check() error { - return nil -} - type OpNode struct { log log.Logger l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) @@ -48,14 +25,6 @@ type OpNode struct { done chan struct{} } -func (conf *Config) GetGenesis() rollup.Genesis { - return rollup.Genesis{ - L1: eth.BlockID{Hash: conf.L1Hash, Number: conf.L1Num}, - // TODO: if we start from a squashed snapshot we might have a non-zero L2 genesis number - L2: eth.BlockID{Hash: conf.L2Hash, Number: 0}, - } -} - func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { if err := cfg.Check(); err != nil { return nil, err diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go index 7cb2d065235e..f82987d674ec 100644 --- a/opnode/rollup/types.go +++ b/opnode/rollup/types.go @@ -1,6 +1,7 @@ package rollup import ( + "errors" "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -33,6 +34,9 @@ type Config struct { // Required to verify L1 signatures L1ChainID *big.Int + // Note: below addresses are part of the block-derivation process, + // and required to be the same network-wide to stay in consensus. + // L2 address receiving all L2 transaction fees FeeRecipientAddress common.Address // L1 address that batches are sent to @@ -41,6 +45,26 @@ type Config struct { BatchSenderAddress common.Address } +// Check verifies that the given configuration makes sense +func (cfg *Config) Check() error { + if cfg.BlockTime == 0 { + return errors.New("block time cannot be 0") + } + if cfg.SeqWindowSize == 0 { + return errors.New("sequencing window size cannot be 0") + } + if cfg.Genesis.L1.Hash == (common.Hash{}) { + return errors.New("genesis l1 hash cannot be empty") + } + if cfg.Genesis.L2.Hash == (common.Hash{}) { + return errors.New("genesis l2 hash cannot be empty") + } + if cfg.Genesis.L2.Hash == cfg.Genesis.L1.Hash { + return errors.New("achievement get! rollup inception: L1 and L2 genesis cannot be the same") + } + return nil +} + func (c *Config) L1Signer() types.Signer { return types.NewLondonSigner(c.L1ChainID) } diff --git a/opnode/service.go b/opnode/service.go new file mode 100644 index 000000000000..12fd6dcfd5d5 --- /dev/null +++ b/opnode/service.go @@ -0,0 +1,82 @@ +package opnode + +import ( + "crypto/ecdsa" + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/crypto" + "github.com/urfave/cli" +) + +// NewConfig creates a Config from the provided flags or environment variables. +func NewConfig(ctx *cli.Context) (*node.Config, error) { + rollupConfig, err := NewRollupConfig(ctx) + if err != nil { + return nil, err + } + + enableSequencing := ctx.GlobalBool(flags.SequencingEnabledFlag.Name) + + var batchSubmitterKey *ecdsa.PrivateKey + if enableSequencing { + keyFile := ctx.GlobalString(flags.BatchSubmitterKeyFlag.Name) + if keyFile == "" { + return nil, errors.New("sequencer mode needs batch-submitter key") + } + // TODO we should be using encrypted keystores. + // Mnemonics are bad because they leak *all* keys when they leak + // Unencrypted keys from file are bad because they are easy to leak (and we are not checking file permissions) + batchSubmitterKey, err = crypto.LoadECDSA(keyFile) + if err != nil { + return nil, fmt.Errorf("failed to read batch submitter key: %v", err) + } + } + + cfg := &node.Config{ + L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), + L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), + Rollup: *rollupConfig, + Sequencer: enableSequencing, + SubmitterPrivKey: batchSubmitterKey, + } + if err := cfg.Check(); err != nil { + return nil, err + } + return cfg, nil +} + +func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) { + rollupConfigPath := ctx.GlobalString(flags.RollupConfig.Name) + file, err := os.Open(rollupConfigPath) + if err != nil { + return nil, fmt.Errorf("failed to read rollup config: %v", err) + } + defer file.Close() + + var rollupConfig rollup.Config + if err := json.NewDecoder(file).Decode(&rollupConfig); err != nil { + return nil, fmt.Errorf("failed to decode rollup config: %v", err) + } + return &rollupConfig, nil +} + +// NewLogConfig creates a log config from the provided flags or environment variables. +func NewLogConfig(ctx *cli.Context) (node.LogConfig, error) { + cfg := node.DefaultLogConfig() // Done to set color based on terminal type + cfg.Level = ctx.GlobalString(flags.LogLevelFlag.Name) + cfg.Format = ctx.GlobalString(flags.LogFormatFlag.Name) + if ctx.IsSet(flags.LogColorFlag.Name) { + cfg.Color = ctx.GlobalBool(flags.LogColorFlag.Name) + } + + if err := cfg.Check(); err != nil { + return cfg, err + } + return cfg, nil +} diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 711cef7d590e..710db9c0bbc4 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" @@ -30,14 +32,14 @@ import ( "github.com/stretchr/testify/require" ) -func getGenesisHash(client *ethclient.Client) common.Hash { +func getGenesisInfo(client *ethclient.Client) (id eth.BlockID, timestamp uint64) { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() block, err := client.BlockByNumber(ctx, common.Big0) if err != nil { panic(err) } - return block.Hash() + return eth.BlockID{Hash: block.Hash(), Number: block.NumberU64()}, block.Time() } func endpoint(cfg *node.Config) string { @@ -112,7 +114,7 @@ func TestSystemE2E(t *testing.T) { l1Client, err := ethclient.Dial(endpoint(cfg.l1.nodeConfig)) require.Nil(t, err) - l1GenesisHash := getGenesisHash(l1Client) + l1GenesisID, _ := getGenesisInfo(l1Client) // Start L2 l2Node, _, err := l2Geth(cfg) @@ -124,7 +126,7 @@ func TestSystemE2E(t *testing.T) { l2Client, err := ethclient.Dial(endpoint(cfg.l2Verifier.nodeConfig)) require.Nil(t, err) - l2GenesisHash := getGenesisHash(l2Client) + l2GenesisID, l2GenesisTime := getGenesisInfo(l2Client) // Start L2 l2SequencerNode, _, err := l2SequencerGeth(cfg) @@ -156,12 +158,14 @@ func TestSystemE2E(t *testing.T) { // Verifier Rollup Node nodeCfg := &rollupNode.Config{ - L2Hash: l2GenesisHash, - L1Hash: l1GenesisHash, - L1Num: 0, L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2Verifier.nodeConfig)}, Rollup: rollup.Config{ + Genesis: rollup.Genesis{ + L1: l1GenesisID, + L2: l2GenesisID, + L2Time: l2GenesisTime, + }, BlockTime: 1, MaxSequencerTimeDiff: 10, SeqWindowSize: 2, @@ -172,7 +176,6 @@ func TestSystemE2E(t *testing.T) { BatchSenderAddress: submitterAddress, }, } - nodeCfg.Rollup.Genesis = nodeCfg.GetGenesis() node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlError)) require.Nil(t, err) @@ -182,12 +185,14 @@ func TestSystemE2E(t *testing.T) { // Sequencer Rollup Node sequenceCfg := &rollupNode.Config{ - L2Hash: l2GenesisHash, - L1Hash: l1GenesisHash, - L1Num: 0, L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2Sequencer.nodeConfig)}, Rollup: rollup.Config{ + Genesis: rollup.Genesis{ + L1: l1GenesisID, + L2: l2GenesisID, + L2Time: l2GenesisTime, + }, BlockTime: 1, MaxSequencerTimeDiff: 10, SeqWindowSize: 2, @@ -200,7 +205,6 @@ func TestSystemE2E(t *testing.T) { Sequencer: true, SubmitterPrivKey: bssPrivKey, } - sequenceCfg.Rollup.Genesis = sequenceCfg.GetGenesis() sequencer, err := rollupNode.New(context.Background(), sequenceCfg, testlog.Logger(t, log.LvlError)) require.Nil(t, err) From a0000191be2f5b7a4805e2c70cfd42c550181ee5 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 18 Mar 2022 00:22:46 +0100 Subject: [PATCH 308/585] opnode/rollup: json encode/decode rollup config --- opnode/eth/id.go | 14 +++++------ opnode/rollup/types.go | 22 ++++++++--------- opnode/rollup/types_test.go | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 opnode/rollup/types_test.go diff --git a/opnode/eth/id.go b/opnode/eth/id.go index 359726727bd4..44d48ddf4e83 100644 --- a/opnode/eth/id.go +++ b/opnode/eth/id.go @@ -7,8 +7,8 @@ import ( ) type BlockID struct { - Hash common.Hash - Number uint64 + Hash common.Hash `json:"hash"` + Number uint64 `json:"number"` } func (id BlockID) String() string { @@ -22,9 +22,9 @@ func (id BlockID) TerminalString() string { } type L2BlockRef struct { - Self BlockID - Parent BlockID - L1Origin BlockID + Self BlockID `json:"self"` + Parent BlockID `json:"parent"` + L1Origin BlockID `json:"l1_origin"` } func (id L2BlockRef) String() string { @@ -38,8 +38,8 @@ func (id L2BlockRef) TerminalString() string { } type L1BlockRef struct { - Self BlockID - Parent BlockID + Self BlockID `json:"self"` + Parent BlockID `json:"parent"` } func (id L1BlockRef) String() string { diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go index f82987d674ec..0c25d7c9d1d5 100644 --- a/opnode/rollup/types.go +++ b/opnode/rollup/types.go @@ -11,38 +11,38 @@ import ( type Genesis struct { // The L1 block that the rollup starts *after* (no derived transactions) - L1 eth.BlockID + L1 eth.BlockID `json:"l1"` // The L2 block the rollup starts from (no transactions, pre-configured state) - L2 eth.BlockID + L2 eth.BlockID `json:"l2"` // Timestamp of L2 block - L2Time uint64 + L2Time uint64 `json:"l2_time"` } type Config struct { // Genesis anchor point of the rollup - Genesis Genesis + Genesis Genesis `json:"genesis"` // Seconds per L2 block - BlockTime uint64 + BlockTime uint64 `json:"block_time"` // Sequencer batches may not be more than MaxSequencerTimeDiff seconds after // the L1 timestamp of the sequencing window end. // // Note: When L1 has many 1 second consecutive blocks, and L2 grows at fixed 2 seconds, // the L2 time may still grow beyond this difference. - MaxSequencerTimeDiff uint64 + MaxSequencerTimeDiff uint64 `json:"max_sequencer_time_diff"` // Number of epochs (L1 blocks) per sequencing window - SeqWindowSize uint64 + SeqWindowSize uint64 `json:"seq_window_size"` // Required to verify L1 signatures - L1ChainID *big.Int + L1ChainID *big.Int `json:"l1_chain_id"` // Note: below addresses are part of the block-derivation process, // and required to be the same network-wide to stay in consensus. // L2 address receiving all L2 transaction fees - FeeRecipientAddress common.Address + FeeRecipientAddress common.Address `json:"fee_recipient_address"` // L1 address that batches are sent to - BatchInboxAddress common.Address + BatchInboxAddress common.Address `json:"batch_inbox_address"` // Acceptable batch-sender address - BatchSenderAddress common.Address + BatchSenderAddress common.Address `json:"batch_sender_address"` } // Check verifies that the given configuration makes sense diff --git a/opnode/rollup/types_test.go b/opnode/rollup/types_test.go new file mode 100644 index 000000000000..628cba8285cb --- /dev/null +++ b/opnode/rollup/types_test.go @@ -0,0 +1,47 @@ +package rollup + +import ( + "encoding/json" + "math/big" + "math/rand" + "testing" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func randConfig() *Config { + randHash := func() (out common.Hash) { + rand.Read(out[:]) + return + } + randAddr := func() (out common.Address) { // we need generics... + rand.Read(out[:]) + return + } + return &Config{ + Genesis: Genesis{ + L1: eth.BlockID{Hash: randHash(), Number: 424242}, + L2: eth.BlockID{Hash: randHash(), Number: 1337}, + L2Time: uint64(time.Now().Unix()), + }, + BlockTime: 2, + MaxSequencerTimeDiff: 100, + SeqWindowSize: 2, + L1ChainID: big.NewInt(900), + FeeRecipientAddress: randAddr(), + BatchInboxAddress: randAddr(), + BatchSenderAddress: randAddr(), + } +} + +func TestConfigJSON(t *testing.T) { + config := randConfig() + data, err := json.Marshal(config) + assert.NoError(t, err) + var roundTripped Config + assert.NoError(t, json.Unmarshal(data, &roundTripped)) + assert.Equal(t, &roundTripped, config) +} From 8fff39568ee27f24888e04a0d9cb78000b6b7b99 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 18 Mar 2022 00:52:29 +0100 Subject: [PATCH 309/585] opnode/rollup: improve Config.Check --- opnode/rollup/types.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go index 0c25d7c9d1d5..bb9ed7e9b0e9 100644 --- a/opnode/rollup/types.go +++ b/opnode/rollup/types.go @@ -2,6 +2,7 @@ package rollup import ( "errors" + "fmt" "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -48,10 +49,10 @@ type Config struct { // Check verifies that the given configuration makes sense func (cfg *Config) Check() error { if cfg.BlockTime == 0 { - return errors.New("block time cannot be 0") + return fmt.Errorf("block time cannot be 0, got %d", cfg.BlockTime) } - if cfg.SeqWindowSize == 0 { - return errors.New("sequencing window size cannot be 0") + if cfg.SeqWindowSize < 2 { + return fmt.Errorf("sequencing window size must at least be 2, got %d", cfg.SeqWindowSize) } if cfg.Genesis.L1.Hash == (common.Hash{}) { return errors.New("genesis l1 hash cannot be empty") From 2bab20ab640d90de87854a095f2ac1e72f0476bf Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Thu, 17 Mar 2022 23:00:41 -0600 Subject: [PATCH 310/585] Demo setup and fixes Includes the following: - A docker-compose setup with Dockerfiles for each service. The reference Geth implementation pulls an image from my personal repo for now. We can switch this out once we get CI running there. - An exponential backoff library, which is then used to retry connections to the L1/L2 provider on node startup. This prevents the opnode from crashing on startup due to the L1/L2 taking a while to start in Docker. - A fix for one of the CLI falgs - `--batchsubmitter.key` was specified as a boolean. - Make tasks to build the docker-compose setup, and clean it up. Fixes #259 --- Makefile | 17 + opnode/backoff/operation.go | 44 ++ opnode/backoff/operation_test.go | 34 + opnode/backoff/strategies.go | 63 ++ opnode/backoff/strategies_test.go | 21 + opnode/bss/submitter.go | 2 +- opnode/flags/flags.go | 2 +- opnode/node/node.go | 44 +- ops/Dockerfile.l1 | 15 + ops/Dockerfile.l2 | 15 + Dockerfile.opnode => ops/Dockerfile.opnode | 2 +- ops/bss-key.txt | 1 + ops/docker-compose.yml | 50 ++ ops/entrypoint.sh | 56 ++ ops/genesis-l1.json | 808 +++++++++++++++++++++ ops/genesis-l2.json | 806 ++++++++++++++++++++ ops/rollup.json | 21 + 17 files changed, 1985 insertions(+), 16 deletions(-) create mode 100644 opnode/backoff/operation.go create mode 100644 opnode/backoff/operation_test.go create mode 100644 opnode/backoff/strategies.go create mode 100644 opnode/backoff/strategies_test.go create mode 100644 ops/Dockerfile.l1 create mode 100644 ops/Dockerfile.l2 rename Dockerfile.opnode => ops/Dockerfile.opnode (94%) create mode 100644 ops/bss-key.txt create mode 100644 ops/docker-compose.yml create mode 100644 ops/entrypoint.sh create mode 100644 ops/genesis-l1.json create mode 100644 ops/genesis-l2.json create mode 100644 ops/rollup.json diff --git a/Makefile b/Makefile index e3b2003d0419..362616e69b10 100644 --- a/Makefile +++ b/Makefile @@ -5,3 +5,20 @@ opnode: clean: rm -rf ./bin .PHONY: clean + +devnet-clean: devnet-down + cd ops && docker-compose rm + docker volume rm ops_l1_data + docker volume rm ops_l2_data +.PHONY: devnet-clean + +devnet-up: + @(cd ./ops && \ + DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ + L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ + docker-compose up --build) +.PHONY: devnet-up + +devnet-down: + @(cd ./ops && docker-compose down) +.PHONY: devnet-stop \ No newline at end of file diff --git a/opnode/backoff/operation.go b/opnode/backoff/operation.go new file mode 100644 index 000000000000..4bd7f4539f1d --- /dev/null +++ b/opnode/backoff/operation.go @@ -0,0 +1,44 @@ +package backoff + +import ( + "fmt" + "time" +) + +// Operation represents an operation that will be retried +// based on some backoff strategy if it fails. +type Operation func() error + +// ErrFailedPermanently is an error raised by Do when the +// underlying Operation has been retried maxAttempts times. +type ErrFailedPermanently struct { + attempts int + LastErr error +} + +func (e *ErrFailedPermanently) Error() string { + return fmt.Sprintf("operation failed permanently after %d attempts: %v", e.attempts, e.LastErr) +} + +// Do performs the provided Operation up to maxAttempts times +// with delays in between each retry according to the provided +// Strategy. +func Do(maxAttempts int, strat Strategy, op Operation) error { + var attempt int + + for { + attempt++ + err := op() + if err == nil { + return nil + } + + if attempt == maxAttempts { + return &ErrFailedPermanently{ + attempts: maxAttempts, + LastErr: err, + } + } + time.Sleep(strat.Duration(attempt - 1)) + } +} diff --git a/opnode/backoff/operation_test.go b/opnode/backoff/operation_test.go new file mode 100644 index 000000000000..a7e2d174e7c3 --- /dev/null +++ b/opnode/backoff/operation_test.go @@ -0,0 +1,34 @@ +package backoff + +import ( + "errors" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestDo(t *testing.T) { + strat := Fixed(10 * time.Millisecond) + dummyErr := errors.New("explode") + + start := time.Now() + var i int + require.NoError(t, Do(2, strat, func() error { + if i == 1 { + return nil + } + + i++ + return dummyErr + })) + require.True(t, time.Since(start) > 10*time.Millisecond) + + start = time.Now() + // add one because the first attempt counts + err := Do(3, strat, func() error { + return dummyErr + }) + require.Equal(t, dummyErr, err.(*ErrFailedPermanently).LastErr) + require.True(t, time.Since(start) > 20*time.Millisecond) +} diff --git a/opnode/backoff/strategies.go b/opnode/backoff/strategies.go new file mode 100644 index 000000000000..a852f37df8ba --- /dev/null +++ b/opnode/backoff/strategies.go @@ -0,0 +1,63 @@ +package backoff + +import ( + "math" + "math/rand" + "time" +) + +// Strategy is used to calculate how long a particular Operation +// should wait between attempts. +type Strategy interface { + // Duration returns how long to wait for a given retry attempt. + Duration(attempt int) time.Duration +} + +// ExponentialStrategy performs exponential backoff. The exponential backoff +// function is min(e.Min + (2^attempt * 1000) + randBetween(0, e.MaxJitter), e.Max) +type ExponentialStrategy struct { + // Min is the minimum amount of time to wait between attempts in ms. + Min float64 + + // Max is the maximum amount of time to wait between attempts in ms. + Max float64 + + // MaxJitter is the maximum amount of random jitter to insert between + // attempts in ms. + MaxJitter int +} + +func (e *ExponentialStrategy) Duration(attempt int) time.Duration { + var jitter int + if e.MaxJitter > 0 { + jitter = rand.Intn(e.MaxJitter) + } + dur := e.Min + (math.Pow(2, float64(attempt)) * 1000) + dur += float64(jitter) + if dur > e.Max { + return time.Millisecond * time.Duration(e.Max) + } + + return time.Millisecond * time.Duration(dur) +} + +func Exponential() Strategy { + return &ExponentialStrategy{ + Max: 10000, + MaxJitter: 250, + } +} + +type FixedStrategy struct { + Dur time.Duration +} + +func (f *FixedStrategy) Duration(attempt int) time.Duration { + return f.Dur +} + +func Fixed(dur time.Duration) Strategy { + return &FixedStrategy{ + Dur: dur, + } +} diff --git a/opnode/backoff/strategies_test.go b/opnode/backoff/strategies_test.go new file mode 100644 index 000000000000..852ee2b67ab6 --- /dev/null +++ b/opnode/backoff/strategies_test.go @@ -0,0 +1,21 @@ +package backoff + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestExponential(t *testing.T) { + strat := &ExponentialStrategy{ + Min: 3000, + Max: 10000, + MaxJitter: 0, + } + + durations := []int{4, 5, 7, 10, 10} + for i, dur := range durations { + require.Equal(t, time.Millisecond*time.Duration(dur*1000), strat.Duration(i)) + } +} diff --git a/opnode/bss/submitter.go b/opnode/bss/submitter.go index 3fbb3708f4e3..51a13ccdd9f7 100644 --- a/opnode/bss/submitter.go +++ b/opnode/bss/submitter.go @@ -86,7 +86,7 @@ func (b *BatchSubmitter) Submit(config *rollup.Config, batches []*derive.BatchDa return common.Hash{}, err } - timeout := time.After(4 * time.Second) + timeout := time.After(30 * time.Second) for { receipt, err := b.Client.TransactionReceipt(context.Background(), tx.Hash()) diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go index 575d5d195469..c2913a54f16b 100644 --- a/opnode/flags/flags.go +++ b/opnode/flags/flags.go @@ -41,7 +41,7 @@ var ( } // TODO: move batch submitter to stand-alone process - BatchSubmitterKeyFlag = cli.BoolFlag{ + BatchSubmitterKeyFlag = cli.StringFlag{ Name: "batchsubmitter.key", Usage: "key for batch submitting", EnvVar: prefixEnvVar("BATCHSUBMITTER_KEY"), diff --git a/opnode/node/node.go b/opnode/node/node.go index b4bb7114e027..7648de8d505e 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/backoff" + "github.com/ethereum-optimism/optimistic-specs/opnode/bss" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" @@ -30,14 +32,22 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { return nil, err } - // L1 exec engine: read-only, to update L2 consensus with - l1Node, err := rpc.DialContext(ctx, cfg.L1NodeAddr) - if err != nil { - // HTTP or WS RPC may create a disconnected client, RPC over IPC may fail directly - if l1Node == nil { - return nil, fmt.Errorf("failed to dial L1 addres (%s): %v", cfg.L1NodeAddr, err) + bOff := backoff.Exponential() + var l1Node *rpc.Client + err := backoff.Do(10, bOff, func() error { + client, err := rpc.DialContext(ctx, cfg.L1NodeAddr) + if err != nil { + // HTTP or WS RPC may create a disconnected client, RPC over IPC may fail directly + if client == nil { + return fmt.Errorf("failed to dial L1 address (%s): %v", cfg.L1NodeAddr, err) + } + log.Warn("failed to dial L1 address, but may connect later", "addr", cfg.L1NodeAddr, "err", err) } - log.Warn("failed to dial L1 address, but may connect later", "addr", cfg.L1NodeAddr, "err", err) + l1Node = client + return nil + }) + if err != nil { + return nil, err } // TODO: we may need to authenticate the connection with L1 @@ -46,14 +56,22 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { var l2Engines []*driver.Driver for i, addr := range cfg.L2EngineAddrs { - // L2 exec engine: updated by this OpNode (L2 consensus layer node) - backend, err := rpc.DialContext(ctx, addr) - if err != nil { - if backend == nil { - return nil, fmt.Errorf("failed to dial L2 address %d (%s): %v", i, addr, err) + var backend *rpc.Client + err := backoff.Do(10, bOff, func() error { + client, err := rpc.DialContext(ctx, addr) + if err != nil { + if client == nil { + return fmt.Errorf("failed to dial L2 address %d (%s): %v", i, addr, err) + } + log.Warn("failed to dial L2 address, but may connect later", "i", i, "addr", addr, "err", err) } - log.Warn("failed to dial L2 address, but may connect later", "i", i, "addr", addr, "err", err) + backend = client + return nil + }) + if err != nil { + return nil, err } + // TODO: we may need to authenticate the connection with L2 // backend.SetHeader() client := &l2.EngineClient{ diff --git a/ops/Dockerfile.l1 b/ops/Dockerfile.l1 new file mode 100644 index 000000000000..e1655c864e05 --- /dev/null +++ b/ops/Dockerfile.l1 @@ -0,0 +1,15 @@ +FROM ethereum/client-go:v1.10.16 + +ARG DEPOSIT_FEED_BYTECODE="" + +RUN apk add --no-cache jq + +COPY entrypoint.sh /entrypoint.sh +COPY genesis-l1.json /genesis.json + +RUN cat /genesis.json | jq ". | .alloc.deaddeaddeaddeaddeaddeaddeaddeaddead0001.code = \"$DEPOSIT_FEED_BYTECODE\"" | tee /genesis-with-bytecode.json && \ + mv /genesis-with-bytecode.json /genesis.json + +VOLUME ["/db"] + +ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] diff --git a/ops/Dockerfile.l2 b/ops/Dockerfile.l2 new file mode 100644 index 000000000000..32b0b2a4c3bd --- /dev/null +++ b/ops/Dockerfile.l2 @@ -0,0 +1,15 @@ +FROM mslipper/reference-optimistic-geth:latest + +ARG L1_BLOCK_INFO_BYTECODE="" + +RUN apk add --no-cache jq + +COPY entrypoint.sh /entrypoint.sh +COPY genesis-l2.json /genesis.json + +RUN cat /genesis.json | jq ". | .alloc.\"4242424242424242424242424242424242424242\".code = \"$L1_BLOCK_INFO_BYTECODE\"" | tee /genesis-with-bytecode.json && \ + mv /genesis-with-bytecode.json /genesis.json + +VOLUME ["/db"] + +ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] \ No newline at end of file diff --git a/Dockerfile.opnode b/ops/Dockerfile.opnode similarity index 94% rename from Dockerfile.opnode rename to ops/Dockerfile.opnode index f308e25d1410..1031e0db478c 100644 --- a/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -8,7 +8,7 @@ COPY go.sum /app/go.sum WORKDIR /app COPY ./opnode /app/opnode -RUN make +RUN make opnode FROM alpine:3.13 diff --git a/ops/bss-key.txt b/ops/bss-key.txt new file mode 100644 index 000000000000..0994f47ba01e --- /dev/null +++ b/ops/bss-key.txt @@ -0,0 +1 @@ +bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 \ No newline at end of file diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml new file mode 100644 index 000000000000..bc130d85c9f1 --- /dev/null +++ b/ops/docker-compose.yml @@ -0,0 +1,50 @@ +version: '3.4' + +volumes: + l1_data: + l2_data: + +services: + l1: + build: + context: . + dockerfile: Dockerfile.l1 + args: + DEPOSIT_FEED_BYTECODE: $DEPOSIT_FEED_BYTECODE + ports: + - "9545:8545" + volumes: + - "l1_data:/db" + + l2: + build: + context: . + dockerfile: Dockerfile.l2 + args: + L1_BLOCK_INFO_BYTECODE: $L1_BLOCK_INFO_BYTECODE + ports: + - "8545:8545" + volumes: + - "l2_data:/db" + + opnode: + depends_on: + - l1 + - l2 + build: + context: ../ + dockerfile: ./ops/Dockerfile.opnode + volumes: + - ${PWD}/bss-key.txt:/config/bss-key.txt + - ${PWD}/rollup.json:/config/rollup.json + command: + - "op" + - "--l1" + - "ws://l1:8546" + - "--l2" + - "ws://l2:8546" + - "--sequencing.enabled" + - "--rollup.config" + - "/config/rollup.json" + - "--batchsubmitter.key" + - "/config/bss-key.txt" \ No newline at end of file diff --git a/ops/entrypoint.sh b/ops/entrypoint.sh new file mode 100644 index 000000000000..de5c25039465 --- /dev/null +++ b/ops/entrypoint.sh @@ -0,0 +1,56 @@ +#!/bin/sh +set -exu + +VERBOSITY=${GETH_VERBOSITY:-3} +GETH_DATA_DIR=/db +GETH_CHAINDATA_DIR="$GETH_DATA_DIR/geth/chaindata" +GETH_KEYSTORE_DIR="$GETH_DATA_DIR/keystore" +CHAIN_ID=$(cat /genesis.json | jq -r .config.chainId) +BLOCK_SIGNER_PRIVATE_KEY="3e4bde571b86929bf08e2aaad9a6a1882664cd5e65b96fff7d03e1c4e6dfa15c" +BLOCK_SIGNER_ADDRESS="0xca062b0fd91172d89bcd4bb084ac4e21972cc467" + +if [ ! -d "$GETH_KEYSTORE_DIR" ]; then + echo "$GETH_KEYSTORE_DIR missing, running account import" + echo -n "pwd" > "$GETH_DATA_DIR"/password + echo -n "$BLOCK_SIGNER_PRIVATE_KEY" | sed 's/0x//' > "$GETH_DATA_DIR"/block-signer-key + geth account import \ + --datadir="$GETH_DATA_DIR" \ + --password="$GETH_DATA_DIR"/password \ + "$GETH_DATA_DIR"/block-signer-key +else + echo "$GETH_KEYSTORE_DIR exists." +fi + +if [ ! -d "$GETH_CHAINDATA_DIR" ]; then + echo "$GETH_CHAINDATA_DIR missing, running init" + echo "Initializing genesis." + geth --verbosity="$VERBOSITY" init \ + --datadir="$GETH_DATA_DIR" \ + "/genesis.json" +else + echo "$GETH_CHAINDATA_DIR exists." +fi + +exec geth \ + --datadir="$GETH_DATA_DIR" \ + --verbosity="$VERBOSITY" \ + --http \ + --http.corsdomain="*" \ + --http.vhosts="*" \ + --http.addr=0.0.0.0 \ + --http.port=8545 \ + --ws \ + --ws.addr=0.0.0.0 \ + --ws.port=8546 \ + --ws.origins="*" \ + --ws.api=debug,eth,txpool,net,engine \ + --syncmode=full \ + --nodiscover \ + --maxpeers=1 \ + --networkid=$CHAIN_ID \ + --unlock=$BLOCK_SIGNER_ADDRESS \ + --mine \ + --miner.etherbase=$BLOCK_SIGNER_ADDRESS \ + --password="$GETH_DATA_DIR"/password \ + --allow-insecure-unlock \ + "$@" \ No newline at end of file diff --git a/ops/genesis-l1.json b/ops/genesis-l1.json new file mode 100644 index 000000000000..88b72018d35e --- /dev/null +++ b/ops/genesis-l1.json @@ -0,0 +1,808 @@ +{ + "config": { + "chainId": 900, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "clique": { + "period": 15, + "epoch": 30000 + } + }, + "nonce": "0x0", + "timestamp": "0x623239da", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000ca062b0fd91172d89bcd4bb084ac4e21972cc4670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0000000000000000000000000000000000000000": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000001": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000002": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000003": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000004": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000005": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000006": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000007": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000008": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000009": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000010": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000011": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000012": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000013": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000014": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000015": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000016": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000017": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000018": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000019": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000020": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000021": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000022": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000023": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000024": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000025": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000026": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000027": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000028": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000029": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000030": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000031": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000032": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000033": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000034": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000035": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000036": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000037": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000038": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000039": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000040": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000041": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000042": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000043": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000044": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000045": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000046": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000047": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000048": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000049": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000050": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000051": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000052": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000053": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000054": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000055": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000056": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000057": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000058": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000059": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000060": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000061": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000062": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000063": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000064": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000065": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000066": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000067": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000068": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000069": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000070": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000071": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000072": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000073": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000074": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000075": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000076": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000077": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000078": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000079": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000080": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000081": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000082": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000083": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000084": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000085": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000086": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000087": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000088": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000089": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000090": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000091": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000092": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000093": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000094": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000095": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000096": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000097": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000098": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000099": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009f": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000aa": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ab": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ac": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ad": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ae": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000af": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ba": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000be": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bf": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ca": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ce": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cf": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000da": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000db": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000dc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000dd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000de": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000df": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ea": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000eb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ec": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ed": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ee": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ef": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fa": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fe": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ff": { + "balance": "0x1" + }, + "de3829a23df1479438622a08a116e8eb3f620bb5": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "deaddeaddeaddeaddeaddeaddeaddeaddead0001": { + "code": "", + "balance": "0x0" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null +} \ No newline at end of file diff --git a/ops/genesis-l2.json b/ops/genesis-l2.json new file mode 100644 index 000000000000..37335af1bb16 --- /dev/null +++ b/ops/genesis-l2.json @@ -0,0 +1,806 @@ +{ + "config": { + "chainId": 901, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "mergeForkBlock": 0, + "terminalTotalDifficulty": 0 + }, + "nonce": "0x1234", + "timestamp": "0x61fc5cf1", + "extraData": "0x", + "gasLimit": "0x4c4b40", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0000000000000000000000000000000000000000": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000001": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000002": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000003": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000004": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000005": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000006": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000007": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000008": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000009": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000000f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000010": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000011": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000012": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000013": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000014": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000015": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000016": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000017": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000018": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000019": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000001f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000020": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000021": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000022": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000023": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000024": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000025": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000026": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000027": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000028": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000029": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000002f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000030": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000031": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000032": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000033": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000034": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000035": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000036": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000037": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000038": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000039": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000003f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000040": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000041": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000042": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000043": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000044": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000045": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000046": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000047": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000048": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000049": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000004f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000050": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000051": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000052": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000053": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000054": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000055": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000056": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000057": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000058": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000059": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000005f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000060": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000061": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000062": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000063": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000064": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000065": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000066": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000067": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000068": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000069": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000006f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000070": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000071": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000072": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000073": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000074": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000075": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000076": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000077": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000078": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000079": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000007f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000080": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000081": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000082": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000083": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000084": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000085": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000086": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000087": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000088": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000089": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000008f": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000090": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000091": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000092": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000093": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000094": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000095": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000096": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000097": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000098": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000099": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009a": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009b": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009c": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009d": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009e": { + "balance": "0x1" + }, + "000000000000000000000000000000000000009f": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000a9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000aa": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ab": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ac": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ad": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ae": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000af": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000b9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ba": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000be": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000bf": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000c9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ca": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ce": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000cf": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000d9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000da": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000db": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000dc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000dd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000de": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000df": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000e9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ea": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000eb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ec": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ed": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ee": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ef": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f0": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f1": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f2": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f3": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f4": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f5": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f6": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f7": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f8": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000f9": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fa": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fb": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fc": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fd": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000fe": { + "balance": "0x1" + }, + "00000000000000000000000000000000000000ff": { + "balance": "0x1" + }, + "de3829a23df1479438622a08a116e8eb3f620bb5": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "4242424242424242424242424242424242424242": { + "code": "", + "balance": "0x0" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x7" +} \ No newline at end of file diff --git a/ops/rollup.json b/ops/rollup.json new file mode 100644 index 000000000000..68d34ea846c3 --- /dev/null +++ b/ops/rollup.json @@ -0,0 +1,21 @@ +{ + "genesis": { + "l1": { + "hash": "0x21837b23495539c19e4b85d3d115c740c677d2609480eb67c3b2bb218a3ffd8f", + "number": 0 + }, + "l2": { + "hash": "0xb6eacd24a7fa15fa1a9b3ae550e217760f7d8a82a9c246975144b6ba6e3589f3", + "number": 0 + }, + "l2_time": 1647573629 + }, + + "block_time": 1, + + "max_sequencer_time_diff": 10, + + "seq_window_size": 64, + + "l1_chain_id": 900 +} \ No newline at end of file From cbf53c5e99c3309325a03a8a96c9e2be08c89e6e Mon Sep 17 00:00:00 2001 From: norswap Date: Sun, 20 Mar 2022 15:40:47 +0100 Subject: [PATCH 311/585] remove R&D calls We haven't been running those for a while, and someone did ask me about it. Let's add it back when we actually start doing them again. --- README.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/README.md b/README.md index 4d723cfda863..6677d1791e84 100644 --- a/README.md +++ b/README.md @@ -31,20 +31,6 @@ request]. [Issues]: https://github.com/ethereum-optimism/optimistic-specs/issues [pull request]: https://github.com/ethereum-optimism/optimistic-specs/pulls -### R&D Calls - -We hold bi-weekly R&D calls that are open to anyone interested in contributing -to the Optimism spec. - -Contact [@karlfloersch], [@protolambda], [@kelvinfichter] or [@norswap] if you'd -like to join these calls. Please note that these calls may be recorded and -shared publicly (we will ask for consent before recording). - -[@karlfloersch]: https://twitter.com/karl_dot_tech/ -[@protolambda]: https://github.com/protolambda/ -[@kelvinfichter]: https://twitter.com/kelvinfichter -[@norswap]: https://twitter.com/norswap - ## License Specification: CC0 1.0 Universal, see [`specs/LICENSE`](./specs/LICENSE) file. From f5a415cccf7d19e8a6b5d3d7743cdbb96bcbd639 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 17 Mar 2022 06:35:39 -0400 Subject: [PATCH 312/585] Add forge --- .gitignore | 6 +---- .gitmodules | 3 +++ packages/contracts/.gitignore | 3 +++ packages/contracts/.solhintignore | 1 + packages/contracts/README.md | 35 ++++++++++++++++++++++---- packages/contracts/lib/ds-test | 1 + packages/contracts/package.json | 11 +++++--- packages/contracts/slither.config.json | 2 +- 8 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 .gitmodules create mode 160000 packages/contracts/lib/ds-test diff --git a/.gitignore b/.gitignore index 6841a1f303c3..44f8fca85218 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,8 @@ node_modules yarn-error.log -coverage.out - -# hardhat automatically puts console.sol in here when you use it -.deps # built binaries bin -# + # vim swap files *.sw* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000000..b8a7e1389771 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "packages/contracts/lib/ds-test"] + path = packages/contracts/lib/ds-test + url = https://github.com/dapphub/ds-test diff --git a/packages/contracts/.gitignore b/packages/contracts/.gitignore index 674f13159b32..19d9d7338bfc 100644 --- a/packages/contracts/.gitignore +++ b/packages/contracts/.gitignore @@ -1,3 +1,6 @@ artifacts +forge-artifacts cache typechain +coverage.out +.deps diff --git a/packages/contracts/.solhintignore b/packages/contracts/.solhintignore index 3c3629e647f5..ffbffa57dd5b 100644 --- a/packages/contracts/.solhintignore +++ b/packages/contracts/.solhintignore @@ -1 +1,2 @@ node_modules +lib/ds-test diff --git a/packages/contracts/README.md b/packages/contracts/README.md index ba40b3d099a9..8e434a2819cc 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -1,17 +1,42 @@ -# Contracts for OVM 1.0 +# Optimism: Bedrock Edition - Contracts -## Usage +## Install -Install with yarn (v1), and Node.js (14+). +The repo currently uses a mix of typescript tests (run with HardHat) and solidity tests (run with Forge). The project +uses the default hardhat directory structure, and all build/test steps should be run using the yarn scripts to ensure +the correct options are set. + +Install node modules with yarn (v1), and Node.js (14+). ```shell yarn ``` -### Running Tests +See installation instructions for forge [here](https://github.com/gakonst/foundry). + +## Build + +```shell +yarn build +``` + +## Running Tests -Tests are executed via `yarn`: + +The full test suite can be executed via `yarn`: ```shell yarn test ``` + +To run only typescript tests: + +```shell +yarn test:hh +``` + +To run only solidity tests: + +```shell +yarn test:forge +``` diff --git a/packages/contracts/lib/ds-test b/packages/contracts/lib/ds-test new file mode 160000 index 000000000000..0a5da56b0d65 --- /dev/null +++ b/packages/contracts/lib/ds-test @@ -0,0 +1 @@ +Subproject commit 0a5da56b0d65960e6a994d2ec8245e6edd38c248 diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 37c3801a194d..c26f39d00217 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -8,9 +8,14 @@ "hardhat": "^2.7.1" }, "scripts": { - "test": "hardhat test", - "test:slither": "slither .", - "build": "hardhat compile", + "build:forge": "forge build --root . -c contracts --out forge-artifacts", + "build:hh": "yarn hardhat compile", + "build": "yarn build:forge && yarn build:hh", + "test:hh": "yarn hardhat test", + "test:forge": "forge test --root . -c contracts --out forge-artifacts", + "test": "yarn test:forge && yarn test:hh", + "slither": "slither .", + "clean": "rm -rf ./artifacts ./forge-artifacts ./cache ./coverage ./tsconfig.build.tsbuildinfo", "lint:ts:check": "eslint .", "lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol'", "lint:check": "yarn lint:contracts:check && yarn lint:ts:check", diff --git a/packages/contracts/slither.config.json b/packages/contracts/slither.config.json index 1acc8f4111b3..a745b72be39e 100644 --- a/packages/contracts/slither.config.json +++ b/packages/contracts/slither.config.json @@ -8,5 +8,5 @@ "hardhat_ignore_compile": false, "disable_color": false, "exclude_dependencies": false, - "filter_paths": "contracts/test" + "filter_paths": "contracts/test|lib/ds-test" } From 9b3e3957f14c8bd157e0bd76436f193b515bcba5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 17 Mar 2022 21:22:53 -0400 Subject: [PATCH 313/585] Convert L1Block test from ts to sol --- packages/contracts/.solhintignore | 1 + .../contracts/contracts/test/L1Block.t.sol | 38 ++++++++++++ packages/contracts/test/L2/L1Block.spec.ts | 62 ------------------- 3 files changed, 39 insertions(+), 62 deletions(-) create mode 100644 packages/contracts/contracts/test/L1Block.t.sol delete mode 100644 packages/contracts/test/L2/L1Block.spec.ts diff --git a/packages/contracts/.solhintignore b/packages/contracts/.solhintignore index ffbffa57dd5b..ad2b84c9ae43 100644 --- a/packages/contracts/.solhintignore +++ b/packages/contracts/.solhintignore @@ -1,2 +1,3 @@ node_modules lib/ds-test +contracts/test/*.t.sol diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts/contracts/test/L1Block.t.sol new file mode 100644 index 000000000000..c07aadde2788 --- /dev/null +++ b/packages/contracts/contracts/test/L1Block.t.sol @@ -0,0 +1,38 @@ +pragma solidity 0.8.10; + +import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { L1Block } from "../L2/L1Block.sol"; + +interface CheatCodes { + function prank(address) external; +} + +contract L1BLockTest is DSTest { + CheatCodes cheats = CheatCodes(HEVM_ADDRESS); + L1Block lb; + address depositor; + bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1)); + + function setUp() external { + lb = new L1Block(); + depositor = lb.DEPOSITOR_ACCOUNT(); + cheats.prank(depositor); + lb.setL1BlockValues(1, 2, 3, NON_ZERO_HASH); + } + + function test_number() external { + assertEq(lb.number(), 1); + } + + function test_timestamp() external { + assertEq(lb.timestamp(), 2); + } + + function test_basefee() external { + assertEq(lb.timestamp(), 2); + } + + function test_hash() external { + assertEq(lb.hash(), NON_ZERO_HASH); + } +} diff --git a/packages/contracts/test/L2/L1Block.spec.ts b/packages/contracts/test/L2/L1Block.spec.ts deleted file mode 100644 index 4e029c186645..000000000000 --- a/packages/contracts/test/L2/L1Block.spec.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { expect } from 'chai' -import { ethers } from 'hardhat' -import { Signer } from 'ethers' - -import { L1Block__factory, L1Block } from '../../typechain' - -const DEPOSITOR_ACCOUNT = '0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001' -const NON_ZERO_HASH = '0x' + 'ab'.repeat(32) - -describe('L1Block contract', () => { - let signer: Signer - let signerAddress: string - let l1Block: L1Block - let depositor: Signer - before(async () => { - ;[signer] = await ethers.getSigners() - signerAddress = await signer.getAddress() - l1Block = await new L1Block__factory(signer).deploy() - await l1Block.deployed() - - depositor = await ethers.getSigner(DEPOSITOR_ACCOUNT) - }) - - it('setL1BlockValues: Should revert if not called by L1 Attributes Depositor Account', async () => { - await expect( - l1Block.connect(signer).setL1BlockValues(1, 2, 3, NON_ZERO_HASH) - ).to.be.revertedWith('OnlyDepositor()') - }) - - describe('Should return the correct block values for:', async () => { - before(async () => { - await ethers.provider.send('hardhat_impersonateAccount', [ - DEPOSITOR_ACCOUNT, - ]) - await ethers.provider.send('hardhat_setBalance', [ - DEPOSITOR_ACCOUNT, - '0xFFFFFFFFFFFF', - ]) - await l1Block.connect(depositor).setL1BlockValues(1, 2, 3, NON_ZERO_HASH) - await ethers.provider.send('hardhat_stopImpersonatingAccount', [ - DEPOSITOR_ACCOUNT, - ]) - l1Block.connect(signer) - }) - - it('number', async () => { - expect(await l1Block.number()).to.equal(1) - }) - - it('timestamp', async () => { - expect(await l1Block.timestamp()).to.equal(2) - }) - - it('basefee', async () => { - expect(await l1Block.basefee()).to.equal(3) - }) - - it('hash', async () => { - expect(await l1Block.hash()).to.equal(NON_ZERO_HASH) - }) - }) -}) From fedcc734f931a3f71dc65682b26e1e54b1b0bae5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 21 Mar 2022 10:37:52 -0400 Subject: [PATCH 314/585] Clean up workflow configuration --- .editorconfig | 3 ++ .../workflows/{lint.yml => markdown-ci.yml} | 0 .../{static-analysis.yml => solidity-ci.yml} | 37 +++++++++++++------ 3 files changed, 28 insertions(+), 12 deletions(-) rename .github/workflows/{lint.yml => markdown-ci.yml} (100%) rename .github/workflows/{static-analysis.yml => solidity-ci.yml} (59%) diff --git a/.editorconfig b/.editorconfig index bfaafc5d2614..79d2fd91e224 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,3 +14,6 @@ indent_style = tab [*.{ts,js}] indent_size = 2 + +[*.yml] +indent_size = 2 diff --git a/.github/workflows/lint.yml b/.github/workflows/markdown-ci.yml similarity index 100% rename from .github/workflows/lint.yml rename to .github/workflows/markdown-ci.yml diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/solidity-ci.yml similarity index 59% rename from .github/workflows/static-analysis.yml rename to .github/workflows/solidity-ci.yml index 1719a3543f61..61905b82702c 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/solidity-ci.yml @@ -11,31 +11,44 @@ on: env: PYTEST_ADDOPTS: "--color=yes" +defaults: + run: + shell: bash + working-directory: ./packages/contracts + jobs: - slither: - name: Slither run + solidity-ci: runs-on: ubuntu-latest - defaults: - run: - shell: bash - working-directory: ./packages/contracts + name: Solidity Checks steps: - uses: actions/checkout@v2 + with: + submodules: recursive + - uses: actions/setup-node@v2 with: node-version: '14' cache: 'yarn' - run: yarn install - - name: Build - run: yarn build - - name: Lint - run: yarn lint:check + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly + + - name: Build with Forge + run: yarn build:forge + + - name: Build with HH + run: yarn build:hh - name: Test run: yarn test + - name: Lint + run: yarn lint:check + - name: Set up Python 3.8 uses: actions/setup-python@v2 with: @@ -44,5 +57,5 @@ jobs: - name: Install Slither run: pip3 install slither-analyzer - - name: Run analysis - run: yarn test:slither + - name: Run Slither + run: yarn slither From 4bcde9db9e8cfa9bc8fe904f3495d3aef1918b57 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 21 Mar 2022 11:10:38 -0700 Subject: [PATCH 315/585] Squashed cleanup (#256) This better handles the fork choice update in the rollup node, exposes the fork choice method throughout, cleans up the L2 Engine API interface, and random aspects of block creation. The l2.Source is the Ethereum client wrapper for the L2 execution engine. It directly wraps some block accessing methods (like BlockByNumber and BlockByHash). It also wraps raw RPC calls to create a golang interface for the Engine API (newBlock, forkchoiceUpdated, getPayload). This PR also pulls out the ethclient initialization loop into a standalone function. --- opnode/l2/api.go | 130 -------------------- opnode/l2/source.go | 127 ++++++++++++++----- opnode/node/node.go | 53 ++++---- opnode/rollup/derive/execution_payload.go | 36 ------ opnode/rollup/derive/payload_attributes.go | 122 +++++++------------ opnode/rollup/driver/driver.go | 5 +- opnode/rollup/driver/state.go | 44 ++++--- opnode/rollup/driver/state_test.go | 12 +- opnode/rollup/driver/step.go | 135 ++++++++++++++------- 9 files changed, 287 insertions(+), 377 deletions(-) delete mode 100644 opnode/rollup/derive/execution_payload.go diff --git a/opnode/l2/api.go b/opnode/l2/api.go index f11a23d195cc..06f4d4f03bbb 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -2,19 +2,13 @@ package l2 import ( - "context" "fmt" - "math/big" "reflect" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" "github.com/holiman/uint256" ) @@ -173,127 +167,3 @@ type ForkchoiceUpdatedResult struct { // the payload id if requested PayloadID *PayloadID `json:"payloadId"` } - -type EngineAPI interface { - GetPayload(ctx context.Context, payloadId PayloadID) (*ExecutionPayload, error) - ExecutePayload(ctx context.Context, payload *ExecutionPayload) (*ExecutePayloadResult, error) - ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) - Close() -} - -type RPCBackend interface { - CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error - Close() -} - -type EthBackend interface { - SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) -} - -type EngineClient struct { - RPCBackend - EthBackend - Log log.Logger -} - -func (el *EngineClient) GetPayload(ctx context.Context, payloadId PayloadID) (*ExecutionPayload, error) { - e := el.Log.New("payload_id", payloadId) - e.Debug("getting payload") - var result ExecutionPayload - err := el.CallContext(ctx, &result, "engine_getPayloadV1", payloadId) - if err != nil { - e = log.New("payload_id", "err", err) - if rpcErr, ok := err.(rpc.Error); ok { - code := ErrorCode(rpcErr.ErrorCode()) - if code != UnavailablePayload { - e.Warn("unexpected error code in get-payload response", "code", code) - } else { - e.Warn("unavailable payload in get-payload request") - } - } else { - e.Error("failed to get payload") - } - return nil, err - } - e.Debug("Received payload") - return &result, nil -} - -func (el *EngineClient) ExecutePayload(ctx context.Context, payload *ExecutionPayload) (*ExecutePayloadResult, error) { - e := el.Log.New("block_hash", payload.BlockHash) - e.Debug("sending payload for execution") - var result ExecutePayloadResult - err := el.CallContext(ctx, &result, "engine_executePayloadV1", payload) - if err != nil { - e.Error("Payload execution failed", "err", err) - return nil, err - } - e.Debug("Received payload execution result", "status", result.Status, "latestValidHash", result.LatestValidHash, "message", result.ValidationError) - return &result, nil -} - -func (el *EngineClient) ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) { - e := el.Log.New("state", state, "attr", attr) - e.Debug("Sharing forkchoice-updated signal") - - var result ForkchoiceUpdatedResult - err := el.CallContext(ctx, &result, "engine_forkchoiceUpdatedV1", state, attr) - if err == nil { - e.Debug("Shared forkchoice-updated signal") - if attr != nil { - e.Debug("Received payload id", "payloadId", result.PayloadID) - } - return result, nil - } else { - e = e.New("err", err) - if rpcErr, ok := err.(rpc.Error); ok { - code := ErrorCode(rpcErr.ErrorCode()) - e.Warn("Unexpected error code in forkchoice-updated response", "code", code) - } else { - e.Error("Failed to share forkchoice-updated signal") - } - return result, err - } -} - -func (el *EngineClient) Close() { - el.RPCBackend.Close() -} - -func BlockToPayload(bl *types.Block, random Bytes32) (*ExecutionPayload, error) { - extra := bl.Extra() - if len(extra) > 32 { - return nil, fmt.Errorf("eth2 merge spec limits extra data to 32 bytes in payload, got %d", len(extra)) - } - baseFee, overflow := uint256.FromBig(bl.BaseFee()) - if overflow { - return nil, fmt.Errorf("overflowing base fee") - } - txs := bl.Transactions() - txsEncoded := make([]Data, 0, len(txs)) - for i, tx := range txs { - txOpaque, err := tx.MarshalBinary() - if err != nil { - return nil, fmt.Errorf("failed to encode tx %d", i) - } - txsEncoded = append(txsEncoded, txOpaque) - } - return &ExecutionPayload{ - ParentHash: bl.ParentHash(), - FeeRecipient: bl.Coinbase(), - StateRoot: Bytes32(bl.Root()), - ReceiptsRoot: Bytes32(bl.ReceiptHash()), - LogsBloom: Bytes256(bl.Bloom()), - Random: random, - BlockNumber: Uint64Quantity(bl.NumberU64()), - GasLimit: Uint64Quantity(bl.GasLimit()), - GasUsed: Uint64Quantity(bl.GasUsed()), - Timestamp: Uint64Quantity(bl.Time()), - ExtraData: BytesMax32(extra), - BaseFeePerGas: Uint256Quantity(*baseFee), - BlockHash: bl.Hash(), - Transactions: txsEncoded, - }, nil -} diff --git a/opnode/l2/source.go b/opnode/l2/source.go index 22c00e442f55..74d820a19f4c 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -3,56 +3,123 @@ package l2 import ( "context" "fmt" + "math/big" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" ) -type RPC interface { - ExecutePayload(ctx context.Context, payload *ExecutionPayload) (*ExecutePayloadResult, error) - ForkchoiceUpdated(ctx context.Context, state *ForkchoiceState, attr *PayloadAttributes) (ForkchoiceUpdatedResult, error) +type Source struct { + rpc *rpc.Client // raw RPC client. Used for the consensus namespace + client *ethclient.Client // go-ethereum's wrapper around the rpc client for the eth namespace + log log.Logger } -// ExecutePayload executes the payload and parses the return status into a useful error code -func ExecutePayload(ctx context.Context, rpc RPC, payload *ExecutionPayload) error { +func NewSource(l2Node *rpc.Client, log log.Logger) (*Source, error) { + return &Source{ + rpc: l2Node, + client: ethclient.NewClient(l2Node), + log: log, + }, nil +} + +func (s *Source) Close() { + s.rpc.Close() +} + +func (s *Source) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return s.client.BlockByHash(ctx, hash) +} + +func (s *Source) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return s.client.BlockByNumber(ctx, number) +} + +// ForkchoiceUpdate updates the forkchoice on the execution client. If attributes is not nil, the engine client will also begin building a block +// based on attributes after the new head block and return the payload ID. +// May return an error in ForkChoiceResult, but the error is marshalled into the error return +func (s *Source) ForkchoiceUpdate(ctx context.Context, fc *ForkchoiceState, attributes *PayloadAttributes) (*ForkchoiceUpdatedResult, error) { + e := s.log.New("state", fc, "attr", attributes) + e.Debug("Sharing forkchoice-updated signal") + fcCtx, cancel := context.WithTimeout(ctx, time.Second*5) + defer cancel() + var result ForkchoiceUpdatedResult + err := s.rpc.CallContext(fcCtx, &result, "engine_forkchoiceUpdatedV1", fc, attributes) + if err == nil { + e.Debug("Shared forkchoice-updated signal") + if attributes != nil { + e.Debug("Received payload id", "payloadId", result.PayloadID) + } + } else { + e = e.New("err", err) + if rpcErr, ok := err.(rpc.Error); ok { + code := ErrorCode(rpcErr.ErrorCode()) + e.Warn("Unexpected error code in forkchoice-updated response", "code", code) + } else { + e.Error("Failed to share forkchoice-updated signal") + } + } + switch result.Status { + case UpdateSyncing: + return nil, fmt.Errorf("updated forkchoice, but node is syncing: %v", err) + case UpdateSuccess: + return &result, nil + default: + return nil, fmt.Errorf("unknown forkchoice status on %s: %q, ", fc.SafeBlockHash, string(result.Status)) + } +} + +// ExecutePayload executes a built block on the execution engine and returns an error if it was not successful. +func (s *Source) ExecutePayload(ctx context.Context, payload *ExecutionPayload) error { + e := s.log.New("block_hash", payload.BlockHash) + e.Debug("sending payload for execution") + execCtx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() - execRes, err := rpc.ExecutePayload(execCtx, payload) + var result ExecutePayloadResult + err := s.rpc.CallContext(execCtx, &result, "engine_executePayloadV1", payload) + e.Debug("Received payload execution result", "status", result.Status, "latestValidHash", result.LatestValidHash, "message", result.ValidationError) if err != nil { + e.Error("Payload execution failed", "err", err) return fmt.Errorf("failed to execute payload: %v", err) } - switch execRes.Status { + + switch result.Status { case ExecutionValid: return nil case ExecutionSyncing: - return fmt.Errorf("failed to execute payload %s, node is syncing, latest valid hash is %s", payload.ID(), execRes.LatestValidHash) + return fmt.Errorf("failed to execute payload %s, node is syncing, latest valid hash is %s", payload.ID(), result.LatestValidHash) case ExecutionInvalid: - return fmt.Errorf("execution payload %s was INVALID! Latest valid hash is %s, ignoring bad block: %q", payload.ID(), execRes.LatestValidHash, execRes.ValidationError) + return fmt.Errorf("execution payload %s was INVALID! Latest valid hash is %s, ignoring bad block: %q", payload.ID(), result.LatestValidHash, result.ValidationError) default: - return fmt.Errorf("unknown execution status on %s: %q, ", payload.ID(), string(execRes.Status)) + return fmt.Errorf("unknown execution status on %s: %q, ", payload.ID(), string(result.Status)) } } -// ForkchoiceUpdate updates the forkchoive for L2 and parses the return status into a useful error code -func ForkchoiceUpdate(ctx context.Context, rpc RPC, l2BlockHash common.Hash, l2Finalized common.Hash) error { - postState := &ForkchoiceState{ - HeadBlockHash: l2BlockHash, // no difference yet between Head and Safe, no data ahead of L1 yet. - SafeBlockHash: l2BlockHash, - FinalizedBlockHash: l2Finalized, - } - - fcCtx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() - fcRes, err := rpc.ForkchoiceUpdated(fcCtx, postState, nil) +// GetPayload gets the execution payload associated with the PayloadId +func (s *Source) GetPayload(ctx context.Context, payloadId PayloadID) (*ExecutionPayload, error) { + e := s.log.New("payload_id", payloadId) + e.Debug("getting payload") + var result ExecutionPayload + err := s.rpc.CallContext(ctx, &result, "engine_getPayloadV1", payloadId) if err != nil { - return fmt.Errorf("failed to update forkchoice: %v", err) - } - switch fcRes.Status { - case UpdateSyncing: - return fmt.Errorf("updated forkchoice, but node is syncing: %v", err) - case UpdateSuccess: - return nil - default: - return fmt.Errorf("unknown forkchoice status on %s: %q, ", l2BlockHash, string(fcRes.Status)) + e = log.New("payload_id", "err", err) + if rpcErr, ok := err.(rpc.Error); ok { + code := ErrorCode(rpcErr.ErrorCode()) + if code != UnavailablePayload { + e.Warn("unexpected error code in get-payload response", "code", code) + } else { + e.Warn("unavailable payload in get-payload request") + } + } else { + e.Error("failed to get payload") + } + return nil, err } + e.Debug("Received payload") + return &result, nil } diff --git a/opnode/node/node.go b/opnode/node/node.go index 7648de8d505e..4c3a3723d658 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -27,28 +27,35 @@ type OpNode struct { done chan struct{} } -func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { - if err := cfg.Check(); err != nil { - return nil, err - } - +func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) (*rpc.Client, error) { bOff := backoff.Exponential() - var l1Node *rpc.Client + var ret *rpc.Client err := backoff.Do(10, bOff, func() error { - client, err := rpc.DialContext(ctx, cfg.L1NodeAddr) + client, err := rpc.DialContext(ctx, addr) if err != nil { - // HTTP or WS RPC may create a disconnected client, RPC over IPC may fail directly if client == nil { - return fmt.Errorf("failed to dial L1 address (%s): %v", cfg.L1NodeAddr, err) + return fmt.Errorf("failed to dial address (%s): %w", addr, err) } - log.Warn("failed to dial L1 address, but may connect later", "addr", cfg.L1NodeAddr, "err", err) + log.Warn("failed to dial address, but may connect later", "addr", addr, "err", err) } - l1Node = client + ret = client return nil }) if err != nil { return nil, err } + return ret, nil +} + +func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { + if err := cfg.Check(); err != nil { + return nil, err + } + + l1Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L1NodeAddr) + if err != nil { + return nil, fmt.Errorf("failed to dial L1 address (%s): %w", cfg.L1NodeAddr, err) + } // TODO: we may need to authenticate the connection with L1 // l1Node.SetHeader() @@ -56,29 +63,17 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { var l2Engines []*driver.Driver for i, addr := range cfg.L2EngineAddrs { - var backend *rpc.Client - err := backoff.Do(10, bOff, func() error { - client, err := rpc.DialContext(ctx, addr) - if err != nil { - if client == nil { - return fmt.Errorf("failed to dial L2 address %d (%s): %v", i, addr, err) - } - log.Warn("failed to dial L2 address, but may connect later", "i", i, "addr", addr, "err", err) - } - backend = client - return nil - }) + l2Node, err := dialRPCClientWithBackoff(ctx, log, addr) if err != nil { return nil, err } - // TODO: we may need to authenticate the connection with L2 // backend.SetHeader() - client := &l2.EngineClient{ - RPCBackend: backend, - EthBackend: ethclient.NewClient(backend), - Log: log.New("engine_client", i), + client, err := l2.NewSource(l2Node, log.New("engine_client", i)) + if err != nil { + return nil, err } + var submitter *bss.BatchSubmitter if cfg.Sequencer { submitter = &bss.BatchSubmitter{ @@ -88,7 +83,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { PrivKey: cfg.SubmitterPrivKey, } } - engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), submitter, cfg.Sequencer) + engine := driver.NewDriver(cfg.Rollup, client, &l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), submitter, cfg.Sequencer) l2Engines = append(l2Engines, engine) } diff --git a/opnode/rollup/derive/execution_payload.go b/opnode/rollup/derive/execution_payload.go deleted file mode 100644 index 0e2b37c373c3..000000000000 --- a/opnode/rollup/derive/execution_payload.go +++ /dev/null @@ -1,36 +0,0 @@ -package derive - -import ( - "context" - "fmt" - - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum/go-ethereum/common" -) - -type BlockPreparer interface { - GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) - ForkchoiceUpdated(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (l2.ForkchoiceUpdatedResult, error) -} - -// ExecutionPayload uses the engine API to derive a full L2 block from the payload attributes. -// The fcState does not affect the block production, but may inform the engine of finality and head changes to sync towards before block computation. -func ExecutionPayload(ctx context.Context, engine BlockPreparer, l2Parent common.Hash, l2Finalized common.Hash, attributes *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { - fcState := &l2.ForkchoiceState{ - HeadBlockHash: l2Parent, // no difference yet between Head and Safe, no data ahead of L1 yet. - SafeBlockHash: l2Parent, - FinalizedBlockHash: l2Finalized, - } - fcResult, err := engine.ForkchoiceUpdated(ctx, fcState, attributes) - if err != nil { - return nil, fmt.Errorf("engine failed to process forkchoice update for block derivation: %v", err) - } else if fcResult.Status != l2.UpdateSuccess { - return nil, fmt.Errorf("engine not in sync, failed to derive block, status: %s", fcResult.Status) - } - - payload, err := engine.GetPayload(ctx, *fcResult.PayloadID) - if err != nil { - return nil, fmt.Errorf("failed to get payload: %v", err) - } - return payload, nil -} diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 2cd192817ece..82273baee22a 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -210,21 +210,9 @@ func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) func FilterBatches(config *rollup.Config, epoch rollup.Epoch, minL2Time uint64, maxL2Time uint64, batches []*BatchData) (out []*BatchData) { uniqueTime := make(map[uint64]struct{}) for _, batch := range batches { - if batch.Epoch != epoch { - // Batch was tagged for past or future epoch, - // i.e. it was included too late or depends on the given L1 block to be processed first. + if !ValidBatch(batch, config, epoch, minL2Time, maxL2Time) { continue } - if (batch.Timestamp-config.Genesis.L2Time)%config.BlockTime != 0 { - continue // bad timestamp, not a multiple of the block time - } - if batch.Timestamp < minL2Time { - continue // old batch - } - // limit timestamp upper bound to avoid huge amount of empty blocks - if batch.Timestamp >= maxL2Time { - continue // too far in future - } // Check if we have already seen a batch for this L2 block if _, ok := uniqueTime[batch.Timestamp]; ok { // block already exists, batch is duplicate (first batch persists, others are ignored) @@ -236,91 +224,67 @@ func FilterBatches(config *rollup.Config, epoch rollup.Epoch, minL2Time uint64, return } -type L2Info interface { - Time() uint64 -} - -// PayloadAttributes derives a sequence of pre-execution payload attributes from: -// - The L1 information the L1-info deposit is derived from -// - The L1 receipts the user deposits are derived from -// - The data batches the L2 sequencer work is derived from -// - The L2 information of the block the new derived blocks build on -// -// This is a pure function. -func PayloadAttributes(config *rollup.Config, l1Info L1Info, receipts []*types.Receipt, seqWindow []*BatchData, l2Info L2Info, minL2Time, maxL2Time uint64) ([]*l2.PayloadAttributes, error) { - // Retrieve the deposits of this epoch (all deposits from the first block) - deposits, err := DeriveDeposits(l1Info, receipts) - if err != nil { - return nil, fmt.Errorf("failed to derive deposits: %v", err) +func ValidBatch(batch *BatchData, config *rollup.Config, epoch rollup.Epoch, minL2Time uint64, maxL2Time uint64) bool { + if batch.Epoch != epoch { + // Batch was tagged for past or future epoch, + // i.e. it was included too late or depends on the given L1 block to be processed first. + return false } - - l1Tx := types.NewTx(L1InfoDeposit(l1Info)) - l1InfoTx, err := l1Tx.MarshalBinary() // TODO: Issue with shared l1InfoTx? - if err != nil { - return nil, fmt.Errorf("failed to encode L1 info tx") + if (batch.Timestamp-config.Genesis.L2Time)%config.BlockTime != 0 { + return false // bad timestamp, not a multiple of the block time } + if batch.Timestamp < minL2Time { + return false // old batch + } + // limit timestamp upper bound to avoid huge amount of empty blocks + if batch.Timestamp >= maxL2Time { + return false // too far in future + } + return true +} - // copy L1 randomness (mix-digest becomes randao field post-merge) - // TODO: we don't have a randomness oracle on L2, what should sequencing randomness look like. - // Repeating the latest randomness of L1 might not be ideal. - randomnessSeed := l2.Bytes32(l1Info.MixDigest()) - - // Collect all L2 batches, the batches may be out-of-order, or possibly missing. - l2Blocks := make(map[uint64]*l2.PayloadAttributes) - for _, batch := range seqWindow { - - txns := make([]l2.Data, 0, len(batch.Transactions)+1) - txns = append(txns, l1InfoTx) - txns = append(txns, batch.Transactions...) +type L2Info interface { + Time() uint64 +} - l2Blocks[batch.Timestamp] = &l2.PayloadAttributes{ - Timestamp: l2.Uint64Quantity(batch.Timestamp), - Random: randomnessSeed, - SuggestedFeeRecipient: config.FeeRecipientAddress, - Transactions: txns, - } +// SortedAndPreparedBatches turns a collection of batches to the input batches for a series of blocks +func SortedAndPreparedBatches(batches []*BatchData, epoch, blockTime, minL2Time, maxL2Time uint64) []*BatchData { + m := make(map[uint64]*BatchData) + for _, b := range batches { + m[b.BatchV1.Timestamp] = b } - - // fill the gaps and always ensure at least one L2 block - var out []*l2.PayloadAttributes - for t := minL2Time; t < maxL2Time; t += config.BlockTime { - if bl, ok := l2Blocks[t]; ok { - out = append(out, bl) + var out []*BatchData + for t := minL2Time; t < maxL2Time; t += blockTime { + b, ok := m[t] + if ok { + out = append(out, b) } else { - // skipped/missing L2 block, create an empty block instead - txns := make([]l2.Data, 1) - txns[0] = l1InfoTx - out = append(out, &l2.PayloadAttributes{ - Timestamp: l2.Uint64Quantity(t), - Random: randomnessSeed, - SuggestedFeeRecipient: config.FeeRecipientAddress, - Transactions: txns, - // we are verifying, not sequencing, we've all transactions and do not pull from the tx-pool - // (that would make the block derivation non-deterministic) - NoTxPool: true, + out = append(out, &BatchData{ + BatchV1{ + Epoch: rollup.Epoch(epoch), + Timestamp: t, + }, }) } } - // TODO: Assert that this does not panic here (i.e. make sure that len(out) > 0) - - // Force deposits into the first block. TODO: Clean up L1 Info handling. - out[0].Transactions = append(append(make([]l2.Data, 0), deposits...), out[0].Transactions[1:]...) - - return out, nil + return out } -func DeriveDeposits(l1Info L1Info, receipts []*types.Receipt) ([]l2.Data, error) { +func L1InfoDepositBytes(l1Info L1Info) (l2.Data, error) { l1Tx := types.NewTx(L1InfoDeposit(l1Info)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { return nil, fmt.Errorf("failed to encode L1 info tx") } - userDeposits, err := UserDeposits(l1Info.NumberU64(), receipts) + return opaqueL1Tx, nil +} + +func DeriveDeposits(epoch uint64, receipts []*types.Receipt) ([]l2.Data, error) { + userDeposits, err := UserDeposits(epoch, receipts) if err != nil { return nil, fmt.Errorf("failed to derive user deposits: %v", err) } - encodedTxs := make([]l2.Data, 0, len(userDeposits)+1) - encodedTxs = append(encodedTxs, opaqueL1Tx) + encodedTxs := make([]l2.Data, 0, len(userDeposits)) for i, tx := range userDeposits { opaqueTx, err := types.NewTx(tx).MarshalBinary() if err != nil { diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index aaecc669b96e..474d31e38a46 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" @@ -20,7 +21,7 @@ type BatchSubmitter interface { Submit(config *rollup.Config, batches []*derive.BatchData) (common.Hash, error) } -func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { +func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { if sequencer && submitter == nil { log.Error("Bad configuration") // TODO: return error @@ -32,8 +33,8 @@ func NewDriver(cfg rollup.Config, l2 DriverAPI, l1 l1.Source, log log.Logger, su output := &outputImpl{ Config: cfg, dl: l1, + l2: l2, log: log, - rpc: l2, } return &Driver{ s: NewState(log, cfg, input, output, submitter, sequencer), diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index de6afcb4632c..f862772185aa 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/log" ) +// TODO: Extend L2 Inteface to get safe/unsafe blocks (specifically for Unsafe L2 head) + type inputInterface interface { L1Head(ctx context.Context) (eth.L1BlockRef, error) L2Head(ctx context.Context) (eth.L2BlockRef, error) @@ -19,19 +21,19 @@ type inputInterface interface { } type outputInterface interface { - step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) - newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) + step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.BlockID, error) + newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) } type state struct { // Chain State - l1Head eth.BlockID // Latest recorded head of the L1 Chain - l1Base eth.BlockID // L1 Parent of L2 Head block - l2UnsafeHead eth.BlockID // L2 Unsafe Head - this is the head block from the sequencer - l1Origin eth.BlockID // L1 Origin of the L2 Unsafe head. For sequencing only. - l2Head eth.BlockID // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) - l2Finalized eth.BlockID // L2 Block that will never be reversed - l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. + l1Head eth.BlockID // Latest recorded head of the L1 Chain + l2Head eth.BlockID // L2 Unsafe Head + l1Origin eth.BlockID // L1 Origin of the L2 Unsafe head. For sequencing only. + l2SafeHead eth.BlockID // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) + l1Base eth.BlockID // L1 Parent of L2 Safe Head block + l2Finalized eth.BlockID // L2 Block that will never be reversed + l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. // Rollup config Config rollup.Config @@ -69,10 +71,11 @@ func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error return err } + // TODO: Don't start everything from L2 heads s.l1Head = l1Head.Self s.l1Origin = s.l1Head - s.l2UnsafeHead = l2Head.Self // TODO: Makes sense? - s.l2Head = l2Head.Self + s.l2Head = l2Head.Self // TODO: Makes sense? + s.l2SafeHead = l2Head.Self s.l1Base = l2Head.L1Origin s.l1Heads = l1Heads @@ -159,14 +162,14 @@ func (s *state) loop() { continue } // 2. Ask output to create new block - newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2UnsafeHead, s.l1Origin, firstOfEpoch) + newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2Head, s.l2SafeHead, s.l1Origin, firstOfEpoch) if err != nil { - s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2UnsafeHead, "l1Origin", s.l1Origin) + s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", s.l1Origin) continue } // 3. Update unsafe l2 head + epoch - s.l2UnsafeHead = newUnsafeL2Head - s.log.Trace("Created new l2 block", "l2UnsafeHead", s.l2UnsafeHead) + s.l2Head = newUnsafeL2Head + s.log.Trace("Created new l2 block", "l2UnsafeHead", s.l2Head) // 4. Ask for batch submission go func() { _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches @@ -201,7 +204,7 @@ func (s *state) loop() { // TODO: Unsafe head here s.l1Window = nil s.l1Base = nextL2Head.L1Origin - s.l2Head = nextL2Head.Self + s.l2SafeHead = nextL2Head.Self } // Run step if we are able to if s.l1Head.Number-s.l1Base.Number >= s.Config.SeqWindowSize { @@ -226,13 +229,16 @@ func (s *state) loop() { if window, ok := s.sequencingWindow(); ok { s.log.Trace("Have enough cached blocks to run step.") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - newL2Head, err := s.output.step(ctx, s.l2Head, s.l2Finalized, window) + newL2Head, err := s.output.step(ctx, s.l2SafeHead, s.l2Finalized, s.l2Head, window) cancel() if err != nil { - s.log.Error("Error in running the output step.", "err", err, "l2Head", s.l2Head, "l2Finalized", s.l2Finalized, "window", window) + s.log.Error("Error in running the output step.", "err", err, "l2SafeHead", s.l2SafeHead, "l2Finalized", s.l2Finalized, "window", window) continue } - s.l2Head = newL2Head + if s.l2Head == s.l2SafeHead { + s.l2Head = newL2Head + } + s.l2SafeHead = newL2Head s.l1Base = s.l1Window[0] s.l1Window = s.l1Window[1:] // TODO: l2Finalized diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 539baa6fd140..80caa84f06ff 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -38,13 +38,13 @@ func (id testID) ID() eth.BlockID { } } -type outputHandlerFn func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) +type outputHandlerFn func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l2Unsafe eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) -func (fn outputHandlerFn) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { - return fn(ctx, l2Head, l2Finalized, l1Window) +func (fn outputHandlerFn) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l2Unsafe eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { + return fn(ctx, l2Head, l2Finalized, l2Unsafe, l1Window) } -func (fn outputHandlerFn) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { +func (fn outputHandlerFn) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { panic("Unimplemented") } @@ -134,7 +134,7 @@ func (tc *stateTestCase) Run(t *testing.T) { // Unbuffered channels to force a sync point between the test and the state loop. outputIn := make(chan outputArgs) outputReturn := make(chan outputReturnArgs) - outputHandler := func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { + outputHandler := func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l2Unsafe eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { outputIn <- outputArgs{l2Head: l2Head, l2Finalized: l2Finalized, l1Window: l1Window} r := <-outputReturn return r.l2Head, r.err @@ -158,7 +158,7 @@ func (tc *stateTestCase) Run(t *testing.T) { <-time.After(5 * time.Millisecond) assert.Equal(t, step.l1head.ID(), state.l1Head, "l1 head") - assert.Equal(t, step.l2head.ID(), state.l2Head, "l2 head") + assert.Equal(t, step.l2head.ID(), state.l2SafeHead, "l2 head") } } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 7d37d6791463..acfda99d79fd 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -26,23 +26,26 @@ type Downloader interface { FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) } -type DriverAPI interface { - l2.EngineAPI - l2.EthBackend +// L2 is block preparer + BlockByHash +type L2Client interface { + GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) + ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) + ExecutePayload(ctx context.Context, payload *l2.ExecutionPayload) error + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) } type outputImpl struct { dl Downloader - rpc DriverAPI + l2 L2Client log log.Logger Config rollup.Config } -func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { +func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { d.log.Info("creating new block", "l2Parent", l2Parent, "l1Origin", l1Origin, "includeDeposits", includeDeposits) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - l2Info, err := d.rpc.BlockByHash(fetchCtx, l2Parent.Hash) + l2Info, err := d.l2.BlockByHash(fetchCtx, l2Parent.Hash) if err != nil { return l2Parent, nil, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Parent, err) } @@ -64,23 +67,35 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa } } - deposits, err := derive.DeriveDeposits(l1Info, receipts) + l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) + if err != nil { + return l2Parent, nil, err + } + var txns []l2.Data + txns = append(txns, l1InfoTx) + deposits, err := derive.DeriveDeposits(l1Info.NumberU64(), receipts) d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Parent, "l1Origin", l1Origin) if err != nil { return l2Parent, nil, fmt.Errorf("failed to derive deposits: %v", err) } + txns = append(txns, deposits...) - depositStart := len(deposits) + depositStart := len(txns) attrs := &l2.PayloadAttributes{ Timestamp: hexutil.Uint64(timestamp), Random: l2.Bytes32(l1Info.MixDigest()), SuggestedFeeRecipient: d.Config.FeeRecipientAddress, - Transactions: deposits, + Transactions: txns, NoTxPool: false, } + fc := l2.ForkchoiceState{ + HeadBlockHash: l2Parent.Hash, + SafeBlockHash: l2Safe.Hash, + FinalizedBlockHash: l2Finalized.Hash, + } - payload, err := AddBlock(ctx, d.log, d.rpc, l2Parent, l2Finalized.Hash, attrs) + payload, err := d.addBlock(ctx, fc, attrs, false, true) if err != nil { return l2Parent, nil, fmt.Errorf("failed to extend L2 chain: %v", err) } @@ -99,7 +114,8 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa // An incomplete sequencing window will result in an incomplete L2 chain if so. // // After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. -func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l1Input []eth.BlockID) (out eth.BlockID, err error) { +func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (out eth.BlockID, err error) { + // Sanity Checks if len(l1Input) == 0 { return l2Head, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Head) } @@ -107,26 +123,32 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e return l2Head, errors.New("Invalid sequencing window size") } - logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], - "input_l2_parent", l2Head, "finalized_l2", l2Finalized) + logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], "input_l2_parent", l2Head, "finalized_l2", l2Finalized) logger.Trace("Running update step on the L2 node") + // Get inputs from L1 and L2 epoch := rollup.Epoch(l1Input[0].Number) - fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - - l2Info, err := d.rpc.BlockByHash(fetchCtx, l2Head.Hash) + l2Info, err := d.l2.BlockByHash(fetchCtx, l2Head.Hash) if err != nil { - return l2Head, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Head, err) + return l2Head, fmt.Errorf("failed to fetch L2 block info of %s: %w", l2Head, err) } l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Input[0]) if err != nil { - return l2Head, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Input[0], err) + return l2Head, fmt.Errorf("failed to fetch L1 block info of %s: %w", l1Input[0], err) + } + l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) + if err != nil { + return l2Head, fmt.Errorf("failed to create l1InfoTx: %w", err) } receipts, err := d.dl.FetchReceipts(fetchCtx, l1Input[0]) if err != nil { - return l2Head, fmt.Errorf("failed to fetch receipts of %s: %v", l1Input[0], err) + return l2Head, fmt.Errorf("failed to fetch receipts of %s: %w", l1Input[0], err) + } + deposits, err := derive.DeriveDeposits(uint64(epoch), receipts) + if err != nil { + return l2Head, fmt.Errorf("failed to derive deposits: %w", err) } // TODO: with sharding the blobs may be identified in more detail than L1 block hashes transactions, err := d.dl.FetchTransactions(fetchCtx, l1Input) @@ -137,52 +159,73 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e if err != nil { return l2Head, fmt.Errorf("failed to fetch create batches from transactions: %w", err) } + // Make batches contiguous minL2Time := l2Info.Time() + d.Config.BlockTime maxL2Time := l1Info.Time() batches = derive.FilterBatches(&d.Config, epoch, minL2Time, maxL2Time, batches) + batches = derive.SortedAndPreparedBatches(batches, uint64(epoch), d.Config.BlockTime, minL2Time, maxL2Time) - attrsList, err := derive.PayloadAttributes(&d.Config, l1Info, receipts, batches, l2Info, minL2Time, maxL2Time) - if err != nil { - return l2Head, fmt.Errorf("failed to derive execution payload inputs: %v", err) + // Note: SafeBlockHash currently needs to be set b/c of Geth + fc := l2.ForkchoiceState{ + HeadBlockHash: l2Head.Hash, + SafeBlockHash: l2Head.Hash, + FinalizedBlockHash: l2Finalized.Hash, } - + updateUnsafeHead := unsafeL2Head.Hash == l2Head.Hash // If unsafe head is the same as the safe head, keep it up to date + // Execute each L2 block in the epoch last := l2Head - for i, attrs := range attrsList { - payload, err := AddBlock(ctx, logger, d.rpc, last, l2Finalized.Hash, attrs) + for i, batch := range batches { + var txns []l2.Data + txns = append(txns, l1InfoTx) + if i == 0 { + txns = append(txns, deposits...) + } + txns = append(txns, batch.Transactions...) + attrs := &l2.PayloadAttributes{ + Timestamp: hexutil.Uint64(batch.Timestamp), + Random: l2.Bytes32(l1Info.MixDigest()), + SuggestedFeeRecipient: d.Config.FeeRecipientAddress, + Transactions: txns, + NoTxPool: false, + } + + payload, err := d.addBlock(ctx, fc, attrs, true, updateUnsafeHead) if err != nil { - return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %v", i, len(attrsList), epoch, err) + return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) } last = payload.ID() + fc.HeadBlockHash = last.Hash } return last, nil } -// AddBlock extends the L2 chain by deriving the full execution payload from inputs, -// and then executing and persisting it. -// -// After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. -func AddBlock(ctx context.Context, logger log.Logger, rpc DriverAPI, - l2Parent eth.BlockID, l2Finalized common.Hash, attrs *l2.PayloadAttributes) (*l2.ExecutionPayload, error) { - - payload, err := derive.ExecutionPayload(ctx, rpc, l2Parent.Hash, l2Finalized, attrs) +func (d *outputImpl) addBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, updateSafe, updateUnsafe bool) (*l2.ExecutionPayload, error) { + fcRes, err := d.l2.ForkchoiceUpdate(ctx, &fc, attrs) if err != nil { - return nil, fmt.Errorf("failed to derive execution payload: %v", err) + return nil, fmt.Errorf("failed to create new block via forkchoice: %w", err) } - - logger = logger.New("derived_l2", payload.ID()) - logger.Info("derived full block", "l2Parent", l2Parent, "attrs", attrs, "payload", payload) - - err = l2.ExecutePayload(ctx, rpc, payload) + id := fcRes.PayloadID + if id == nil { + return nil, errors.New("nil id in forkchoice result when expecting a valid ID") + } + payload, err := d.l2.GetPayload(ctx, *id) if err != nil { - return nil, fmt.Errorf("failed to apply execution payload: %v", err) + return nil, fmt.Errorf("failed to get execution payload: %w", err) } - logger.Info("executed block") - - err = l2.ForkchoiceUpdate(ctx, rpc, payload.BlockHash, l2Finalized) + err = d.l2.ExecutePayload(ctx, payload) + if err != nil { + return nil, fmt.Errorf("failed to insert execution payload: %w", err) + } + if updateSafe { + fc.SafeBlockHash = payload.BlockHash + } + if updateUnsafe { + fc.HeadBlockHash = payload.BlockHash + } + _, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { - return nil, fmt.Errorf("failed to persist execution payload: %v", err) + return nil, fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", err) } - logger.Info("updated fork-choice with block") return payload, nil } From 6b988c3f0f4b75369d2e414fbad72efaa167e839 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 17 Mar 2022 12:57:14 -0700 Subject: [PATCH 316/585] ref impl: Flatten source interfaces This makes the following changes: 1. Flatten the L1 & L2 source into one object that fulfills several interfaces (primarily the BlockReference) 2. Place the L1Range function in the L1 Source (removed from sync package) 3. Provide FindSyncStart with the L2 block to use --- opnode/l1/source.go | 91 +++++++++++++++++---- opnode/l2/source.go | 39 +++++++-- opnode/node/node.go | 3 +- opnode/rollup/derive/payload_attributes.go | 8 +- opnode/rollup/driver/driver.go | 64 ++++++++------- opnode/rollup/driver/fake_chain.go | 25 +++++- opnode/rollup/driver/state.go | 38 ++++----- opnode/rollup/driver/state_test.go | 2 +- opnode/rollup/driver/step.go | 22 +---- opnode/rollup/sync/reference.go | 92 --------------------- opnode/rollup/sync/start.go | 94 +++++----------------- opnode/rollup/sync/start_test.go | 30 ++++++- 12 files changed, 237 insertions(+), 271 deletions(-) delete mode 100644 opnode/rollup/sync/reference.go diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 2f6b1eba65bd..80c0ad0b8b36 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -2,6 +2,7 @@ package l1 import ( "context" + "errors" "fmt" "math/big" @@ -13,6 +14,11 @@ import ( "github.com/ethereum/go-ethereum/ethclient" ) +var WrongChainErr = errors.New("wrong chain") +var TooDeepReorgErr = errors.New("reorg is too deep") +var MaxReorgDepth = 500 +var MaxBlocksInL1Range = uint64(100) + type Source struct { client *ethclient.Client downloader *Downloader @@ -25,20 +31,6 @@ func NewSource(client *ethclient.Client) Source { } } -func (s Source) BlockLinkByNumber(ctx context.Context, num uint64) (self eth.BlockID, parent eth.BlockID, err error) { - header, err := s.client.HeaderByNumber(ctx, big.NewInt(int64(num))) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("failed to determine block-hash of height %d, could not get header: %w", num, err) - } - parentNum := num - if parentNum > 0 { - parentNum -= 1 - } - return eth.BlockID{Hash: header.Hash(), Number: num}, eth.BlockID{Hash: header.ParentHash, Number: parentNum}, nil - -} - func (s Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { return s.client.SubscribeNewHead(ctx, ch) } @@ -74,6 +66,7 @@ func (s Source) Close() { func (s Source) FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) { return s.client.BlockByHash(ctx, id.Hash) } + func (s Source) FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) { _, receipts, err := s.Fetch(ctx, id) return receipts, err @@ -91,3 +84,73 @@ func (s Source) FetchTransactions(ctx context.Context, window []eth.BlockID) ([] return txns, nil } +func (s Source) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { + return s.l1BlockRefByNumber(ctx, nil) +} + +func (s Source) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { + return s.l1BlockRefByNumber(ctx, new(big.Int).SetUint64(l1Num)) +} + +// l1BlockRefByNumber wraps l1.HeaderByNumber to return an eth.L1BlockRef +// This is internal because the exposed L1BlockRefByNumber takes uint64 instead of big.Ints +func (s Source) l1BlockRefByNumber(ctx context.Context, number *big.Int) (eth.L1BlockRef, error) { + header, err := s.client.HeaderByNumber(ctx, number) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L1BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", number, err) + } + l1Num := header.Number.Uint64() + parentNum := l1Num + if parentNum > 0 { + parentNum -= 1 + } + return eth.L1BlockRef{ + Self: eth.BlockID{Hash: header.Hash(), Number: l1Num}, + Parent: eth.BlockID{Hash: header.ParentHash, Number: parentNum}, + }, nil +} + +// L1Range returns a range of L1 block beginning just after `begin`. +func (s Source) L1Range(ctx context.Context, begin eth.BlockID) ([]eth.BlockID, error) { + // Ensure that we start on the expected chain. + if canonicalBegin, err := s.L1BlockRefByNumber(ctx, begin.Number); err != nil { + return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) + } else { + if canonicalBegin.Self != begin { + return nil, fmt.Errorf("Re-org at begin block. Expected: %v. Actual: %v", begin, canonicalBegin.Self) + } + } + + l1head, err := s.L1HeadBlockRef(ctx) + if err != nil { + return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) + } + maxBlocks := MaxBlocksInL1Range + // Cap maxBlocks if there are less than maxBlocks between `begin` and the head of the chain. + if l1head.Self.Number-begin.Number <= maxBlocks { + maxBlocks = l1head.Self.Number - begin.Number + } + + if maxBlocks == 0 { + return nil, nil + } + + prevHash := begin.Hash + var res []eth.BlockID + // TODO: Walk backwards to be able to use block by hash + for i := begin.Number + 1; i < begin.Number+maxBlocks+1; i++ { + n, err := s.L1BlockRefByNumber(ctx, i) + if err != nil { + return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) + } + // TODO(Joshua): Look into why this fails around the genesis block + if n.Parent.Number != 0 && n.Parent.Hash != prevHash { + return nil, errors.New("re-organization occurred while attempting to get l1 range") + } + prevHash = n.Self.Hash + res = append(res, n.Self) + } + + return res, nil +} diff --git a/opnode/l2/source.go b/opnode/l2/source.go index 74d820a19f4c..c7b8f14cdcfb 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -6,6 +6,9 @@ import ( "math/big" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" @@ -14,16 +17,18 @@ import ( ) type Source struct { - rpc *rpc.Client // raw RPC client. Used for the consensus namespace - client *ethclient.Client // go-ethereum's wrapper around the rpc client for the eth namespace - log log.Logger + rpc *rpc.Client // raw RPC client. Used for the consensus namespace + client *ethclient.Client // go-ethereum's wrapper around the rpc client for the eth namespace + genesis *rollup.Genesis + log log.Logger } -func NewSource(l2Node *rpc.Client, log log.Logger) (*Source, error) { +func NewSource(ll2Node *rpc.Client, genesis *rollup.Genesis, log log.Logger) (*Source, error) { return &Source{ - rpc: l2Node, - client: ethclient.NewClient(l2Node), - log: log, + rpc: ll2Node, + client: ethclient.NewClient(ll2Node), + genesis: genesis, + log: log, }, nil } @@ -123,3 +128,23 @@ func (s *Source) GetPayload(ctx context.Context, payloadId PayloadID) (*Executio e.Debug("Received payload") return &result, nil } + +// L2BlockRefByNumber returns the canonical block and parent ids. +func (s *Source) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { + block, err := s.client.BlockByNumber(ctx, l2Num) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) + } + return derive.BlockReferences(block, s.genesis) +} + +// L2BlockRefByHash returns the block & parent ids based on the supplied hash. The returned BlockRef may not be in the canonical chain +func (s *Source) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { + block, err := s.client.BlockByHash(ctx, l2Hash) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) + } + return derive.BlockReferences(block, s.genesis) +} diff --git a/opnode/node/node.go b/opnode/node/node.go index 4c3a3723d658..675f2dc8ffb0 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -61,6 +61,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { // l1Node.SetHeader() l1Source := l1.NewSource(ethclient.NewClient(l1Node)) var l2Engines []*driver.Driver + genesis := cfg.Rollup.Genesis for i, addr := range cfg.L2EngineAddrs { l2Node, err := dialRPCClientWithBackoff(ctx, log, addr) @@ -69,7 +70,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { } // TODO: we may need to authenticate the connection with L2 // backend.SetHeader() - client, err := l2.NewSource(l2Node, log.New("engine_client", i)) + client, err := l2.NewSource(l2Node, &genesis, log.New("engine_client", i)) if err != nil { return nil, err } diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 82273baee22a..a2f6bf67c7c0 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -8,8 +8,8 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/trie" @@ -270,7 +270,7 @@ func SortedAndPreparedBatches(batches []*BatchData, epoch, blockTime, minL2Time, return out } -func L1InfoDepositBytes(l1Info L1Info) (l2.Data, error) { +func L1InfoDepositBytes(l1Info L1Info) (hexutil.Bytes, error) { l1Tx := types.NewTx(L1InfoDeposit(l1Info)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { @@ -279,12 +279,12 @@ func L1InfoDepositBytes(l1Info L1Info) (l2.Data, error) { return opaqueL1Tx, nil } -func DeriveDeposits(epoch uint64, receipts []*types.Receipt) ([]l2.Data, error) { +func DeriveDeposits(epoch uint64, receipts []*types.Receipt) ([]hexutil.Bytes, error) { userDeposits, err := UserDeposits(epoch, receipts) if err != nil { return nil, fmt.Errorf("failed to derive user deposits: %v", err) } - encodedTxs := make([]l2.Data, 0, len(userDeposits)) + encodedTxs := make([]hexutil.Bytes, 0, len(userDeposits)) for i, tx := range userDeposits { opaqueTx, err := types.NewTx(tx).MarshalBinary() if err != nil { diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 474d31e38a46..41d1b8bbbaee 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -2,14 +2,15 @@ package driver import ( "context" + "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -21,15 +22,44 @@ type BatchSubmitter interface { Submit(config *rollup.Config, batches []*derive.BatchData) (common.Hash, error) } +type Downloader interface { + // FetchL1Info fetches the L1 header information corresponding to a L1 block ID + FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) + // FetchReceipts of a L1 block + FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) + // FetchTransactions from the given window of L1 blocks + FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) +} + +type BlockPreparer interface { + GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) + ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) + ExecutePayload(ctx context.Context, payload *l2.ExecutionPayload) error + BlockByHash(context.Context, common.Hash) (*types.Block, error) +} + +type L1Chain interface { + L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) + L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) + L1Range(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) +} + +// TODO: Extend L2 Interface to get safe/unsafe blocks (specifically for Unsafe L2 head) +type L2Chain interface { + L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) + L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) +} + +type outputInterface interface { + step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.BlockID, error) + newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) +} + func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { if sequencer && submitter == nil { log.Error("Bad configuration") // TODO: return error } - input := &inputImpl{ - chainSource: sync.NewChainSource(l1, l2, &cfg.Genesis), - genesis: &cfg.Genesis, - } output := &outputImpl{ Config: cfg, dl: l1, @@ -37,7 +67,7 @@ func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, log: log, } return &Driver{ - s: NewState(log, cfg, input, output, submitter, sequencer), + s: NewState(log, cfg, l1, l2, output, submitter, sequencer), } } @@ -47,25 +77,3 @@ func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error func (d *Driver) Close() error { return d.s.Close() } - -type inputImpl struct { - chainSource sync.ChainSource - genesis *rollup.Genesis -} - -func (i *inputImpl) L1Head(ctx context.Context) (eth.L1BlockRef, error) { - return i.chainSource.L1HeadBlockRef(ctx) -} - -func (i *inputImpl) L2Head(ctx context.Context) (eth.L2BlockRef, error) { - return i.chainSource.L2BlockRefByNumber(ctx, nil) - -} - -func (i *inputImpl) L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) { - return sync.FindL1Range(ctx, i.chainSource, base) -} - -func (i *inputImpl) SafeL2Head(ctx context.Context) (eth.L2BlockRef, error) { - return sync.FindSafeL2Head(ctx, i.chainSource, i.genesis) -} diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 5b5475397a7b..f95985151e66 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" ) func fakeGenesis(l1 rune, l2 rune, l2offset int) rollup.Genesis { @@ -89,6 +88,27 @@ type fakeChainSource struct { log log.Logger } +func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) { + var out []eth.BlockID + found := false + for i, b := range m.l1s[m.l1reorg] { + if found { + out = append(out, b.Self) + } + if b.Self == base { + found = true + } + if i == m.l1head { + if found { + return out, nil + } else { + return nil, ethereum.NotFound + } + } + } + return nil, ethereum.NotFound +} + func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { m.log.Trace("L1BlockRefByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.l1reorg) if l1Num > uint64(m.l1head) { @@ -131,7 +151,8 @@ func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Ha return eth.L2BlockRef{}, ethereum.NotFound } -var _ sync.ChainSource = (*fakeChainSource)(nil) +var _ L1Chain = (*fakeChainSource)(nil) +var _ L2Chain = (*fakeChainSource)(nil) func (m *fakeChainSource) reorgL1() { m.log.Trace("Reorg L1", "new_reorg", m.l1reorg+1, "old_reorg", m.l1reorg) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index f862772185aa..74cd580673a2 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -7,24 +7,10 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum/log" ) -// TODO: Extend L2 Inteface to get safe/unsafe blocks (specifically for Unsafe L2 head) - -type inputInterface interface { - L1Head(ctx context.Context) (eth.L1BlockRef, error) - L2Head(ctx context.Context) (eth.L2BlockRef, error) - L1ChainWindow(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) - // SafeL2Head is the L2 Head found via the sync algorithm - SafeL2Head(ctx context.Context) (eth.L2BlockRef, error) -} - -type outputInterface interface { - step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.BlockID, error) - newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) -} - type state struct { // Chain State l1Head eth.BlockID // Latest recorded head of the L1 Chain @@ -41,7 +27,8 @@ type state struct { // Connections (in/out) l1Heads <-chan eth.L1BlockRef - input inputInterface + l1 L1Chain + l2 L2Chain output outputInterface bss BatchSubmitter @@ -49,12 +36,13 @@ type state struct { done chan struct{} } -func NewState(log log.Logger, config rollup.Config, input inputInterface, output outputInterface, submitter BatchSubmitter, sequencer bool) *state { +func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, submitter BatchSubmitter, sequencer bool) *state { return &state{ Config: config, done: make(chan struct{}), log: log, - input: input, + l1: l1, + l2: l2, output: output, bss: submitter, sequencer: sequencer, @@ -62,11 +50,11 @@ func NewState(log log.Logger, config rollup.Config, input inputInterface, output } func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error { - l1Head, err := s.input.L1Head(ctx) + l1Head, err := s.l1.L1HeadBlockRef(ctx) if err != nil { return err } - l2Head, err := s.input.L2Head(ctx) + l2Head, err := s.l2.L2BlockRefByNumber(ctx, nil) if err != nil { return err } @@ -101,7 +89,7 @@ func (s *state) l1WindowEnd() eth.BlockID { // It starts just after `s.l1WindowEnd()`. func (s *state) extendL1Window(ctx context.Context) error { s.log.Trace("Extending the cached window from L1", "cached_size", len(s.l1Window), "window_end", s.l1WindowEnd()) - nexts, err := s.input.L1ChainWindow(ctx, s.l1WindowEnd()) + nexts, err := s.l1.L1Range(ctx, s.l1WindowEnd()) if err != nil { return err } @@ -195,7 +183,13 @@ func (s *state) loop() { } } else { s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.Parent, "new_l1_head", newL1Head.Self) - nextL2Head, err := s.input.SafeL2Head(ctx) + // TODO(Joshua): Fix having to make this call when being careful about the exact state + l2Head, err := s.l2.L2BlockRefByNumber(context.Background(), nil) + if err != nil { + s.log.Error("Could not get fetch L2 head when trying to handle a re-org", "err", err) + continue + } + nextL2Head, err := sync.FindSafeL2Head(ctx, l2Head.Self, s.l1, s.l2, &s.Config.Genesis) if err != nil { s.log.Error("Could not get new safe L2 head when trying to handle a re-org", "err", err) continue diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 80caa84f06ff..112df03939c6 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -140,7 +140,7 @@ func (tc *stateTestCase) Run(t *testing.T) { return r.l2Head, r.err } config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis, BlockTime: 2} - state := NewState(log, config, &inputImpl{chainSource: chainSource, genesis: &tc.genesis}, outputHandlerFn(outputHandler), nil, false) + state := NewState(log, config, chainSource, chainSource, outputHandlerFn(outputHandler), nil, false) defer func() { assert.NoError(t, state.Close(), "Error closing state") }() diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index acfda99d79fd..554c3a5bf417 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -11,32 +11,14 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) -type Downloader interface { - // FetchL1Info fetches the L1 header information corresponding to a L1 block ID - FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) - // FetchReceipts of a L1 block - FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) - // FetchTransactions from the given window of L1 blocks - FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) -} - -// L2 is block preparer + BlockByHash -type L2Client interface { - GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) - ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) - ExecutePayload(ctx context.Context, payload *l2.ExecutionPayload) error - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) -} - type outputImpl struct { dl Downloader - l2 L2Client + l2 BlockPreparer log log.Logger Config rollup.Config } @@ -194,7 +176,7 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) } last = payload.ID() - fc.HeadBlockHash = last.Hash + fc.HeadBlockHash = last.Hash // should be safe block, but geth is broken } return last, nil diff --git a/opnode/rollup/sync/reference.go b/opnode/rollup/sync/reference.go deleted file mode 100644 index 305258d7cfb7..000000000000 --- a/opnode/rollup/sync/reference.go +++ /dev/null @@ -1,92 +0,0 @@ -package sync - -import ( - "context" - "fmt" - "math/big" - - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -// L1Client is the subset of methods that ChainSource needs to determine the L1 block graph -type L1Client interface { - HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) -} - -// L2Client is the subset of methods that ChainSource needs to determine the L2 block graph -type L2Client interface { - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) -} - -// ChainSource provides access to the L1 and L2 block graph -type ChainSource interface { - L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) - L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) - L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) - L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) -} - -func NewChainSource(l1 L1Client, l2 L2Client, genesis *rollup.Genesis) *chainSourceImpl { - return &chainSourceImpl{l1: l1, l2: l2, genesis: genesis} -} - -type chainSourceImpl struct { - l1 L1Client - l2 L2Client - genesis *rollup.Genesis -} - -// L1BlockRefByNumber returns the canonical block and parent ids. -func (src chainSourceImpl) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { - return src.l1BlockRefByNumber(ctx, new(big.Int).SetUint64(l1Num)) -} - -// L1BlockRefByNumber returns the canonical head block and parent ids. -func (src chainSourceImpl) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { - return src.l1BlockRefByNumber(ctx, nil) -} - -// l1BlockRefByNumber wraps l1.HeaderByNumber to return an eth.L1BlockRef -// This is internal because the exposed L1BlockRefByNumber takes uint64 instead of big.Ints -func (src chainSourceImpl) l1BlockRefByNumber(ctx context.Context, number *big.Int) (eth.L1BlockRef, error) { - header, err := src.l1.HeaderByNumber(ctx, number) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L1BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", number, err) - } - l1Num := header.Number.Uint64() - parentNum := l1Num - if parentNum > 0 { - parentNum -= 1 - } - return eth.L1BlockRef{ - Self: eth.BlockID{Hash: header.Hash(), Number: l1Num}, - Parent: eth.BlockID{Hash: header.ParentHash, Number: parentNum}, - }, nil -} - -// L2BlockRefByNumber returns the canonical block and parent ids. -func (src chainSourceImpl) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { - block, err := src.l2.BlockByNumber(ctx, l2Num) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) - } - return derive.BlockReferences(block, src.genesis) -} - -// L2BlockRefByHash returns the block & parent ids based on the supplied hash. The returned BlockRef may not be in the canonical chain -func (src chainSourceImpl) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { - block, err := src.l2.BlockByHash(ctx, l2Hash) - if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) - } - return derive.BlockReferences(block, src.genesis) -} diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 7efcb3cdfff6..386a810c1ff7 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -35,56 +35,41 @@ import ( "context" "errors" "fmt" + "math/big" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" ) +type L1Chain interface { + L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) + L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) +} + +type L2Chain interface { + L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) + L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) +} + var WrongChainErr = errors.New("wrong chain") var TooDeepReorgErr = errors.New("reorg is too deep") var MaxReorgDepth = 500 -var MaxBlocksInL1Range = uint64(100) - -// FindSyncStart finds the L2 head and the chain of L1 blocks after the L1 base block. -// Note: The ChainSource should memoize calls as the L1 and L2 chains will be walked multiple times. -// The L2 Head is the highest possible l2block such that it is valid (see above rules). -// It also returns a portion of the L1 chain starting just after l2block.l1parent.number. -// - The returned L1 blocks were canonical when the function was called. -// - The returned L1 block are contiguous and ordered from low to high. -// - The first block (if len > 0) has height l2block.l1parent.number + 1. -// - The length of the array may be any value, including 0. -// If err is not nil, the above return values are not well defined. An error will be returned in the following cases: -// - Wrapped ethereum.NotFound if it could not find a block in L1 or L2. This error may be temporary. -// - Wrapped WrongChainErr if the l1_rollup_genesis block is not reachable from the L2 chain. -func FindSyncStart(ctx context.Context, source ChainSource, genesis *rollup.Genesis) ([]eth.BlockID, eth.BlockID, error) { - l2Head, err := FindSafeL2Head(ctx, source, genesis) - if err != nil { - return nil, eth.BlockID{}, err - } - l1blocks, err := FindL1Range(ctx, source, l2Head.L1Origin) - if err != nil { - return nil, eth.BlockID{}, fmt.Errorf("failed to fetch l1 range: %w", err) - } - return l1blocks, l2Head.Self, nil - -} - -// FindSafeL2Head takes the current L2 Head and then finds the topmost L2 head that is valid -// In the case that there are no re-orgs, this is just the L2 head. Otherwise it has to walk back -// until it finds the first L2 block that is based on a canonical L1 block. -func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Genesis) (eth.L2BlockRef, error) { +// FindSafeL2Head takes the supplied L2 start block and walks the L2 chain until it finds the first L2 block reachable from the supplied +// block that is also canonical. +func FindSafeL2Head(ctx context.Context, start eth.BlockID, l1 L1Chain, l2 L2Chain, genesis *rollup.Genesis) (eth.L2BlockRef, error) { // Starting point - l2Head, err := source.L2BlockRefByNumber(ctx, nil) + l2Head, err := l2.L2BlockRefByHash(ctx, start.Hash) if err != nil { return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 head: %w", err) } reorgDepth := 0 // Walk L2 chain from L2 head to first L2 block which has a L1 Parent that is canonical. May walk to L2 genesis for n := l2Head; ; { - l1header, err := source.L1BlockRefByNumber(ctx, n.L1Origin.Number) + l1header, err := l1.L1BlockRefByNumber(ctx, n.L1Origin.Number) if err != nil { // Generic error, bail out. if !errors.Is(err, ethereum.NotFound) { @@ -105,7 +90,7 @@ func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Gen } // Pull L2 parent for next iteration - n, err = source.L2BlockRefByHash(ctx, n.Parent.Hash) + n, err = l2.L2BlockRefByHash(ctx, n.Parent.Hash) if err != nil { return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.Parent.Hash, err) } @@ -115,46 +100,3 @@ func FindSafeL2Head(ctx context.Context, source ChainSource, genesis *rollup.Gen } } } - -// FindL1Range returns a range of L1 block beginning just after `begin`. -func FindL1Range(ctx context.Context, source ChainSource, begin eth.BlockID) ([]eth.BlockID, error) { - // Ensure that we start on the expected chain. - if canonicalBegin, err := source.L1BlockRefByNumber(ctx, begin.Number); err != nil { - return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) - } else { - if canonicalBegin.Self != begin { - return nil, fmt.Errorf("Re-org at begin block. Expected: %v. Actual: %v", begin, canonicalBegin.Self) - } - } - - l1head, err := source.L1HeadBlockRef(ctx) - if err != nil { - return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) - } - maxBlocks := MaxBlocksInL1Range - // Cap maxBlocks if there are less than maxBlocks between `begin` and the head of the chain. - if l1head.Self.Number-begin.Number <= maxBlocks { - maxBlocks = l1head.Self.Number - begin.Number - } - - if maxBlocks == 0 { - return nil, nil - } - - prevHash := begin.Hash - var res []eth.BlockID - for i := begin.Number + 1; i < begin.Number+maxBlocks+1; i++ { - n, err := source.L1BlockRefByNumber(ctx, i) - if err != nil { - return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) - } - // TODO(Joshua): Look into why this fails around the genesis block - if n.Parent.Number != 0 && n.Parent.Hash != prevHash { - return nil, errors.New("re-organization occurred while attempting to get l1 range") - } - prevHash = n.Self.Hash - res = append(res, n.Self) - } - - return res, nil -} diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 78c0ceb97718..c6b71ce88588 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type fakeChainSource struct { @@ -17,6 +18,23 @@ type fakeChainSource struct { L2 []eth.L2BlockRef } +func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) { + var out []eth.BlockID + found := false + for _, b := range m.L1 { + if found { + out = append(out, b.Self) + } + if b.Self == base { + found = true + } + } + if found { + return out, nil + } + return nil, ethereum.NotFound +} + func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { if l1Num >= uint64(len(m.L1)) { return eth.L1BlockRef{}, ethereum.NotFound @@ -52,7 +70,8 @@ func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Ha return eth.L2BlockRef{}, ethereum.NotFound } -var _ ChainSource = (*fakeChainSource)(nil) +var _ L1Chain = (*fakeChainSource)(nil) +var _ L2Chain = (*fakeChainSource)(nil) func fakeID(id rune, num uint64) eth.BlockID { var h common.Hash @@ -129,14 +148,17 @@ func (c *syncStartTestCase) Run(t *testing.T) { L1: fakeID(c.GenesisL1, c.OffsetL2), L2: fakeID(c.GenesisL2, 0), } - - nextRefL1s, refL2, err := FindSyncStart(context.Background(), msr, genesis) + head, err := msr.L2BlockRefByNumber(context.Background(), nil) + require.Nil(t, err) + refL2, err := FindSafeL2Head(context.Background(), head.Self, msr, msr, genesis) if c.ExpectedErr != nil { assert.Error(t, err, "Expecting an error in this test case") assert.ErrorIs(t, err, c.ExpectedErr) } else { - expectedRefL2 := refToRune(refL2) + nextRefL1s, err := msr.L1Range(context.Background(), refL2.L1Origin) + require.Nil(t, err) + expectedRefL2 := refToRune(refL2.Self) var expectedRefsL1 []rune for _, ref := range nextRefL1s { expectedRefsL1 = append(expectedRefsL1, refToRune(ref)) From 265b536daaeab07ca87e49d0b88b327cd7a42b2e Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Mon, 21 Mar 2022 16:35:43 -0700 Subject: [PATCH 317/585] fix: test_basefee now tests basefee --- packages/contracts/contracts/test/L1Block.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts/contracts/test/L1Block.t.sol index c07aadde2788..c86107c62125 100644 --- a/packages/contracts/contracts/test/L1Block.t.sol +++ b/packages/contracts/contracts/test/L1Block.t.sol @@ -29,7 +29,7 @@ contract L1BLockTest is DSTest { } function test_basefee() external { - assertEq(lb.timestamp(), 2); + assertEq(lb.basefee(), 3); } function test_hash() external { From 22ccfed9b18fa6638bd4ddcdf8e8c76da6135899 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 21 Mar 2022 16:58:05 -0700 Subject: [PATCH 318/585] ref impl: Address PR Comments - var -> const (+ removing som extra copies) - Rename BlockPreparer interface to Engine - Remove out of date comment and update safe block --- opnode/l1/source.go | 5 +---- opnode/rollup/driver/driver.go | 2 +- opnode/rollup/driver/step.go | 6 ++++-- opnode/rollup/sync/start.go | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 80c0ad0b8b36..03c310182ac6 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -14,10 +14,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient" ) -var WrongChainErr = errors.New("wrong chain") -var TooDeepReorgErr = errors.New("reorg is too deep") -var MaxReorgDepth = 500 -var MaxBlocksInL1Range = uint64(100) +const MaxBlocksInL1Range = uint64(100) type Source struct { client *ethclient.Client diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 41d1b8bbbaee..d515ed8efaeb 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -31,7 +31,7 @@ type Downloader interface { FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) } -type BlockPreparer interface { +type Engine interface { GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) ExecutePayload(ctx context.Context, payload *l2.ExecutionPayload) error diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 554c3a5bf417..1afca3e3f508 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -18,7 +18,7 @@ import ( type outputImpl struct { dl Downloader - l2 BlockPreparer + l2 Engine log log.Logger Config rollup.Config } @@ -176,7 +176,9 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) } last = payload.ID() - fc.HeadBlockHash = last.Hash // should be safe block, but geth is broken + // TODO(Joshua): Update this to handle verifiers + sequencers + fc.HeadBlockHash = last.Hash + fc.SafeBlockHash = last.Hash } return last, nil diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 386a810c1ff7..1c245cf994c4 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -56,7 +56,8 @@ type L2Chain interface { var WrongChainErr = errors.New("wrong chain") var TooDeepReorgErr = errors.New("reorg is too deep") -var MaxReorgDepth = 500 + +const MaxReorgDepth = 500 // FindSafeL2Head takes the supplied L2 start block and walks the L2 chain until it finds the first L2 block reachable from the supplied // block that is also canonical. From 1ce49833e53e38454f4a2000a9db880798ca4645 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 22 Mar 2022 00:10:52 +0100 Subject: [PATCH 319/585] opnode/rollup/derive,specs: verify batch does not contain deposit tx type, sanity-check receipts, use l2 block height for deposits, update specs --- opnode/l1/source.go | 17 ++- opnode/rollup/derive/invert_test.go | 28 ++-- opnode/rollup/derive/payload_attributes.go | 31 ++--- .../rollup/derive/payload_attributes_test.go | 128 ++++++++++++++++++ opnode/rollup/driver/driver.go | 4 +- opnode/rollup/driver/step.go | 9 +- specs/deposits.md | 9 ++ specs/rollup-node.md | 11 +- 8 files changed, 192 insertions(+), 45 deletions(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 03c310182ac6..e40bc2ade487 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -6,6 +6,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum" @@ -64,9 +66,19 @@ func (s Source) FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, return s.client.BlockByHash(ctx, id.Hash) } -func (s Source) FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) { +func (s Source) FetchReceipts(ctx context.Context, id eth.BlockID, receiptHash common.Hash) ([]*types.Receipt, error) { _, receipts, err := s.Fetch(ctx, id) - return receipts, err + if err != nil { + return nil, err + } + // Sanity-check: external L1-RPC sources are notorious for not returning all receipts, + // or returning them out-of-order. Verify the receipts against the expected receipt-hash. + hasher := trie.NewStackTrie(nil) + computed := types.DeriveSha(types.Receipts(receipts), hasher) + if receiptHash != computed { + return nil, fmt.Errorf("failed to validate receipts of %s, computed receipt-hash %s does not match expected hash %d", id, computed, receiptHash) + } + return receipts, nil } func (s Source) FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) { @@ -79,7 +91,6 @@ func (s Source) FetchTransactions(ctx context.Context, window []eth.BlockID) ([] txns = append(txns, block.Transactions()...) } return txns, nil - } func (s Source) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { return s.l1BlockRefByNumber(ctx, nil) diff --git a/opnode/rollup/derive/invert_test.go b/opnode/rollup/derive/invert_test.go index c9a0c7c8b90f..9d7038a7a2df 100644 --- a/opnode/rollup/derive/invert_test.go +++ b/opnode/rollup/derive/invert_test.go @@ -5,16 +5,21 @@ import ( "math/rand" "testing" + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" ) type l1MockInfo struct { - num uint64 - time uint64 - hash common.Hash - baseFee *big.Int - mixDigest [32]byte + num uint64 + time uint64 + hash common.Hash + baseFee *big.Int + mixDigest [32]byte + receiptRoot common.Hash } func (l *l1MockInfo) NumberU64() uint64 { @@ -37,6 +42,10 @@ func (l *l1MockInfo) MixDigest() common.Hash { return l.mixDigest } +func (l *l1MockInfo) ReceiptHash() common.Hash { + return l.receiptRoot +} + func randomHash(rng *rand.Rand) (out common.Hash) { rng.Read(out[:]) return @@ -44,10 +53,11 @@ func randomHash(rng *rand.Rand) (out common.Hash) { func randomL1Info(rng *rand.Rand) *l1MockInfo { return &l1MockInfo{ - num: rng.Uint64(), - time: rng.Uint64(), - hash: randomHash(rng), - baseFee: big.NewInt(rng.Int63n(1000_0000 * 1e9)), // a million GWEI + num: rng.Uint64(), + time: rng.Uint64(), + hash: randomHash(rng), + baseFee: big.NewInt(rng.Int63n(1000_000 * params.GWei)), // a million GWEI + receiptRoot: types.EmptyRootHash, } } diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index a2f6bf67c7c0..55f4426b8436 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -12,7 +12,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" ) @@ -120,6 +119,7 @@ type L1Info interface { BaseFee() *big.Int // MixDigest field, reused for randomness after The Merge (Bellatrix hardfork) MixDigest() common.Hash + ReceiptHash() common.Hash } // L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block @@ -148,19 +148,8 @@ func L1InfoDeposit(block L1Info) *types.DepositTx { } } -type ReceiptHash interface { - ReceiptHash() common.Hash -} - -// CheckReceipts sanity checks that the receipts are consistent with the block data. -func CheckReceipts(block ReceiptHash, receipts []*types.Receipt) bool { - hasher := trie.NewStackTrie(nil) - computed := types.DeriveSha(types.Receipts(receipts), hasher) - return block.ReceiptHash() == computed -} - -// UserDeposits transforms a L1 block and corresponding receipts into the transaction inputs for a full L2 block -func UserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, error) { +// UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block +func UserDeposits(l2BlockHeight uint64, receipts []*types.Receipt) ([]*types.DepositTx, error) { var out []*types.DepositTx for _, rec := range receipts { @@ -170,7 +159,7 @@ func UserDeposits(height uint64, receipts []*types.Receipt) ([]*types.DepositTx, for _, log := range rec.Logs { if log.Address == DepositContractAddr { // offset transaction index by 1, the first is the l1-info tx - dep, err := UnmarshalLogEvent(height, uint64(len(out))+1, log) + dep, err := UnmarshalLogEvent(l2BlockHeight, uint64(len(out))+1, log) if err != nil { return nil, fmt.Errorf("malformatted L1 deposit log: %v", err) } @@ -240,6 +229,14 @@ func ValidBatch(batch *BatchData, config *rollup.Config, epoch rollup.Epoch, min if batch.Timestamp >= maxL2Time { return false // too far in future } + for _, txBytes := range batch.Transactions { + if len(txBytes) == 0 { + return false // transaction data must not be empty + } + if txBytes[0] == types.DepositTxType { + return false // sequencers may not embed any deposits into batch data + } + } return true } @@ -279,8 +276,8 @@ func L1InfoDepositBytes(l1Info L1Info) (hexutil.Bytes, error) { return opaqueL1Tx, nil } -func DeriveDeposits(epoch uint64, receipts []*types.Receipt) ([]hexutil.Bytes, error) { - userDeposits, err := UserDeposits(epoch, receipts) +func DeriveDeposits(l2BlockHeight uint64, receipts []*types.Receipt) ([]hexutil.Bytes, error) { + userDeposits, err := UserDeposits(l2BlockHeight, receipts) if err != nil { return nil, fmt.Errorf("failed to derive user deposits: %v", err) } diff --git a/opnode/rollup/derive/payload_attributes_test.go b/opnode/rollup/derive/payload_attributes_test.go index 75afbb503b43..7a9f8e2280c2 100644 --- a/opnode/rollup/derive/payload_attributes_test.go +++ b/opnode/rollup/derive/payload_attributes_test.go @@ -7,6 +7,9 @@ import ( "math/rand" "testing" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/assert" "github.com/ethereum/go-ethereum/common" @@ -196,3 +199,128 @@ func TestDeriveUserDeposits(t *testing.T) { }) } } + +type ValidBatchTestCase struct { + Name string + Epoch rollup.Epoch + MinL2Time uint64 + MaxL2Time uint64 + Batch BatchData + Valid bool +} + +func TestValidBatch(t *testing.T) { + testCases := []ValidBatchTestCase{ + { + Name: "valid epoch", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 123, + Timestamp: 43, + Transactions: []hexutil.Bytes{{0x01, 0x13, 0x37}, {0x02, 0x13, 0x37}}, + }}, + Valid: true, + }, + { + Name: "ignored epoch", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 122, + Timestamp: 43, + Transactions: nil, + }}, + Valid: false, + }, + { + Name: "too old", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 123, + Timestamp: 42, + Transactions: nil, + }}, + Valid: false, + }, + { + Name: "too new", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 123, + Timestamp: 52, + Transactions: nil, + }}, + Valid: false, + }, + { + Name: "wrong time alignment", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 123, + Timestamp: 46, + Transactions: nil, + }}, + Valid: false, + }, + { + Name: "good time alignment", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 123, + Timestamp: 51, // 31 + 2*10 + Transactions: nil, + }}, + Valid: true, + }, + { + Name: "empty tx", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 123, + Timestamp: 43, + Transactions: []hexutil.Bytes{{}}, + }}, + Valid: false, + }, + { + Name: "sneaky deposit", + Epoch: 123, + MinL2Time: 43, + MaxL2Time: 52, + Batch: BatchData{BatchV1: BatchV1{ + Epoch: 123, + Timestamp: 43, + Transactions: []hexutil.Bytes{{0x01}, {types.DepositTxType, 0x13, 0x37}, {0xc0, 0x13, 0x37}}, + }}, + Valid: false, + }, + } + conf := rollup.Config{ + Genesis: rollup.Genesis{ + L2Time: 31, // a genesis time that itself does not align to make it more interesting + }, + BlockTime: 2, + // other config fields are ignored and can be left empty. + } + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + got := ValidBatch(&testCase.Batch, &conf, testCase.Epoch, testCase.MinL2Time, testCase.MaxL2Time) + if got != testCase.Valid { + t.Fatalf("case %v was expected to return %v, but got %v", testCase, testCase.Valid, got) + } + }) + } +} diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index d515ed8efaeb..8d363c3470c7 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -25,8 +25,8 @@ type BatchSubmitter interface { type Downloader interface { // FetchL1Info fetches the L1 header information corresponding to a L1 block ID FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) - // FetchReceipts of a L1 block - FetchReceipts(ctx context.Context, id eth.BlockID) ([]*types.Receipt, error) + // FetchReceipts of a L1 block. The receipt-hash must be provided to sanity-check the retrieved receipts. + FetchReceipts(ctx context.Context, id eth.BlockID, receiptHash common.Hash) ([]*types.Receipt, error) // FetchTransactions from the given window of L1 blocks FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 1afca3e3f508..d6dbdf26ed50 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -43,11 +43,10 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa var receipts types.Receipts if includeDeposits { - receipts, err = d.dl.FetchReceipts(fetchCtx, l1Origin) + receipts, err = d.dl.FetchReceipts(fetchCtx, l1Origin, l1Info.ReceiptHash()) if err != nil { return l2Parent, nil, fmt.Errorf("failed to fetch receipts of %s: %v", l1Origin, err) } - } l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) if err != nil { @@ -55,7 +54,7 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa } var txns []l2.Data txns = append(txns, l1InfoTx) - deposits, err := derive.DeriveDeposits(l1Info.NumberU64(), receipts) + deposits, err := derive.DeriveDeposits(l2Parent.Number+1, receipts) d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Parent, "l1Origin", l1Origin) if err != nil { return l2Parent, nil, fmt.Errorf("failed to derive deposits: %v", err) @@ -124,11 +123,11 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e if err != nil { return l2Head, fmt.Errorf("failed to create l1InfoTx: %w", err) } - receipts, err := d.dl.FetchReceipts(fetchCtx, l1Input[0]) + receipts, err := d.dl.FetchReceipts(fetchCtx, l1Input[0], l1Info.ReceiptHash()) if err != nil { return l2Head, fmt.Errorf("failed to fetch receipts of %s: %w", l1Input[0], err) } - deposits, err := derive.DeriveDeposits(uint64(epoch), receipts) + deposits, err := derive.DeriveDeposits(l2Head.Number+1, receipts) if err != nil { return l2Head, fmt.Errorf("failed to derive deposits: %w", err) } diff --git a/specs/deposits.md b/specs/deposits.md index 98516c3aa6d9..9b921c4724e5 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -8,6 +8,7 @@ [g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction [g-user-deposited]: glossary.md#user-deposited-transaction [g-eoa]: glossary.md#eoa +[g-exec-engine]: glossary.md#execution-engine [Deposited transactions][g-deposited], also known as [deposits][g-deposits] are transactions which are initiated on L1, and executed on L2. This document outlines a new [transaction @@ -54,6 +55,8 @@ fields (rlp encoded in the order they appear here): [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 +- `uint64 blockHeight`: the block-height of the L2 block +- `uint64 transactionIndex`: the transaction-index within the L2 transactions list - `address from`: The address of the sender account. - `address to`: The address of the recipient account, or the null (zero-length) address if the deposited transaction is a contract creation. @@ -72,6 +75,12 @@ Picking a high identifier minimizes the risk that the identifier will be used be transaction type on the L1 chain in the future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. +The extra blockHeight and transactionIndex in deposits will be used to ensure that deposited transactions +will be unique. Without them, two different deposited transaction could have the same exact hash. + +We do not use the sender's nonce to ensure uniqueness because this would require an extra L2 EVM state read from the +[execution engine][g-exec-engine] during block-derivation. + ### Kinds of Deposited Transactions Although we define only one new transaction type, we can distinguish between two kinds of deposited diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 56631ba485b7..6fa8cfbbedb6 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -114,9 +114,8 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi - timestamp - basefee - *random* (the output of the [`RANDOM` opcode][random]) - - L1 log entries emitted for [user deposits][g-deposits], augmented with - - `blockHeight`: the block-height of the L1 block - - `transactionIndex`: the transaction-index within the L2 transactions list + - L1 log entries emitted for [user deposits][g-deposits], derived transactions are augmented with + `blockHeight` and `transactionIndex` of the transaction in L2. - Of each block in the window: - Sequencer batches, derived from the transactions: - The transaction receiver is the sequencer inbox address @@ -154,12 +153,6 @@ Batch contents: [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -> Design note: The extra log entry metadata will be used to ensure that deposited transactions will be unique. Without -> them, two different deposited transaction could have the same exact hash. -> -> We do not use the sender's nonce to ensure uniqueness because this would require an extra L2 EVM state read from the -> [execution engine][g-exec-engine]. - The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts][g-receipts]. Refer to the [**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log entries. From b0ba1ec97a13f803b249630a9f434443966398b2 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 3 Feb 2022 14:30:42 -0800 Subject: [PATCH 320/585] opnode: Add a makefile Primarily for easier building and linting. --- opnode/.gitignore | 1 + opnode/Makefile | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 opnode/.gitignore create mode 100644 opnode/Makefile diff --git a/opnode/.gitignore b/opnode/.gitignore new file mode 100644 index 000000000000..ba077a4031ad --- /dev/null +++ b/opnode/.gitignore @@ -0,0 +1 @@ +bin diff --git a/opnode/Makefile b/opnode/Makefile new file mode 100644 index 000000000000..84081e9bb816 --- /dev/null +++ b/opnode/Makefile @@ -0,0 +1,26 @@ +GITCOMMIT := $(shell git rev-parse HEAD) +GITDATE := $(shell git show -s --format='%ct') +VERSION := v0.0.0 + +LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) +LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) +LDFLAGSSTRING +=-X main.Version=$(VERSION) +LDFLAGS := -ldflags "$(LDFLAGSSTRING)" + +opnode: + env GO111MODULE=on go build -v $(LDFLAGS) -o ./bin/opnode ./cmd/main.go + +clean: + rm bin/opnode + +test: + go test -v ./... + +lint: + golangci-lint run ./... + +.PHONY: \ + bss \ + clean \ + test \ + lint From ab791ad0d0fb7a1b79736437d144b9749decc0bb Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 10:39:06 -0700 Subject: [PATCH 321/585] opnode: Fix misspells --- opnode/rollup/derive/doc.go | 2 +- opnode/rollup/sync/start_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opnode/rollup/derive/doc.go b/opnode/rollup/derive/doc.go index e0b46265c0cd..e8bdb6999700 100644 --- a/opnode/rollup/derive/doc.go +++ b/opnode/rollup/derive/doc.go @@ -1,5 +1,5 @@ // Package derive provides the data transformation functions that take L1 data -// and turn it into L2 blocks and results. Certian L2 data is also able to +// and turn it into L2 blocks and results. Certain L2 data is also able to // turned back into L1 data. // // The flow is data is as follows diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index c6b71ce88588..c3364ce83354 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -125,7 +125,7 @@ type syncStartTestCase struct { GenesisL2 rune ExpectedNextRefsL1 string // The L1 extension to follow (i.e. L1 after the L1 parent in the new L2 Head) - ExpectedRefL2 rune // The new L2 tip after a L1 change that may have occured + ExpectedRefL2 rune // The new L2 tip after a L1 change that may have occurred ExpectedErr error } From 8784d597a34bf566193c84d8b99bc82612a353d0 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 11:05:26 -0700 Subject: [PATCH 322/585] l2os: Fix misspells --- l2os/l2_output_submitter.go | 4 ++-- l2os/txmgr/send_state.go | 4 ++-- l2os/txmgr/send_state_test.go | 4 ++-- l2os/txmgr/txmgr.go | 2 +- l2os/txmgr/txmgr_test.go | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/l2os/l2_output_submitter.go b/l2os/l2_output_submitter.go index cff23be61965..191020d36a44 100644 --- a/l2os/l2_output_submitter.go +++ b/l2os/l2_output_submitter.go @@ -175,8 +175,8 @@ func dialEthClientWithTimeout(ctx context.Context, url string) ( return ethclient.DialContext(ctxt, url) } -// parseAddress parses an ETH addres from a hex string. This method will fail if -// the address is not a valid hexidecimal address. +// parseAddress parses an ETH address from a hex string. This method will fail if +// the address is not a valid hexadecimal address. func parseAddress(address string) (common.Address, error) { if common.IsHexAddress(address) { return common.HexToAddress(address), nil diff --git a/l2os/txmgr/send_state.go b/l2os/txmgr/send_state.go index c223f743edfc..2f34cbb330dd 100644 --- a/l2os/txmgr/send_state.go +++ b/l2os/txmgr/send_state.go @@ -11,7 +11,7 @@ import ( // SendState tracks information about the publication state of a given txn. In // this context, a txn may correspond to multiple different txn hashes due to // varying gas prices, though we treat them all as the same logical txn. This -// struct is primarly used to determine whether or not the txmgr should abort a +// struct is primarily used to determine whether or not the txmgr should abort a // given txn and retry with a higher nonce. type SendState struct { minedTxs map[common.Hash]struct{} @@ -77,7 +77,7 @@ func (s *SendState) TxNotMined(txHash common.Hash) { // If the txn got reorged and left us with no mined txns, reset the nonce // too low count, otherwise we might abort too soon when processing the next // error. If the nonce too low errors persist, we want to ensure we wait out - // the full safe abort count to enesure we have a sufficient number of + // the full safe abort count to ensure we have a sufficient number of // observations. if len(s.minedTxs) == 0 && wasMined { s.nonceTooLowCount = 0 diff --git a/l2os/txmgr/send_state_test.go b/l2os/txmgr/send_state_test.go index 8dd610793646..42d16342c5cd 100644 --- a/l2os/txmgr/send_state_test.go +++ b/l2os/txmgr/send_state_test.go @@ -80,8 +80,8 @@ func TestSendStateMiningTxCancelsAbort(t *testing.T) { } // TestSendStateReorgingTxResetsAbort asserts that unmining a tx does not -// consider ErrNonceTooLow's prior to being mined when determing whether to -// abort. +// consider ErrNonceTooLow's prior to being mined when determining whether +// to abort. func TestSendStateReorgingTxResetsAbort(t *testing.T) { sendState := newSendState() diff --git a/l2os/txmgr/txmgr.go b/l2os/txmgr/txmgr.go index ca206da1926a..90379c3a6217 100644 --- a/l2os/txmgr/txmgr.go +++ b/l2os/txmgr/txmgr.go @@ -209,7 +209,7 @@ func (m *SimpleTxManager) Send( // Avoid republishing if we are waiting for confirmation on an // existing tx. This is primarily an optimization to reduce the // number of API calls we make, but also reduces the chances of - // getting a false postive reading for ShouldAbortImmediately. + // getting a false positive reading for ShouldAbortImmediately. if sendState.IsWaitingForConfirmation() { continue } diff --git a/l2os/txmgr/txmgr_test.go b/l2os/txmgr/txmgr_test.go index 3fb0c4928bc6..81cf9cab01a7 100644 --- a/l2os/txmgr/txmgr_test.go +++ b/l2os/txmgr/txmgr_test.go @@ -37,7 +37,7 @@ func newTestHarnessWithConfig(cfg txmgr.Config) *testHarness { } } -// newTestHarness initializes a testHarness with a defualt configuration that is +// newTestHarness initializes a testHarness with a default configuration that is // suitable for most tests. func newTestHarness() *testHarness { return newTestHarnessWithConfig(configWithNumConfs(1)) From 25cfdadf325bddefda73ddfb8a2b4230e7fa3306 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 10:39:40 -0700 Subject: [PATCH 323/585] opnode: Rename `strat` to `strategy` The misspell linter was trying to correct `strat` to `start`. This is typically correct, but not in this instance. --- opnode/backoff/operation.go | 4 ++-- opnode/backoff/operation_test.go | 6 +++--- opnode/backoff/strategies_test.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/opnode/backoff/operation.go b/opnode/backoff/operation.go index 4bd7f4539f1d..548188754f57 100644 --- a/opnode/backoff/operation.go +++ b/opnode/backoff/operation.go @@ -23,7 +23,7 @@ func (e *ErrFailedPermanently) Error() string { // Do performs the provided Operation up to maxAttempts times // with delays in between each retry according to the provided // Strategy. -func Do(maxAttempts int, strat Strategy, op Operation) error { +func Do(maxAttempts int, strategy Strategy, op Operation) error { var attempt int for { @@ -39,6 +39,6 @@ func Do(maxAttempts int, strat Strategy, op Operation) error { LastErr: err, } } - time.Sleep(strat.Duration(attempt - 1)) + time.Sleep(strategy.Duration(attempt - 1)) } } diff --git a/opnode/backoff/operation_test.go b/opnode/backoff/operation_test.go index a7e2d174e7c3..063e9685ee34 100644 --- a/opnode/backoff/operation_test.go +++ b/opnode/backoff/operation_test.go @@ -9,12 +9,12 @@ import ( ) func TestDo(t *testing.T) { - strat := Fixed(10 * time.Millisecond) + strategy := Fixed(10 * time.Millisecond) dummyErr := errors.New("explode") start := time.Now() var i int - require.NoError(t, Do(2, strat, func() error { + require.NoError(t, Do(2, strategy, func() error { if i == 1 { return nil } @@ -26,7 +26,7 @@ func TestDo(t *testing.T) { start = time.Now() // add one because the first attempt counts - err := Do(3, strat, func() error { + err := Do(3, strategy, func() error { return dummyErr }) require.Equal(t, dummyErr, err.(*ErrFailedPermanently).LastErr) diff --git a/opnode/backoff/strategies_test.go b/opnode/backoff/strategies_test.go index 852ee2b67ab6..2988a32333ae 100644 --- a/opnode/backoff/strategies_test.go +++ b/opnode/backoff/strategies_test.go @@ -8,7 +8,7 @@ import ( ) func TestExponential(t *testing.T) { - strat := &ExponentialStrategy{ + strategy := &ExponentialStrategy{ Min: 3000, Max: 10000, MaxJitter: 0, @@ -16,6 +16,6 @@ func TestExponential(t *testing.T) { durations := []int{4, 5, 7, 10, 10} for i, dur := range durations { - require.Equal(t, time.Millisecond*time.Duration(dur*1000), strat.Duration(i)) + require.Equal(t, time.Millisecond*time.Duration(dur*1000), strategy.Duration(i)) } } From eceaa5399e5edc3654ad7148cc73a118259d4ca4 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 10:41:21 -0700 Subject: [PATCH 324/585] opnode: Pull in version info from ld flags --- opnode/cmd/main.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 2d571d11dc40..d7af2124fc35 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -15,15 +15,21 @@ import ( ) var ( - Version = "0.0.0" - // GitCommit = "" - // GitDate = "" + Version = "0.0.0" + GitCommit = "" + GitDate = "" VersionMeta = "dev" ) // VersionWithMeta holds the textual version string including the metadata. var VersionWithMeta = func() string { v := Version + if GitCommit != "" { + v += "-" + GitCommit[:8] + } + if GitDate != "" { + v += "-" + GitDate + } if VersionMeta != "" { v += "-" + VersionMeta } From f9bedc730d7db12df3841e725111fce936191e92 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 10:41:47 -0700 Subject: [PATCH 325/585] opnode: Specify lints and add misspell --- .github/workflows/go-ci.yml | 2 +- l2os/Makefile | 2 +- meta/linting.md | 2 +- opnode/Makefile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 3e6bf62223d3..f6624c179e64 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -24,7 +24,7 @@ jobs: version: v1.43.0 # version of golangci-lint, not the action skip-go-installation: true # rules: https://golangci-lint.run/usage/quick-start/ - args: -E asciicheck,goimports + args: -E asciicheck,goimports,misspell - name: Test and generate coverage run: go test -coverpkg=./... -coverprofile=coverage.out -covermode=atomic ./... - name: Upload coverage output diff --git a/l2os/Makefile b/l2os/Makefile index 1fab682f8e7d..5642d8c1eb28 100644 --- a/l2os/Makefile +++ b/l2os/Makefile @@ -19,7 +19,7 @@ test: go test -v ./... lint: - golangci-lint run ./... + golangci-lint run -E asciicheck,goimports,misspell ./... bindings: bindings-mock-l2-output-oracle diff --git a/meta/linting.md b/meta/linting.md index 45e7779829b9..cc7ee6179a0e 100644 --- a/meta/linting.md +++ b/meta/linting.md @@ -61,5 +61,5 @@ Justification for linting rules: # Install linter globally (should not affect go.mod) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.43.0 # run linter, add --fix option to fix problems (where supported) -golangci-lint run -E asciicheck,goimports +golangci-lint run -E asciicheck,goimports,misspell ``` diff --git a/opnode/Makefile b/opnode/Makefile index 84081e9bb816..d2c8a6c09c55 100644 --- a/opnode/Makefile +++ b/opnode/Makefile @@ -17,7 +17,7 @@ test: go test -v ./... lint: - golangci-lint run ./... + golangci-lint run -E asciicheck,goimports,misspell ./... .PHONY: \ bss \ From c9c1e0ae468c4a64cb186bb139932f7105e2c1d4 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 10:42:06 -0700 Subject: [PATCH 326/585] opnode: Quiet logging during testing This enables the nice test ouput with `go test -v` that lists each test without polluting the output with logs from passing tests. --- opnode/rollup/driver/state_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 112df03939c6..b3848e476fab 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -128,7 +128,7 @@ type stateTestCase struct { } func (tc *stateTestCase) Run(t *testing.T) { - log := testlog.Logger(t, log.LvlTrace) + log := testlog.Logger(t, log.LvlError) chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) l1headsCh := make(chan eth.L1BlockRef, 10) // Unbuffered channels to force a sync point between the test and the state loop. From 785b5ce30cc4bdf80fa0d5640430bf914bc0ae5b Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 11:13:16 -0700 Subject: [PATCH 327/585] Bump golangci-lint version Required for go version 1.18 --- .github/workflows/go-ci.yml | 2 +- meta/linting.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index f6624c179e64..22da71855654 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -21,7 +21,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v2 with: - version: v1.43.0 # version of golangci-lint, not the action + version: v1.45.0 # version of golangci-lint, not the action skip-go-installation: true # rules: https://golangci-lint.run/usage/quick-start/ args: -E asciicheck,goimports,misspell diff --git a/meta/linting.md b/meta/linting.md index cc7ee6179a0e..c356d1c85504 100644 --- a/meta/linting.md +++ b/meta/linting.md @@ -59,7 +59,7 @@ Justification for linting rules: ```shell # Install linter globally (should not affect go.mod) -go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.43.0 +go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.0 # run linter, add --fix option to fix problems (where supported) golangci-lint run -E asciicheck,goimports,misspell ``` From 8ac860e64d58841f0311d3381bed981c0d559034 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 22 Mar 2022 11:13:48 -0700 Subject: [PATCH 328/585] Require go 1.18 --- .github/workflows/go-ci.yml | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 22da71855654..bc4e702c6965 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -15,7 +15,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.18 - name: Checkout code uses: actions/checkout@v2 - name: golangci-lint diff --git a/go.mod b/go.mod index 80da39b09564..7f9c98b5b746 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum-optimism/optimistic-specs -go 1.17 +go 1.18 require ( github.com/ethereum/go-ethereum v1.10.16 From 90df4ec4fc1bfa7597800da495917bceea992743 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 23 Mar 2022 15:21:51 -0700 Subject: [PATCH 329/585] opnode: Speed up bss Rely on intrinisic gas (which can be computed exactly) rather than using gas estimation. Adds commented out code to manage the nonce manually. I think that there was a race between gas estimation and nonce handling which previously caused problems. If problems continue, it makes sense to switch over to more manual nonce management. --- opnode/bss/submitter.go | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/opnode/bss/submitter.go b/opnode/bss/submitter.go index 51a13ccdd9f7..4bb39fc67afd 100644 --- a/opnode/bss/submitter.go +++ b/opnode/bss/submitter.go @@ -9,10 +9,10 @@ import ( "time" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" @@ -25,10 +25,6 @@ type BatchSubmitter struct { PrivKey *ecdsa.PrivateKey } -// func NewSubmitter(client ethclient.Client, addr common.Address) *BatchSubmitter { -// return &BatchSubmitter{client: client, addr: addr} -// } - // Submit creates & submits batches to L1. Blocks until the transaction is included. // Return the tx hash as well as a possible error. func (b *BatchSubmitter) Submit(config *rollup.Config, batches []*derive.BatchData) (common.Hash, error) { @@ -40,17 +36,18 @@ func (b *BatchSubmitter) Submit(config *rollup.Config, batches []*derive.BatchDa return common.Hash{}, err } - addr := crypto.PubkeyToAddress(b.PrivKey.PublicKey) - nonce, err := b.Client.PendingNonceAt(ctx, addr) + tip, err := b.Client.SuggestGasTipCap(ctx) if err != nil { return common.Hash{}, err } - - tip, err := b.Client.SuggestGasTipCap(ctx) + fee, err := b.Client.SuggestGasPrice(ctx) if err != nil { return common.Hash{}, err } - fee, err := b.Client.SuggestGasPrice(ctx) + + // Note: If the BSS acts up, look into the pending nonce. + addr := crypto.PubkeyToAddress(b.PrivKey.PublicKey) + nonce, err := b.Client.PendingNonceAt(ctx, addr) if err != nil { return common.Hash{}, err } @@ -63,14 +60,10 @@ func (b *BatchSubmitter) Submit(config *rollup.Config, batches []*derive.BatchDa GasFeeCap: fee, Data: buf.Bytes(), } - msg := ethereum.CallMsg{ - From: addr, - To: rawTx.To, - GasTipCap: rawTx.GasTipCap, - GasFeeCap: rawTx.GasFeeCap, - Data: rawTx.Data, - } - gas, err := b.Client.EstimateGas(ctx, msg) + + // No contract execution so we just pay intrinsic gas. + // If we add contract execution, making it gas usage deterministic is very helpful. + gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true) if err != nil { return common.Hash{}, err } From 19fcb3036e33835bbdad2d80b3d71ef9f1942b96 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 18:55:40 -0400 Subject: [PATCH 330/585] Parallelize solidity CI checks Splits the workflow into 3 different steps which can run in parallel. --- .github/workflows/solidity-ci.yml | 41 +++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/.github/workflows/solidity-ci.yml b/.github/workflows/solidity-ci.yml index 61905b82702c..3bf6e1b61c11 100644 --- a/.github/workflows/solidity-ci.yml +++ b/.github/workflows/solidity-ci.yml @@ -17,9 +17,9 @@ defaults: working-directory: ./packages/contracts jobs: - solidity-ci: + yarn-test: runs-on: ubuntu-latest - name: Solidity Checks + name: Yarn Test steps: - uses: actions/checkout@v2 with: @@ -31,6 +31,22 @@ jobs: cache: 'yarn' - run: yarn install + - name: Build with HH + run: yarn build:hh + + - name: Test + run: yarn test:hh + + - name: Lint + run: yarn lint:check + + forge-test: + runs-on: ubuntu-latest + name: Forge Test + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive - name: Install Foundry uses: onbjerg/foundry-toolchain@v1 @@ -40,14 +56,22 @@ jobs: - name: Build with Forge run: yarn build:forge - - name: Build with HH - run: yarn build:hh + - name: Test with Forge + run: yarn test:forge - - name: Test - run: yarn test + slither: + runs-on: ubuntu-latest + name: Slither + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive - - name: Lint - run: yarn lint:check + - uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'yarn' + - run: yarn install - name: Set up Python 3.8 uses: actions/setup-python@v2 @@ -59,3 +83,4 @@ jobs: - name: Run Slither run: yarn slither + continue-on-error: true From 615d88cce938ba1d520e53c390022e24d0959a15 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 10 Mar 2022 12:34:10 -0500 Subject: [PATCH 331/585] specs: Add L2 output submitter service polishing --- .../contracts/L1/MockL2OutputOracle.sol | 1 + specs/README.md | 3 +- specs/glossary.md | 9 ++ specs/proposals.md | 98 +++++++++++++++++-- specs/rollup-node.md | 26 ++++- 5 files changed, 125 insertions(+), 12 deletions(-) diff --git a/packages/contracts/contracts/L1/MockL2OutputOracle.sol b/packages/contracts/contracts/L1/MockL2OutputOracle.sol index 171e3ffa26c5..65d65b24d756 100644 --- a/packages/contracts/contracts/L1/MockL2OutputOracle.sol +++ b/packages/contracts/contracts/L1/MockL2OutputOracle.sol @@ -46,6 +46,7 @@ contract MockL2OutputOracle { require(block.timestamp > _timestamp, "Cannot append L2 output in future"); require(_l2Output != bytes32(0), "Cannot submit empty L2 output"); require(_timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp"); + // todo: add require statement to ensure a specific prev-hash exists on the current chain l2Outputs[_timestamp] = _l2Output; latestBlockTimestamp = _timestamp; } diff --git a/specs/README.md b/specs/README.md index 1d38e5d7cffe..30c3b36572ad 100644 --- a/specs/README.md +++ b/specs/README.md @@ -8,8 +8,9 @@ that maintains 1:1 compatibility with Ethereum. - [Glossary](glossary.md) - [Deposits](deposits.md) +- [Withdrawals](withdrawals.md) - [Execution Engine](exec-engine.md) -- [L2 output root Proposals](proposals.md) +- [L2 Output Root Proposals](proposals.md) - [Rollup Node](rollup-node.md) ## Design Goals diff --git a/specs/glossary.md b/specs/glossary.md index d9f054f01f89..243620705af2 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -37,6 +37,7 @@ - [L2 Derivation Inputs](#l2-derivation-inputs) - [Payload Attributes](#payload-attributes) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) + - [L2 output](#l2-output) - [Execution Engine Concepts](#execution-engine-concepts) - [Execution Engine](#execution-engine) @@ -367,6 +368,14 @@ block number or a given block hash. cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes-predeployed-contract) +## L2 output + +[l2-output]: glossary.md#l2-output + +A 32 byte value representing the current state of the L2 chain. + +cf. [Proposing L2 output commitments](proposals.md#l2-output-root-proposals-specification) + ------------------------------------------------------------------------------------------------------------------------ # Execution Engine Concepts diff --git a/specs/proposals.md b/specs/proposals.md index d3a4866fedd1..35a15bc9516f 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -1,4 +1,4 @@ -# L2 output root Proposals Specification +# L2 Output Root Proposals Specification [g-rollup-node]: glossary.md#rollup-node @@ -7,8 +7,12 @@ **Table of Contents** -- [Proposing L2 output commitments](#proposing-l2-output-commitments) -- [L2 output commitment construction](#l2-output-commitment-construction) +- [Constants](#constants) +- [Proposing L2 Output Commitments](#proposing-l2-output-commitments) +- [L2 Output Commitment Construction](#l2-output-commitment-construction) +- [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract) +- [Security Considerations](#security-considerations) + - [L1 Reorgs](#l1-reorgs) @@ -24,15 +28,39 @@ are part of later specification milestones. [cannon]: https://github.com/ethereum-optimism/cannon -## Proposing L2 output commitments +## Definitions -The proposer's role is to construct and submit output commitments on a configurable interval to a contract on L1. +### Constants -TODO: describe integration with rollup node and L2 execution engine (see PR #179). +| Name | Value | Unit | +| ---------------------- | ----- | ------- | +| `SUBMISSION_FREQUENCY` | `100` | seconds | +| `L2_BLOCK_TIME` | `2` | seconds | -TODO: link to contract specification/source of L2 Output oracle on L1. +### Types -## L2 output commitment construction +The `ForkSpec` type contains the height and blockhash for a block in the L1 chain. + +```js +struct ForkSpec { + uint256 blockHeight; + bytes32 blockHash; +} +``` + +## Proposing L2 Output Commitments + +The proposer's role is to construct and submit output commitments on a configurable interval to a contract on , which +it does by running the [L2 output submitter](../l2os/) service (AKA L2OSS). This service periodically queries the rollup + node's [`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived + from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is + described [below](#l2-output-commitment-construction). + +If there is no newly finalized output, the service continues querying until it receives one. It then submits this +output, and the appropriate timestamp, to the [L2 Output Commitment](#l2-output-commitment-smart-contract) contract's +`appendL2Output()` function. The timestamp MUST be the next multiple of the `SUBMISSION_FREQUENCY` value. + +## L2 Output Commitment Construction This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. @@ -42,7 +70,7 @@ L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas cos ```python class L2Output(Container): state_root: Bytes32 - withdrawal_storage_root: Bytes32 # TODO: withdrawals specifcation work-in-progress + withdrawal_storage_root: Bytes32 # TODO: withdrawals specification work-in-progress latest_block: ExecutionPayload # includes block hash history_accumulator_root: Bytes32 # Not functional yet extension: Bytes32 @@ -71,3 +99,55 @@ This is a work-in-progress, see [issue 181](https://github.com/ethereum-optimism The `extension` is a zeroed `Bytes32`, to be substituted with a SSZ container to extend merkleized information in future upgrades. This keeps the static merkle structure forwards-compatible. + +## L2 Output Oracle Smart Contract + +L2 blocks are produced at a constant rate of `L2_BLOCK_TIME` (2 seconds). +A new L2 output MUST be appended to the chain once per `SUBMISSION_FREQUENCY` (100 seconds). Note that interval is based on L2 time. It is OK to have L2 outputs +submitted at larger or small intervals + +The L2 Output Oracle contract implements the following interface: + +```js +/** + * Data necessary to ensure that the output is being written to the expected fork of the L1 chain. + * This protects against an erroneous commitment in the event of an L1 reorg. + */ +struct ForkSpec { + uint256 blockHeight; + bytes32 blockHash; +} + +/** + * Accepts an L2 output checkpoint and the timestamp of the corresponding L2 + * block. The timestamp must be equal to the current value returned by + * `nextTimestamp()` in order to be accepted. + * @param _l2Output The L2 output of the checkpoint block. + * @param _timestamp The L2 block timestamp that resulted in _l2Output. + * @param _forkSpecifier A commitment to a specific fork. + */ +function appendL2Output(bytes32 _l2Output, uint256 _timestamp, ForkSpec _forkSpecifier) external + + +/** + * Computes the timestamp of the next L2 block that needs to be + * checkpointed. + */ +function nextTimestamp() public view returns (uint256) { + return latestBlockTimestamp + submissionFrequency; +} + +/** + * Computes the L2 block number given a target L2 block timestamp. + * @param _timestamp The L2 block timestamp of the target block. + */ +function computeL2BlockNumber(uint256 _timestamp) public view returns (uint256) +``` + +## Security Considerations + +### L1 Reorgs + +If the L1 has a reorg after an output has been generated and submitted, the L2 state and correct output may change +leading to a faulty proposal. This is mitigated against in the OutputOracle by checking that the block at +`_forkSpecifier.blockHeight` has the expected hash `_forkSpecifier.blockHash`. diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 6fa8cfbbedb6..58db92591a18 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -56,6 +56,8 @@ currently only concerned with the specification of the rollup driver. - [Engine API Error Handling](#engine-api-error-handling) - [Finalization Guarantees](#finalization-guarantees) - [Whole L2 Chain Derivation](#whole-l2-chain-derivation) + - [L2 Output RPC method](#l2-output-rpc-method) + - [Output Method API](#output-method-api) - [Handling L1 Re-Orgs](#handling-l1-re-orgs) @@ -319,11 +321,12 @@ As stated earlier, an L2 block is considered *finalized* after a delay of `FINAL after the L1 block that generated it. This is a duration of approximately 7 days worth of L1 blocks. This is also known as the "fault proof window", as after this time the block can no longer be challenged by a fault proof. -L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality]. L2 blocks generated from finalized L1 blocks +L1 Ethereum reaches [finality][l1-finality] approximately every [12.8 minutes][consensus-time-params]. L2 blocks generated from finalized L1 blocks are "safer" than most recent L2 blocks because they will never disappear from the chain's history because of a re-org. However, they can still be challenged by a fault proof until the end of the fault proof window. -[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge/ +[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge +[consensus-time-params]: https://github.com/ethereum/consensus-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#time-parameters > **TODO** the spec doesn't encode the notion of fault proof yet, revisit this (and include links) when it does @@ -340,6 +343,25 @@ block forward each step, until there is an insufficient number of L1 blocks left > **TODO** specify genesis block +## L2 Output RPC method + +The Rollup node has its own RPC method, `optimism_output` which returns the +a 32 byte hash corresponding to the [SSZ] encoded [L2Output](./proposals.md#l2-output-commitment-construction). + +[SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md + +### Output Method API + +The input and return types here are as defined by the [engine API specs][engine-structures]). + +[engine-structures]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#structures + +- method: `optimism_outputAtBlock` +- params: + 1. `QUANTITY` - L1 integer block number, or the strings `"safe"`, `"latest"`, or `"pending"` +- returns: + 2.`DATA` - The 32 byte output root + # Handling L1 Re-Orgs [l1-reorgs]: #handling-L1-re-orgs From 3c98e79d7fa7c9e0ada111aa7d4c5c9da9b22bee Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 14 Mar 2022 16:02:28 -0400 Subject: [PATCH 332/585] Change optimism_outputAtBlock param to L2 blocknum --- specs/rollup-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 58db92591a18..ccb8de5354bb 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -358,7 +358,7 @@ The input and return types here are as defined by the [engine API specs][engine- - method: `optimism_outputAtBlock` - params: - 1. `QUANTITY` - L1 integer block number, or the strings `"safe"`, `"latest"`, or `"pending"` + 1. `QUANTITY` - L2 integer block number, or the strings `"safe"`, `"latest"`, or `"pending"` - returns: 2.`DATA` - The 32 byte output root From d34822315f9739752b23dc01128c82e7a5041e18 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 17 Mar 2022 11:54:50 -0400 Subject: [PATCH 333/585] Replace submissionFrequency with submissionInterval --- packages/contracts/contracts/L1/MockL2OutputOracle.sol | 10 +++++----- specs/proposals.md | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/contracts/contracts/L1/MockL2OutputOracle.sol b/packages/contracts/contracts/L1/MockL2OutputOracle.sol index 65d65b24d756..2510db44435d 100644 --- a/packages/contracts/contracts/L1/MockL2OutputOracle.sol +++ b/packages/contracts/contracts/L1/MockL2OutputOracle.sol @@ -5,7 +5,7 @@ pragma solidity >=0.8.10; * @title MockL2OutputOracle */ contract MockL2OutputOracle { - uint256 public submissionFrequency; + uint256 public submissionInterval; uint256 public l2BlockTime; mapping(uint256 => bytes32) public l2Outputs; uint256 public historicalTotalBlocks; @@ -14,7 +14,7 @@ contract MockL2OutputOracle { /** * Initialize the MockL2OutputOracle contract. - * @param _submissionFrequency The desired interval in seconds at which + * @param _submissionInterval The desired interval in seconds at which * checkpoints must be submitted. * @param _l2BlockTime The desired L2 inter-block time in seconds. * @param _genesisL2Output The initial L2 output of the L2 chain. @@ -22,12 +22,12 @@ contract MockL2OutputOracle { * initialization of the L2 chain. */ constructor( - uint256 _submissionFrequency, + uint256 _submissionInterval, uint256 _l2BlockTime, bytes32 _genesisL2Output, uint256 _historicalTotalBlocks ) { - submissionFrequency = _submissionFrequency; + submissionInterval = _submissionInterval; l2BlockTime = _l2BlockTime; l2Outputs[block.timestamp] = _genesisL2Output; // solhint-disable not-rely-on-time historicalTotalBlocks = _historicalTotalBlocks; @@ -56,7 +56,7 @@ contract MockL2OutputOracle { * checkpointed. */ function nextTimestamp() public view returns (uint256) { - return latestBlockTimestamp + submissionFrequency; + return latestBlockTimestamp + submissionInterval; } /** diff --git a/specs/proposals.md b/specs/proposals.md index 35a15bc9516f..61673afc8c31 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -58,7 +58,7 @@ it does by running the [L2 output submitter](../l2os/) service (AKA L2OSS). This If there is no newly finalized output, the service continues querying until it receives one. It then submits this output, and the appropriate timestamp, to the [L2 Output Commitment](#l2-output-commitment-smart-contract) contract's -`appendL2Output()` function. The timestamp MUST be the next multiple of the `SUBMISSION_FREQUENCY` value. +`appendL2Output()` function. The timestamp MUST be the next multiple of the `SUBMISSION_INTERVAL` value. ## L2 Output Commitment Construction @@ -103,7 +103,7 @@ upgrades. This keeps the static merkle structure forwards-compatible. ## L2 Output Oracle Smart Contract L2 blocks are produced at a constant rate of `L2_BLOCK_TIME` (2 seconds). -A new L2 output MUST be appended to the chain once per `SUBMISSION_FREQUENCY` (100 seconds). Note that interval is based on L2 time. It is OK to have L2 outputs +A new L2 output MUST be appended to the chain once per `SUBMISSION_INTERVAL` (100 seconds). Note that interval is based on L2 time. It is OK to have L2 outputs submitted at larger or small intervals The L2 Output Oracle contract implements the following interface: @@ -134,7 +134,7 @@ function appendL2Output(bytes32 _l2Output, uint256 _timestamp, ForkSpec _forkSpe * checkpointed. */ function nextTimestamp() public view returns (uint256) { - return latestBlockTimestamp + submissionFrequency; + return latestBlockTimestamp + submissionInterval; } /** From 5ba6d9c4d7eb2ac50fdc89a38f75bbc8a74578c1 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 12:17:37 -0400 Subject: [PATCH 334/585] Address PR comments on output submission spec --- specs/glossary.md | 4 ++-- specs/proposals.md | 17 +++++++++-------- specs/rollup-node.md | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index 243620705af2..ca1c7221c22b 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -37,7 +37,7 @@ - [L2 Derivation Inputs](#l2-derivation-inputs) - [Payload Attributes](#payload-attributes) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - - [L2 output](#l2-output) + - [L2 Output Root](#l2-output-root) - [Execution Engine Concepts](#execution-engine-concepts) - [Execution Engine](#execution-engine) @@ -368,7 +368,7 @@ block number or a given block hash. cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes-predeployed-contract) -## L2 output +## L2 Output Root [l2-output]: glossary.md#l2-output diff --git a/specs/proposals.md b/specs/proposals.md index 61673afc8c31..d05511ed46f0 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -7,7 +7,9 @@ **Table of Contents** -- [Constants](#constants) +- [Definitions](#definitions) + - [Constants](#constants) + - [Types](#types) - [Proposing L2 Output Commitments](#proposing-l2-output-commitments) - [L2 Output Commitment Construction](#l2-output-commitment-construction) - [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract) @@ -34,7 +36,7 @@ are part of later specification milestones. | Name | Value | Unit | | ---------------------- | ----- | ------- | -| `SUBMISSION_FREQUENCY` | `100` | seconds | +| `SUBMISSION_INTERVAL` | `1800` | seconds | | `L2_BLOCK_TIME` | `2` | seconds | ### Types @@ -50,8 +52,8 @@ struct ForkSpec { ## Proposing L2 Output Commitments -The proposer's role is to construct and submit output commitments on a configurable interval to a contract on , which -it does by running the [L2 output submitter](../l2os/) service (AKA L2OSS). This service periodically queries the rollup +The proposer's role is to construct and submit output commitments on a configurable interval to a contract on , which +it does by running the [L2 output submitter](../l2os/) (AKA L2OS). This service periodically queries the rollup node's [`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is described [below](#l2-output-commitment-construction). @@ -103,8 +105,8 @@ upgrades. This keeps the static merkle structure forwards-compatible. ## L2 Output Oracle Smart Contract L2 blocks are produced at a constant rate of `L2_BLOCK_TIME` (2 seconds). -A new L2 output MUST be appended to the chain once per `SUBMISSION_INTERVAL` (100 seconds). Note that interval is based on L2 time. It is OK to have L2 outputs -submitted at larger or small intervals +A new L2 output MUST be appended to the chain once per `SUBMISSION_INTERVAL` (1800 seconds). Note that this interval is based +on L2 time. It is OK to have L2 outputs submitted at larger or small intervals. The L2 Output Oracle contract implements the following interface: @@ -130,8 +132,7 @@ function appendL2Output(bytes32 _l2Output, uint256 _timestamp, ForkSpec _forkSpe /** - * Computes the timestamp of the next L2 block that needs to be - * checkpointed. + * Computes the timestamp of the next L2 block that needs to be checkpointed. */ function nextTimestamp() public view returns (uint256) { return latestBlockTimestamp + submissionInterval; diff --git a/specs/rollup-node.md b/specs/rollup-node.md index ccb8de5354bb..a69443798f28 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -345,7 +345,7 @@ block forward each step, until there is an insufficient number of L1 blocks left ## L2 Output RPC method -The Rollup node has its own RPC method, `optimism_output` which returns the +The Rollup node has its own RPC method, `optimism_outputAtBlock` which returns the a 32 byte hash corresponding to the [SSZ] encoded [L2Output](./proposals.md#l2-output-commitment-construction). [SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md @@ -360,7 +360,7 @@ The input and return types here are as defined by the [engine API specs][engine- - params: 1. `QUANTITY` - L2 integer block number, or the strings `"safe"`, `"latest"`, or `"pending"` - returns: - 2.`DATA` - The 32 byte output root + 1. `DATA` - The 32 byte output root # Handling L1 Re-Orgs From 931c5429f34be95d2ba37ec790cbea8c1062b8a7 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 13:51:31 -0400 Subject: [PATCH 335/585] Run CI on feat/* branches --- .github/workflows/go-ci.yml | 1 + .github/workflows/markdown-ci.yml | 1 + .github/workflows/solidity-ci.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index bc4e702c6965..c3510c21227c 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -5,6 +5,7 @@ on: branches: - 'main' - 'staging' + - 'feat/*' pull_request: workflow_dispatch: diff --git a/.github/workflows/markdown-ci.yml b/.github/workflows/markdown-ci.yml index 1ca984e0debf..7d8645210ce8 100644 --- a/.github/workflows/markdown-ci.yml +++ b/.github/workflows/markdown-ci.yml @@ -5,6 +5,7 @@ on: branches: - 'main' - 'staging' + - 'feat/*' pull_request: workflow_dispatch: diff --git a/.github/workflows/solidity-ci.yml b/.github/workflows/solidity-ci.yml index 3bf6e1b61c11..a8fa89ecbac6 100644 --- a/.github/workflows/solidity-ci.yml +++ b/.github/workflows/solidity-ci.yml @@ -5,6 +5,7 @@ on: branches: - 'main' - 'staging' + - 'feat/*' pull_request: workflow_dispatch: From 67764b5ac75b09b021c5f2b01d895bf48498a280 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 14:21:36 -0400 Subject: [PATCH 336/585] Fix linting --- specs/proposals.md | 4 ++-- specs/rollup-node.md | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/specs/proposals.md b/specs/proposals.md index d05511ed46f0..c691b941d9f1 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -105,8 +105,8 @@ upgrades. This keeps the static merkle structure forwards-compatible. ## L2 Output Oracle Smart Contract L2 blocks are produced at a constant rate of `L2_BLOCK_TIME` (2 seconds). -A new L2 output MUST be appended to the chain once per `SUBMISSION_INTERVAL` (1800 seconds). Note that this interval is based -on L2 time. It is OK to have L2 outputs submitted at larger or small intervals. +A new L2 output MUST be appended to the chain once per `SUBMISSION_INTERVAL` (1800 seconds). Note that this interval is\ +based on L2 time. It is OK to have L2 outputs submitted at larger or small intervals. The L2 Output Oracle contract implements the following interface: diff --git a/specs/rollup-node.md b/specs/rollup-node.md index a69443798f28..213017227a9e 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -321,9 +321,10 @@ As stated earlier, an L2 block is considered *finalized* after a delay of `FINAL after the L1 block that generated it. This is a duration of approximately 7 days worth of L1 blocks. This is also known as the "fault proof window", as after this time the block can no longer be challenged by a fault proof. -L1 Ethereum reaches [finality][l1-finality] approximately every [12.8 minutes][consensus-time-params]. L2 blocks generated from finalized L1 blocks -are "safer" than most recent L2 blocks because they will never disappear from the chain's history because of a re-org. -However, they can still be challenged by a fault proof until the end of the fault proof window. +L1 Ethereum reaches [finality][l1-finality] approximately every [12.8 minutes][consensus-time-params]. L2 blocks +generated from finalized L1 blocksare "safer" than most recent L2 blocks because they will never disappear from the +chain's history because of a re-org. However, they can still be challenged by a fault proof until the end of the fault +proof window. [l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge [consensus-time-params]: https://github.com/ethereum/consensus-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#time-parameters From ef542c086cd866162b9921ddcbea7b12650791dd Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 21 Mar 2022 11:04:35 -0400 Subject: [PATCH 337/585] Rename MockL2OutputOracle to L2OutputOracle --- .../L1/{MockL2OutputOracle.sol => L2OutputOracle.sol} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename packages/contracts/contracts/L1/{MockL2OutputOracle.sol => L2OutputOracle.sol} (96%) diff --git a/packages/contracts/contracts/L1/MockL2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol similarity index 96% rename from packages/contracts/contracts/L1/MockL2OutputOracle.sol rename to packages/contracts/contracts/L1/L2OutputOracle.sol index 2510db44435d..580e7c995154 100644 --- a/packages/contracts/contracts/L1/MockL2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -2,9 +2,9 @@ pragma solidity >=0.8.10; /** - * @title MockL2OutputOracle + * @title L2OutputOracle */ -contract MockL2OutputOracle { +contract L2OutputOracle { uint256 public submissionInterval; uint256 public l2BlockTime; mapping(uint256 => bytes32) public l2Outputs; @@ -13,7 +13,7 @@ contract MockL2OutputOracle { uint256 public startingBlockTimestamp; /** - * Initialize the MockL2OutputOracle contract. + * Initialize the L2OutputOracle contract. * @param _submissionInterval The desired interval in seconds at which * checkpoints must be submitted. * @param _l2BlockTime The desired L2 inter-block time in seconds. From b6812c47511092fbb2d4a6976e1006b872b8c3dd Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 11:20:44 -0400 Subject: [PATCH 338/585] Address review comments --- specs/README.md | 1 - specs/glossary.md | 2 +- specs/proposals.md | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/specs/README.md b/specs/README.md index 30c3b36572ad..cef0578d2c5a 100644 --- a/specs/README.md +++ b/specs/README.md @@ -8,7 +8,6 @@ that maintains 1:1 compatibility with Ethereum. - [Glossary](glossary.md) - [Deposits](deposits.md) -- [Withdrawals](withdrawals.md) - [Execution Engine](exec-engine.md) - [L2 Output Root Proposals](proposals.md) - [Rollup Node](rollup-node.md) diff --git a/specs/glossary.md b/specs/glossary.md index ca1c7221c22b..00691d450e19 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -372,7 +372,7 @@ cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes [l2-output]: glossary.md#l2-output -A 32 byte value representing the current state of the L2 chain. +A 32 byte value which commits to the current state of the L2 chain. cf. [Proposing L2 output commitments](proposals.md#l2-output-root-proposals-specification) diff --git a/specs/proposals.md b/specs/proposals.md index c691b941d9f1..5362303cf755 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -53,7 +53,7 @@ struct ForkSpec { ## Proposing L2 Output Commitments The proposer's role is to construct and submit output commitments on a configurable interval to a contract on , which -it does by running the [L2 output submitter](../l2os/) (AKA L2OS). This service periodically queries the rollup +it does by running the [L2 output submitter](../l2os/). This service periodically queries the rollup node's [`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is described [below](#l2-output-commitment-construction). From a4225c1c1b58940091a70ac7ae9e9e3e50ac9524 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 11:45:00 -0400 Subject: [PATCH 339/585] Update optimism_outputAtBlock method spec The params and return values are given descriptive names, with types and sizes stated separately similar to the execution api specs: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#structures --- specs/rollup-node.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 213017227a9e..9658dcc8cacc 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -347,7 +347,7 @@ block forward each step, until there is an insufficient number of L1 blocks left ## L2 Output RPC method The Rollup node has its own RPC method, `optimism_outputAtBlock` which returns the -a 32 byte hash corresponding to the [SSZ] encoded [L2Output](./proposals.md#l2-output-commitment-construction). +a 32 byte hash corresponding to the [L2 output root](./proposals.md#l2-output-commitment-construction). [SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md @@ -359,9 +359,11 @@ The input and return types here are as defined by the [engine API specs][engine- - method: `optimism_outputAtBlock` - params: - 1. `QUANTITY` - L2 integer block number, or the strings `"safe"`, `"latest"`, or `"pending"` + 1. `blockNumber`: `QUANTITY`, 64 bits - L2 integer block number
+ OR `String` - one of `"safe"`, `"latest"`, or `"pending"`. - returns: - 1. `DATA` - The 32 byte output root + 1. `version`: `DATA`, 32 Bytes - the output root version number, beginning with 0. + 1. `l2OutputRoot`: `DATA`, 32 Bytes - the output root # Handling L1 Re-Orgs From 318f0b193dfaa83fd52494540700a7ccea5be761 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 15:49:24 -0400 Subject: [PATCH 340/585] Move definitions to end of doc --- packages/contracts/README.md | 1 - specs/proposals.md | 46 ++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/packages/contracts/README.md b/packages/contracts/README.md index 8e434a2819cc..c722948f27c9 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -22,7 +22,6 @@ yarn build ## Running Tests - The full test suite can be executed via `yarn`: ```shell diff --git a/specs/proposals.md b/specs/proposals.md index 5362303cf755..3ba0fadee752 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -7,14 +7,14 @@ **Table of Contents** -- [Definitions](#definitions) - - [Constants](#constants) - - [Types](#types) - [Proposing L2 Output Commitments](#proposing-l2-output-commitments) - [L2 Output Commitment Construction](#l2-output-commitment-construction) - [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract) - [Security Considerations](#security-considerations) - [L1 Reorgs](#l1-reorgs) +- [Summary of Definitions](#summary-of-definitions) + - [Constants](#constants) + - [Types](#types) @@ -30,26 +30,6 @@ are part of later specification milestones. [cannon]: https://github.com/ethereum-optimism/cannon -## Definitions - -### Constants - -| Name | Value | Unit | -| ---------------------- | ----- | ------- | -| `SUBMISSION_INTERVAL` | `1800` | seconds | -| `L2_BLOCK_TIME` | `2` | seconds | - -### Types - -The `ForkSpec` type contains the height and blockhash for a block in the L1 chain. - -```js -struct ForkSpec { - uint256 blockHeight; - bytes32 blockHash; -} -``` - ## Proposing L2 Output Commitments The proposer's role is to construct and submit output commitments on a configurable interval to a contract on , which @@ -152,3 +132,23 @@ function computeL2BlockNumber(uint256 _timestamp) public view returns (uint256) If the L1 has a reorg after an output has been generated and submitted, the L2 state and correct output may change leading to a faulty proposal. This is mitigated against in the OutputOracle by checking that the block at `_forkSpecifier.blockHeight` has the expected hash `_forkSpecifier.blockHash`. + +## Summary of Definitions + +### Constants + +| Name | Value | Unit | +| ---------------------- | ----- | ------- | +| `SUBMISSION_INTERVAL` | `1800` | seconds | +| `L2_BLOCK_TIME` | `2` | seconds | + +### Types + +The `ForkSpec` type contains the height and blockhash for a block in the L1 chain. + +```js +struct ForkSpec { + uint256 blockHeight; + bytes32 blockHash; +} +``` From 5569645d0270b21c8a25795d6204a2f9693ed974 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 21 Mar 2022 11:08:33 -0400 Subject: [PATCH 341/585] forge install: openzeppelin-contracts Make appendL2Output payable and onlyOwner --- .gitmodules | 3 +++ packages/contracts/.eslintignore | 5 +++++ packages/contracts/contracts/L1/L2OutputOracle.sol | 12 +++++++++--- packages/contracts/lib/openzeppelin-contracts | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) create mode 160000 packages/contracts/lib/openzeppelin-contracts diff --git a/.gitmodules b/.gitmodules index b8a7e1389771..bc99e9df7dfe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "packages/contracts/lib/ds-test"] path = packages/contracts/lib/ds-test url = https://github.com/dapphub/ds-test +[submodule "packages/contracts/lib/openzeppelin-contracts"] + path = packages/contracts/lib/openzeppelin-contracts + url = https://github.com/openzeppelin/openzeppelin-contracts diff --git a/packages/contracts/.eslintignore b/packages/contracts/.eslintignore index d08b03625b96..e2d42d983115 100644 --- a/packages/contracts/.eslintignore +++ b/packages/contracts/.eslintignore @@ -1,5 +1,10 @@ +# Deps and test files node_modules +lib + +# build output artifacts +forge-artifacts cache typechain coverage* diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 580e7c995154..edae831916c6 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -1,10 +1,12 @@ //SPDX-License-Identifier: MIT pragma solidity >=0.8.10; +import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; + /** * @title L2OutputOracle */ -contract L2OutputOracle { +contract L2OutputOracle is Ownable { uint256 public submissionInterval; uint256 public l2BlockTime; mapping(uint256 => bytes32) public l2Outputs; @@ -25,7 +27,8 @@ contract L2OutputOracle { uint256 _submissionInterval, uint256 _l2BlockTime, bytes32 _genesisL2Output, - uint256 _historicalTotalBlocks + uint256 _historicalTotalBlocks, + address sequencer ) { submissionInterval = _submissionInterval; l2BlockTime = _l2BlockTime; @@ -33,6 +36,8 @@ contract L2OutputOracle { historicalTotalBlocks = _historicalTotalBlocks; latestBlockTimestamp = block.timestamp; // solhint-disable not-rely-on-time startingBlockTimestamp = block.timestamp; // solhint-disable not-rely-on-time + + _transferOwnership(sequencer); } /** @@ -42,7 +47,8 @@ contract L2OutputOracle { * @param _l2Output The L2 output of the checkpoint block. * @param _timestamp The L2 block timestamp that resulted in _l2Output. */ - function appendL2Output(bytes32 _l2Output, uint256 _timestamp) external { + function appendL2Output(bytes32 _l2Output, uint256 _timestamp) external payable onlyOwner { + // todo: separate owner and sequencer roles require(block.timestamp > _timestamp, "Cannot append L2 output in future"); require(_l2Output != bytes32(0), "Cannot submit empty L2 output"); require(_timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp"); diff --git a/packages/contracts/lib/openzeppelin-contracts b/packages/contracts/lib/openzeppelin-contracts new file mode 160000 index 000000000000..52eeebecda14 --- /dev/null +++ b/packages/contracts/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit 52eeebecda140ebaf4ec8752ed119d8288287fac From b05366ed9b181e02ad77baaace88faf0e0613de9 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 15:16:24 -0400 Subject: [PATCH 342/585] Add l2OutputAppended event --- packages/contracts/contracts/L1/L2OutputOracle.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index edae831916c6..79bf48cf1007 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -7,6 +7,12 @@ import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownab * @title L2OutputOracle */ contract L2OutputOracle is Ownable { + + event l2OutputAppended( + bytes32 indexed _l2Output, + uint256 indexed _timestamp + ); + uint256 public submissionInterval; uint256 public l2BlockTime; mapping(uint256 => bytes32) public l2Outputs; @@ -55,6 +61,8 @@ contract L2OutputOracle is Ownable { // todo: add require statement to ensure a specific prev-hash exists on the current chain l2Outputs[_timestamp] = _l2Output; latestBlockTimestamp = _timestamp; + + emit l2OutputAppended(_l2Output, _timestamp); } /** From bca67a4b54d8c6fc17b87fa9ebe0e36e6326e491 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 15:37:53 -0400 Subject: [PATCH 343/585] Add l2OutputOracle tests --- .../contracts/test/L2OutputOracle.t.sol | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 packages/contracts/contracts/test/L2OutputOracle.t.sol diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol new file mode 100644 index 000000000000..39345efb2e2b --- /dev/null +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -0,0 +1,119 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; + +interface CheatCodes { + function prank(address) external; + function expectRevert(bytes calldata) external; + function warp(uint256) external; +} + +contract L2OutputOracle_Initializer is DSTest { + // Utility variables + CheatCodes cheats = CheatCodes(HEVM_ADDRESS); + bytes32 NON_ZERO_HASH = keccak256(abi.encode(1)); + uint256 appendedTimestamp; + + // Test target + L2OutputOracle oracle; + + // Constructor arguments + address sequencer = 0x000000000000000000000000000000000000AbBa; + uint256 submissionInterval = 1800; + uint256 l2BlockTime = 2; + bytes32 genesisL2Output = keccak256(abi.encode(2)); + uint256 historicalTotalBlocks = 100; + + // Cache of the initial L2 timestamp + uint256 startingBlockTimestamp; + + // By default the first block has timestamp zero, which will cause underflows in the tests + uint256 initTime = 1000; + + constructor() { + // Move time forward so we have a non-zero starting timestamp + cheats.warp(initTime); + // Deploy the L2OutputOracle and transfer owernship to the sequencer + oracle = new L2OutputOracle( + submissionInterval, + l2BlockTime, + genesisL2Output, + historicalTotalBlocks, + sequencer + ); + startingBlockTimestamp = block.timestamp; + + } +} + +// Define this test in a standalone contract to ensure it runs immediately after the constructor. +contract L2OutputOracleTest_Constructor is L2OutputOracle_Initializer { + function test_Constructor() external { + assertEq(oracle.owner(), sequencer); + assertEq(oracle.submissionInterval(), submissionInterval); + assertEq(oracle.l2BlockTime(), l2BlockTime); + assertEq(oracle.historicalTotalBlocks(), historicalTotalBlocks); + assertEq(oracle.latestBlockTimestamp(), startingBlockTimestamp); + assertEq(oracle.startingBlockTimestamp(), startingBlockTimestamp); + assertEq(oracle.l2Outputs(startingBlockTimestamp), genesisL2Output); + } +} + +contract L2OutputOracleTest is L2OutputOracle_Initializer { + bytes32 appendedOutput = keccak256(abi.encode(3)); + + constructor() { + appendedTimestamp = oracle.nextTimestamp(); + + // Warp to after the timestamp we'll append + cheats.warp(appendedTimestamp + 1); + cheats.prank(sequencer); + oracle.appendL2Output( + appendedOutput, + appendedTimestamp + ); + } + + function test_latestBlockTimestamp() external { + assertEq(oracle.latestBlockTimestamp(), appendedTimestamp); + } + + function test_getL2Outputs() external { + assertEq(oracle.l2Outputs(appendedTimestamp), appendedOutput); + } + + function test_nextTimestamp() external { + assertEq( + oracle.nextTimestamp(), + // The return value should match this arithmetic + initTime + submissionInterval * 2 + ); + } + + function test_computesL2BlockNumber() external { + // Test with an integer multiple of the l2BlockTime + uint256 argTimestamp = startingBlockTimestamp + 20; + uint256 expected = historicalTotalBlocks + 20/l2BlockTime; + assertEq( + oracle.computeL2BlockNumber(argTimestamp), + expected + ); + + // Test with a remainder + argTimestamp = startingBlockTimestamp + 33; + expected = historicalTotalBlocks + 33/l2BlockTime; + assertEq( + oracle.computeL2BlockNumber(argTimestamp), + expected + ); + } + + function testCannot_computePreHistoricalL2BlockNumber() external { + bytes memory expectedError = "timestamp prior to startingBlockTimestamp"; + uint256 argTimestamp = startingBlockTimestamp - 1; + cheats.expectRevert(expectedError); + oracle.computeL2BlockNumber(argTimestamp); + } +} From 2a81b496500e21549dde89ed9b34afc23ec0f1cb Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 20:42:14 -0400 Subject: [PATCH 344/585] Add comments and improve variables names Also reorder appendL2Output checks for readability --- .../contracts/contracts/L1/L2OutputOracle.sol | 46 ++++++++++++------- .../contracts/test/L2OutputOracle.t.sol | 2 +- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 79bf48cf1007..1a1888e04a4f 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -10,15 +10,26 @@ contract L2OutputOracle is Ownable { event l2OutputAppended( bytes32 indexed _l2Output, - uint256 indexed _timestamp + uint256 indexed _l2timestamp ); - uint256 public submissionInterval; - uint256 public l2BlockTime; - mapping(uint256 => bytes32) public l2Outputs; - uint256 public historicalTotalBlocks; + // The interval in seconds at which checkpoints must be submitted. + uint256 public immutable submissionInterval; + + // The time between blocks on L2. + uint256 public immutable l2BlockTime; + + // The number of blocks in the chain before the first block in this contract. + uint256 public immutable historicalTotalBlocks; + + // The timestamp of the first L2 block recorded in this contract. + uint256 public immutable startingBlockTimestamp; + + // The timestamp of the most recent L2 block recorded in this contract. uint256 public latestBlockTimestamp; - uint256 public startingBlockTimestamp; + + // A mapping from L2 timestamps to the output root for the block with that timestamp + mapping(uint256 => bytes32) public l2Outputs; /** * Initialize the L2OutputOracle contract. @@ -51,18 +62,19 @@ contract L2OutputOracle is Ownable { * block. The timestamp must be equal to the current value returned by * `nextTimestamp()` in order to be accepted. * @param _l2Output The L2 output of the checkpoint block. - * @param _timestamp The L2 block timestamp that resulted in _l2Output. + * @param _l2timestamp The L2 block timestamp that resulted in _l2Output. */ - function appendL2Output(bytes32 _l2Output, uint256 _timestamp) external payable onlyOwner { + function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp) external payable onlyOwner { // todo: separate owner and sequencer roles - require(block.timestamp > _timestamp, "Cannot append L2 output in future"); + require(_l2timestamp < block.timestamp, "Cannot append L2 output in future"); + require(_l2timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp"); require(_l2Output != bytes32(0), "Cannot submit empty L2 output"); - require(_timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp"); + // todo: add require statement to ensure a specific prev-hash exists on the current chain - l2Outputs[_timestamp] = _l2Output; - latestBlockTimestamp = _timestamp; + l2Outputs[_l2timestamp] = _l2Output; + latestBlockTimestamp = _l2timestamp; - emit l2OutputAppended(_l2Output, _timestamp); + emit l2OutputAppended(_l2Output, _l2timestamp); } /** @@ -75,10 +87,10 @@ contract L2OutputOracle is Ownable { /** * Computes the L2 block number given a target L2 block timestamp. - * @param _timestamp The L2 block timestamp of the target block. + * @param _l2timestamp The L2 block timestamp of the target block. */ - function computeL2BlockNumber(uint256 _timestamp) external view returns (uint256) { - require(_timestamp >= startingBlockTimestamp, "timestamp prior to startingBlockTimestamp"); - return historicalTotalBlocks + (_timestamp - startingBlockTimestamp) / l2BlockTime; + function computeL2BlockNumber(uint256 _l2timestamp) external view returns (uint256) { + require(_l2timestamp >= startingBlockTimestamp, "Timestamp prior to startingBlockTimestamp"); + return historicalTotalBlocks + (_l2timestamp - startingBlockTimestamp) / l2BlockTime; } } diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 39345efb2e2b..1e6416054ec3 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -111,7 +111,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { } function testCannot_computePreHistoricalL2BlockNumber() external { - bytes memory expectedError = "timestamp prior to startingBlockTimestamp"; + bytes memory expectedError = "Timestamp prior to startingBlockTimestamp"; uint256 argTimestamp = startingBlockTimestamp - 1; cheats.expectRevert(expectedError); oracle.computeL2BlockNumber(argTimestamp); From 8a2196fec5c4e69343fc8007c2006888e44f9363 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 21:13:33 -0400 Subject: [PATCH 345/585] Add sad path tests for appendL2Output --- .../contracts/test/L2OutputOracle.t.sol | 66 +++++++++++++++++-- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 1e6416054ec3..4ecd1061a12f 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -13,7 +13,6 @@ interface CheatCodes { contract L2OutputOracle_Initializer is DSTest { // Utility variables CheatCodes cheats = CheatCodes(HEVM_ADDRESS); - bytes32 NON_ZERO_HASH = keccak256(abi.encode(1)); uint256 appendedTimestamp; // Test target @@ -23,7 +22,7 @@ contract L2OutputOracle_Initializer is DSTest { address sequencer = 0x000000000000000000000000000000000000AbBa; uint256 submissionInterval = 1800; uint256 l2BlockTime = 2; - bytes32 genesisL2Output = keccak256(abi.encode(2)); + bytes32 genesisL2Output = keccak256(abi.encode(0)); uint256 historicalTotalBlocks = 100; // Cache of the initial L2 timestamp @@ -62,7 +61,7 @@ contract L2OutputOracleTest_Constructor is L2OutputOracle_Initializer { } contract L2OutputOracleTest is L2OutputOracle_Initializer { - bytes32 appendedOutput = keccak256(abi.encode(3)); + bytes32 appendedOutput1 = keccak256(abi.encode(1)); constructor() { appendedTimestamp = oracle.nextTimestamp(); @@ -71,7 +70,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { cheats.warp(appendedTimestamp + 1); cheats.prank(sequencer); oracle.appendL2Output( - appendedOutput, + appendedOutput1, appendedTimestamp ); } @@ -81,7 +80,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { } function test_getL2Outputs() external { - assertEq(oracle.l2Outputs(appendedTimestamp), appendedOutput); + assertEq(oracle.l2Outputs(appendedTimestamp), appendedOutput1); } function test_nextTimestamp() external { @@ -110,6 +109,63 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ); } + function test_appendingAnotherOutput() external { + bytes32 appendedOutput2 = keccak256(abi.encode(2)); + uint256 nextTimestamp = oracle.nextTimestamp(); + + // Ensure the submissionInterval is enforced + assertEq(nextTimestamp, appendedTimestamp + submissionInterval); + + cheats.warp(nextTimestamp + 1); + cheats.prank(sequencer); + oracle.appendL2Output(appendedOutput2, nextTimestamp); + } + + function testCannot_appendOutputIfNotSequencer() external { + bytes32 appendedOutput2 = keccak256(abi.encode(2)); + uint256 nextTimestamp = oracle.nextTimestamp(); + + cheats.warp(nextTimestamp + 1); + cheats.expectRevert("Ownable: caller is not the owner"); + oracle.appendL2Output(appendedOutput2, nextTimestamp); + } + + function testCannot_appendEmptyOutput() external { + bytes32 appendedOutput2 = bytes32(0); + uint256 nextTimestamp = oracle.nextTimestamp(); + cheats.warp(nextTimestamp + 1); + cheats.prank(sequencer); + cheats.expectRevert("Cannot submit empty L2 output"); + oracle.appendL2Output(appendedOutput2, nextTimestamp); + } + + function testCannot_appendUnexpectedTimestamp() external { + bytes32 appendedOutput2 = bytes32(0); + uint256 nextTimestamp = oracle.nextTimestamp(); + cheats.warp(nextTimestamp + 1); + cheats.prank(sequencer); + cheats.expectRevert("Timestamp not equal to next expected timestamp"); + oracle.appendL2Output(appendedOutput2, nextTimestamp - 1); + } + + function testCannot_appendCurrentTimestamp() external { + bytes32 appendedOutput2 = bytes32(0); + uint256 nextTimestamp = oracle.nextTimestamp(); + cheats.warp(nextTimestamp + 1); + cheats.prank(sequencer); + cheats.expectRevert("Cannot append L2 output in future"); + oracle.appendL2Output(appendedOutput2, block.timestamp); + } + + function testCannot_appendFutureTimestamp() external { + bytes32 appendedOutput2 = bytes32(0); + uint256 nextTimestamp = oracle.nextTimestamp(); + cheats.warp(nextTimestamp + 1); + cheats.prank(sequencer); + cheats.expectRevert("Cannot append L2 output in future"); + oracle.appendL2Output(appendedOutput2, block.timestamp); + } + function testCannot_computePreHistoricalL2BlockNumber() external { bytes memory expectedError = "Timestamp prior to startingBlockTimestamp"; uint256 argTimestamp = startingBlockTimestamp - 1; From 1b8d5b02e5a794f9a8bfffcbead26824fb26dd85 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 21:28:41 -0400 Subject: [PATCH 346/585] Add blockhash check Allows the sequencer to append a new output quickly, without worrying that the L1 chain might reorg to change the correct ouput. Also lint:fix contracts --- packages/contracts/.prettierignore | 9 +++++ packages/contracts/.solhintignore | 3 +- .../contracts/contracts/L1/L2OutputOracle.sol | 37 ++++++++++++++----- .../contracts/test/L2OutputOracle.t.sol | 34 +++++++---------- 4 files changed, 52 insertions(+), 31 deletions(-) diff --git a/packages/contracts/.prettierignore b/packages/contracts/.prettierignore index db04f3ca875d..326dbfa52b3f 100644 --- a/packages/contracts/.prettierignore +++ b/packages/contracts/.prettierignore @@ -1,6 +1,15 @@ +# Deps and test files node_modules +lib +contracts/test/*.t.sol + +# build output artifacts +forge-artifacts cache typechain coverage* + +# Other autogenerated files gasReporterOutput.json +slither.db.json diff --git a/packages/contracts/.solhintignore b/packages/contracts/.solhintignore index ad2b84c9ae43..3fc6fd094a66 100644 --- a/packages/contracts/.solhintignore +++ b/packages/contracts/.solhintignore @@ -1,3 +1,4 @@ +# Deps and test files node_modules -lib/ds-test +lib contracts/test/*.t.sol diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 1a1888e04a4f..617ea6c05b5c 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -7,11 +7,7 @@ import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownab * @title L2OutputOracle */ contract L2OutputOracle is Ownable { - - event l2OutputAppended( - bytes32 indexed _l2Output, - uint256 indexed _l2timestamp - ); + event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); // The interval in seconds at which checkpoints must be submitted. uint256 public immutable submissionInterval; @@ -63,14 +59,34 @@ contract L2OutputOracle is Ownable { * `nextTimestamp()` in order to be accepted. * @param _l2Output The L2 output of the checkpoint block. * @param _l2timestamp The L2 block timestamp that resulted in _l2Output. + * @param _blockhash A block hash which must be included in the current chain. + * @param _blocknumber The block number with the specified block hash. */ - function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp) external payable onlyOwner { - // todo: separate owner and sequencer roles + function appendL2Output( + bytes32 _l2Output, + uint256 _l2timestamp, + bytes32 _blockhash, + uint256 _blocknumber + ) external payable onlyOwner { require(_l2timestamp < block.timestamp, "Cannot append L2 output in future"); require(_l2timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp"); require(_l2Output != bytes32(0), "Cannot submit empty L2 output"); - // todo: add require statement to ensure a specific prev-hash exists on the current chain + if (_blockhash != bytes32(0)) { + // This check allows the sequencer to append an output based on a given L1 block, + // without fear that it will be reorged out. + // It will also revert if the blockheight provided is more than 256 blocks behind the + // chain tip (as the hash will return as zero). This does open the door to a grieffing + // attack in which the sequencer's submission is censored until the block is no longer + // retrievable, if the sequencer is experiencing this attack it can simply leave out the + // blockhash value, and delay submission until it is confident that the L1 block is + // finalized. + require( + blockhash(_blocknumber) == _blockhash, + "Blockhash does not match the hash at the expected height." + ); + } + l2Outputs[_l2timestamp] = _l2Output; latestBlockTimestamp = _l2timestamp; @@ -90,7 +106,10 @@ contract L2OutputOracle is Ownable { * @param _l2timestamp The L2 block timestamp of the target block. */ function computeL2BlockNumber(uint256 _l2timestamp) external view returns (uint256) { - require(_l2timestamp >= startingBlockTimestamp, "Timestamp prior to startingBlockTimestamp"); + require( + _l2timestamp >= startingBlockTimestamp, + "Timestamp prior to startingBlockTimestamp" + ); return historicalTotalBlocks + (_l2timestamp - startingBlockTimestamp) / l2BlockTime; } } diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 4ecd1061a12f..0c2f5604e7b4 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -6,7 +6,9 @@ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; interface CheatCodes { function prank(address) external; + function expectRevert(bytes calldata) external; + function warp(uint256) external; } @@ -43,7 +45,6 @@ contract L2OutputOracle_Initializer is DSTest { sequencer ); startingBlockTimestamp = block.timestamp; - } } @@ -69,10 +70,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // Warp to after the timestamp we'll append cheats.warp(appendedTimestamp + 1); cheats.prank(sequencer); - oracle.appendL2Output( - appendedOutput1, - appendedTimestamp - ); + oracle.appendL2Output(appendedOutput1, appendedTimestamp, 0, 0); } function test_latestBlockTimestamp() external { @@ -94,19 +92,13 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { function test_computesL2BlockNumber() external { // Test with an integer multiple of the l2BlockTime uint256 argTimestamp = startingBlockTimestamp + 20; - uint256 expected = historicalTotalBlocks + 20/l2BlockTime; - assertEq( - oracle.computeL2BlockNumber(argTimestamp), - expected - ); + uint256 expected = historicalTotalBlocks + 20 / l2BlockTime; + assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); // Test with a remainder argTimestamp = startingBlockTimestamp + 33; - expected = historicalTotalBlocks + 33/l2BlockTime; - assertEq( - oracle.computeL2BlockNumber(argTimestamp), - expected - ); + expected = historicalTotalBlocks + 33 / l2BlockTime; + assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); } function test_appendingAnotherOutput() external { @@ -118,7 +110,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); - oracle.appendL2Output(appendedOutput2, nextTimestamp); + oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0); } function testCannot_appendOutputIfNotSequencer() external { @@ -127,7 +119,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { cheats.warp(nextTimestamp + 1); cheats.expectRevert("Ownable: caller is not the owner"); - oracle.appendL2Output(appendedOutput2, nextTimestamp); + oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0); } function testCannot_appendEmptyOutput() external { @@ -136,7 +128,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Cannot submit empty L2 output"); - oracle.appendL2Output(appendedOutput2, nextTimestamp); + oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0); } function testCannot_appendUnexpectedTimestamp() external { @@ -145,7 +137,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Timestamp not equal to next expected timestamp"); - oracle.appendL2Output(appendedOutput2, nextTimestamp - 1); + oracle.appendL2Output(appendedOutput2, nextTimestamp - 1, 0, 0); } function testCannot_appendCurrentTimestamp() external { @@ -154,7 +146,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Cannot append L2 output in future"); - oracle.appendL2Output(appendedOutput2, block.timestamp); + oracle.appendL2Output(appendedOutput2, block.timestamp, 0, 0); } function testCannot_appendFutureTimestamp() external { @@ -163,7 +155,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Cannot append L2 output in future"); - oracle.appendL2Output(appendedOutput2, block.timestamp); + oracle.appendL2Output(appendedOutput2, block.timestamp, 0, 0); } function testCannot_computePreHistoricalL2BlockNumber() external { From 8637cbfab67690b3b39d39b02f10591115eede2c Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 22 Mar 2022 22:46:18 -0400 Subject: [PATCH 347/585] Improve ordering of tests Test file clean up and commenting improvements --- .../contracts/test/L2OutputOracle.t.sol | 95 +++++++++++++++---- 1 file changed, 79 insertions(+), 16 deletions(-) diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 0c2f5604e7b4..1f5ed34b2a7b 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -10,11 +10,14 @@ interface CheatCodes { function expectRevert(bytes calldata) external; function warp(uint256) external; + + function roll(uint256) external; } contract L2OutputOracle_Initializer is DSTest { // Utility variables CheatCodes cheats = CheatCodes(HEVM_ADDRESS); + bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); uint256 appendedTimestamp; // Test target @@ -73,14 +76,21 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.appendL2Output(appendedOutput1, appendedTimestamp, 0, 0); } + /**************** + * Getter Tests * + ****************/ + + // Test: latestBlockTimestamp() should return the correct value function test_latestBlockTimestamp() external { assertEq(oracle.latestBlockTimestamp(), appendedTimestamp); } + // Test: getL2Outputs() should return the correct value function test_getL2Outputs() external { assertEq(oracle.l2Outputs(appendedTimestamp), appendedOutput1); } + // Test: nextTimestamp() should return the correct value function test_nextTimestamp() external { assertEq( oracle.nextTimestamp(), @@ -89,7 +99,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ); } - function test_computesL2BlockNumber() external { + // Test: computeL2BlockNumber() should return the correct value + function test_computeL2BlockNumber() external { // Test with an integer multiple of the l2BlockTime uint256 argTimestamp = startingBlockTimestamp + 20; uint256 expected = historicalTotalBlocks + 20 / l2BlockTime; @@ -100,7 +111,20 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { expected = historicalTotalBlocks + 33 / l2BlockTime; assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); } + // Test: computeL2BlockNumber() fails with a blockNumber from before the startingBlockTimestamp + function testCannot_computePreHistoricalL2BlockNumber() external { + bytes memory expectedError = "Timestamp prior to startingBlockTimestamp"; + uint256 argTimestamp = startingBlockTimestamp - 1; + cheats.expectRevert(expectedError); + oracle.computeL2BlockNumber(argTimestamp); + } + /***************************** + * Append Tests - Happy Path * + *****************************/ + + // Test: appendL2Output succeeds when given valid input, and no block hash and number are + // specified. function test_appendingAnotherOutput() external { bytes32 appendedOutput2 = keccak256(abi.encode(2)); uint256 nextTimestamp = oracle.nextTimestamp(); @@ -113,55 +137,94 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0); } + // Test: appendL2Output succeeds when given valid input, and when a block hash and number are + // specified for reorg protection. + // This tests is disabled (w/ skip_ prefix) because all blocks in Foundry currently have a + // blockhash of zero. + function skip_test_appendWithBlockhashAndHeight() external { + // Move ahead to block 100 so that we can reference historical blocks + cheats.roll(100); + + // Get the number and hash of a previous block in the chain + uint256 blockNumber = block.number - 1; + bytes32 blockHash = blockhash(blockNumber); + + uint256 nextTimestamp = oracle.nextTimestamp(); + cheats.warp(nextTimestamp + 1); + cheats.prank(sequencer); + + // Changing the blockNumber argument should break this tests, however it does not + // per the comment preceding this test. + oracle.appendL2Output(nonZeroHash, nextTimestamp, blockHash, blockNumber); + } + + /*************************** + * Append Tests - Sad Path * + ***************************/ + + // Test: appendL2Output fails if called by a party that is not the sequencer. function testCannot_appendOutputIfNotSequencer() external { - bytes32 appendedOutput2 = keccak256(abi.encode(2)); uint256 nextTimestamp = oracle.nextTimestamp(); cheats.warp(nextTimestamp + 1); cheats.expectRevert("Ownable: caller is not the owner"); - oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0); + oracle.appendL2Output(nonZeroHash, nextTimestamp, 0, 0); } + // Test: appendL2Output fails given a zero blockhash. function testCannot_appendEmptyOutput() external { - bytes32 appendedOutput2 = bytes32(0); + bytes32 outputToAppend = bytes32(0); uint256 nextTimestamp = oracle.nextTimestamp(); cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Cannot submit empty L2 output"); - oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0); + oracle.appendL2Output(outputToAppend, nextTimestamp, 0, 0); } + // Test: appendL2Output fails if the timestamp doesn't match the next expected timestamp. function testCannot_appendUnexpectedTimestamp() external { - bytes32 appendedOutput2 = bytes32(0); uint256 nextTimestamp = oracle.nextTimestamp(); cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Timestamp not equal to next expected timestamp"); - oracle.appendL2Output(appendedOutput2, nextTimestamp - 1, 0, 0); + oracle.appendL2Output(nonZeroHash, nextTimestamp - 1, 0, 0); } + // Test: appendL2Output fails if the timestamp is equal to the current L1 timestamp. function testCannot_appendCurrentTimestamp() external { - bytes32 appendedOutput2 = bytes32(0); uint256 nextTimestamp = oracle.nextTimestamp(); cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Cannot append L2 output in future"); - oracle.appendL2Output(appendedOutput2, block.timestamp, 0, 0); + oracle.appendL2Output(nonZeroHash, block.timestamp, 0, 0); } + // Test: appendL2Output fails if the timestamp is in the future. function testCannot_appendFutureTimestamp() external { - bytes32 appendedOutput2 = bytes32(0); uint256 nextTimestamp = oracle.nextTimestamp(); cheats.warp(nextTimestamp + 1); cheats.prank(sequencer); cheats.expectRevert("Cannot append L2 output in future"); - oracle.appendL2Output(appendedOutput2, block.timestamp, 0, 0); + oracle.appendL2Output(nonZeroHash, block.timestamp + 1, 0, 0); } - function testCannot_computePreHistoricalL2BlockNumber() external { - bytes memory expectedError = "Timestamp prior to startingBlockTimestamp"; - uint256 argTimestamp = startingBlockTimestamp - 1; - cheats.expectRevert(expectedError); - oracle.computeL2BlockNumber(argTimestamp); + // Test: appendL2Output fails when given valid input, but the block hash and number do not + // match. + // This tests is disabled (w/ skip_ prefix) because all blocks in Foundry currently have a + // blockhash of zero. + function skip_testCannot_AppendWithUnmatchedBlockhash() external { + // Move ahead to block 100 so that we can reference historical blocks + cheats.roll(100); + + // Get the number and hash of a previous block in the chain + uint256 blockNumber = block.number - 1; + bytes32 blockHash = blockhash(blockNumber); + + uint256 nextTimestamp = oracle.nextTimestamp(); + cheats.warp(nextTimestamp + 1); + cheats.prank(sequencer); + + // This will fail when foundry no longer returns zerod block hashes + oracle.appendL2Output(nonZeroHash, nextTimestamp, blockHash, blockNumber - 1); } } From 71b49cc74777be8e046a40824d18e44f0f0e17ea Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 23 Mar 2022 13:27:08 -0400 Subject: [PATCH 348/585] Fix off-by one error in computeL2BlockNumber --- packages/contracts/contracts/L1/L2OutputOracle.sol | 4 +++- .../contracts/contracts/test/L2OutputOracle.t.sol | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 617ea6c05b5c..e27e3e08be86 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -110,6 +110,8 @@ contract L2OutputOracle is Ownable { _l2timestamp >= startingBlockTimestamp, "Timestamp prior to startingBlockTimestamp" ); - return historicalTotalBlocks + (_l2timestamp - startingBlockTimestamp) / l2BlockTime; + // If _l2timestamp == startingBlockTimestamp, then the L2BlockNumber should be + // historicalTotalBlocks + 1 + return historicalTotalBlocks + 1 + (_l2timestamp - startingBlockTimestamp) / l2BlockTime; } } diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 1f5ed34b2a7b..13dcf8be6703 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -101,14 +101,19 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // Test: computeL2BlockNumber() should return the correct value function test_computeL2BlockNumber() external { + // Test with the timestamp of the very first appended block + uint256 argTimestamp = startingBlockTimestamp; + uint256 expected = historicalTotalBlocks + 1; + assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); + // Test with an integer multiple of the l2BlockTime - uint256 argTimestamp = startingBlockTimestamp + 20; - uint256 expected = historicalTotalBlocks + 20 / l2BlockTime; + argTimestamp = startingBlockTimestamp + 20; + expected = historicalTotalBlocks + 1 + (20 / l2BlockTime); assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); // Test with a remainder argTimestamp = startingBlockTimestamp + 33; - expected = historicalTotalBlocks + 33 / l2BlockTime; + expected = historicalTotalBlocks + 1 + (33 / l2BlockTime); assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); } // Test: computeL2BlockNumber() fails with a blockNumber from before the startingBlockTimestamp From fd1a8f1fc3b3890770700ff0e3b1df6723dba7a6 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 23 Mar 2022 13:31:18 -0400 Subject: [PATCH 349/585] Import forge-std for HEVM interface --- .gitmodules | 3 + .../contracts/test/L2OutputOracle.t.sol | 65 ++++++++----------- packages/contracts/lib/forge-std | 1 + 3 files changed, 32 insertions(+), 37 deletions(-) create mode 160000 packages/contracts/lib/forge-std diff --git a/.gitmodules b/.gitmodules index bc99e9df7dfe..406056b3a734 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "packages/contracts/lib/openzeppelin-contracts"] path = packages/contracts/lib/openzeppelin-contracts url = https://github.com/openzeppelin/openzeppelin-contracts +[submodule "packages/contracts/lib/forge-std"] + path = packages/contracts/lib/forge-std + url = https://github.com/brockelmore/forge-std diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 13dcf8be6703..ad23fa0dbbc9 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -2,21 +2,12 @@ pragma solidity 0.8.10; import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { Vm } from "../../lib/forge-std/src/Vm.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -interface CheatCodes { - function prank(address) external; - - function expectRevert(bytes calldata) external; - - function warp(uint256) external; - - function roll(uint256) external; -} - contract L2OutputOracle_Initializer is DSTest { // Utility variables - CheatCodes cheats = CheatCodes(HEVM_ADDRESS); + Vm vm = Vm(HEVM_ADDRESS); bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); uint256 appendedTimestamp; @@ -38,7 +29,7 @@ contract L2OutputOracle_Initializer is DSTest { constructor() { // Move time forward so we have a non-zero starting timestamp - cheats.warp(initTime); + vm.warp(initTime); // Deploy the L2OutputOracle and transfer owernship to the sequencer oracle = new L2OutputOracle( submissionInterval, @@ -71,8 +62,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { appendedTimestamp = oracle.nextTimestamp(); // Warp to after the timestamp we'll append - cheats.warp(appendedTimestamp + 1); - cheats.prank(sequencer); + vm.warp(appendedTimestamp + 1); + vm.prank(sequencer); oracle.appendL2Output(appendedOutput1, appendedTimestamp, 0, 0); } @@ -120,7 +111,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { function testCannot_computePreHistoricalL2BlockNumber() external { bytes memory expectedError = "Timestamp prior to startingBlockTimestamp"; uint256 argTimestamp = startingBlockTimestamp - 1; - cheats.expectRevert(expectedError); + vm.expectRevert(expectedError); oracle.computeL2BlockNumber(argTimestamp); } @@ -137,8 +128,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // Ensure the submissionInterval is enforced assertEq(nextTimestamp, appendedTimestamp + submissionInterval); - cheats.warp(nextTimestamp + 1); - cheats.prank(sequencer); + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0); } @@ -148,15 +139,15 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // blockhash of zero. function skip_test_appendWithBlockhashAndHeight() external { // Move ahead to block 100 so that we can reference historical blocks - cheats.roll(100); + vm.roll(100); // Get the number and hash of a previous block in the chain uint256 blockNumber = block.number - 1; bytes32 blockHash = blockhash(blockNumber); uint256 nextTimestamp = oracle.nextTimestamp(); - cheats.warp(nextTimestamp + 1); - cheats.prank(sequencer); + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); // Changing the blockNumber argument should break this tests, however it does not // per the comment preceding this test. @@ -171,8 +162,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { function testCannot_appendOutputIfNotSequencer() external { uint256 nextTimestamp = oracle.nextTimestamp(); - cheats.warp(nextTimestamp + 1); - cheats.expectRevert("Ownable: caller is not the owner"); + vm.warp(nextTimestamp + 1); + vm.expectRevert("Ownable: caller is not the owner"); oracle.appendL2Output(nonZeroHash, nextTimestamp, 0, 0); } @@ -180,36 +171,36 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { function testCannot_appendEmptyOutput() external { bytes32 outputToAppend = bytes32(0); uint256 nextTimestamp = oracle.nextTimestamp(); - cheats.warp(nextTimestamp + 1); - cheats.prank(sequencer); - cheats.expectRevert("Cannot submit empty L2 output"); + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); + vm.expectRevert("Cannot submit empty L2 output"); oracle.appendL2Output(outputToAppend, nextTimestamp, 0, 0); } // Test: appendL2Output fails if the timestamp doesn't match the next expected timestamp. function testCannot_appendUnexpectedTimestamp() external { uint256 nextTimestamp = oracle.nextTimestamp(); - cheats.warp(nextTimestamp + 1); - cheats.prank(sequencer); - cheats.expectRevert("Timestamp not equal to next expected timestamp"); + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); + vm.expectRevert("Timestamp not equal to next expected timestamp"); oracle.appendL2Output(nonZeroHash, nextTimestamp - 1, 0, 0); } // Test: appendL2Output fails if the timestamp is equal to the current L1 timestamp. function testCannot_appendCurrentTimestamp() external { uint256 nextTimestamp = oracle.nextTimestamp(); - cheats.warp(nextTimestamp + 1); - cheats.prank(sequencer); - cheats.expectRevert("Cannot append L2 output in future"); + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); + vm.expectRevert("Cannot append L2 output in future"); oracle.appendL2Output(nonZeroHash, block.timestamp, 0, 0); } // Test: appendL2Output fails if the timestamp is in the future. function testCannot_appendFutureTimestamp() external { uint256 nextTimestamp = oracle.nextTimestamp(); - cheats.warp(nextTimestamp + 1); - cheats.prank(sequencer); - cheats.expectRevert("Cannot append L2 output in future"); + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); + vm.expectRevert("Cannot append L2 output in future"); oracle.appendL2Output(nonZeroHash, block.timestamp + 1, 0, 0); } @@ -219,15 +210,15 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // blockhash of zero. function skip_testCannot_AppendWithUnmatchedBlockhash() external { // Move ahead to block 100 so that we can reference historical blocks - cheats.roll(100); + vm.roll(100); // Get the number and hash of a previous block in the chain uint256 blockNumber = block.number - 1; bytes32 blockHash = blockhash(blockNumber); uint256 nextTimestamp = oracle.nextTimestamp(); - cheats.warp(nextTimestamp + 1); - cheats.prank(sequencer); + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); // This will fail when foundry no longer returns zerod block hashes oracle.appendL2Output(nonZeroHash, nextTimestamp, blockHash, blockNumber - 1); diff --git a/packages/contracts/lib/forge-std b/packages/contracts/lib/forge-std new file mode 160000 index 000000000000..d880879a97ce --- /dev/null +++ b/packages/contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit d880879a97cea1857688c13a6ceb869ef48d715f From 92a269d4001e8568121df2c8e39ef67e225727ac Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 23 Mar 2022 15:40:53 -0400 Subject: [PATCH 350/585] Fix slither warnings --- packages/contracts/contracts/L1/L2OutputOracle.sol | 2 ++ packages/contracts/slither.config.json | 2 +- packages/contracts/slither.db.json | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index e27e3e08be86..5154cb7d26d9 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -6,6 +6,8 @@ import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownab /** * @title L2OutputOracle */ +// The payable keyword is used on appendL2Output to save gas on the msg.value check. +// slither-disable-next-line locked-ether contract L2OutputOracle is Ownable { event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); diff --git a/packages/contracts/slither.config.json b/packages/contracts/slither.config.json index a745b72be39e..f48a7929c076 100644 --- a/packages/contracts/slither.config.json +++ b/packages/contracts/slither.config.json @@ -8,5 +8,5 @@ "hardhat_ignore_compile": false, "disable_color": false, "exclude_dependencies": false, - "filter_paths": "contracts/test|lib/ds-test" + "filter_paths": "contracts/test|lib" } diff --git a/packages/contracts/slither.db.json b/packages/contracts/slither.db.json index 877ba1a66143..1ce4b1b35d52 100644 --- a/packages/contracts/slither.db.json +++ b/packages/contracts/slither.db.json @@ -1 +1 @@ -[{"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1102, "length": 648, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-59) has payable functions:\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#38-58)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L59) has payable functions:\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L38-L58)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "be013b000d4c176d4d893619bdca725d93e4761e4b2e22fa77a64144e53abb26", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 2010, "length": 88, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 97}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}}}], "description": "MockL2OutputOracle.appendL2Output(bytes32,uint256) (contracts/L1/MockL2OutputOracle.sol#45-51) uses a dangerous strict equality:\n\t- require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/MockL2OutputOracle.sol#48)\n", "markdown": "[MockL2OutputOracle.appendL2Output(bytes32,uint256)](contracts/L1/MockL2OutputOracle.sol#L45-L51) uses a dangerous strict equality:\n\t- [require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/MockL2OutputOracle.sol#L48)\n", "first_markdown_element": "contracts/L1/MockL2OutputOracle.sol#L45-L51", "id": "74ee9955ede80e105221045625f8b4f963a0ca8422674891166ad65bdcdba57a", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}, {"type": "node", "name": "OFFSET = uint160(0x1111000000000000000000000000000000001111)", "source_mapping": {"start": 284, "length": 85, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [14], "starting_column": 5, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}}}], "description": "DepositFeed.slitherConstructorConstantVariables() (contracts/L1/DepositFeed.sol#7-59) uses literals with too many digits:\n\t- OFFSET = uint160(0x1111000000000000000000000000000000001111) (contracts/L1/DepositFeed.sol#14)\n", "markdown": "[DepositFeed.slitherConstructorConstantVariables()](contracts/L1/DepositFeed.sol#L7-L59) uses literals with too many digits:\n\t- [OFFSET = uint160(0x1111000000000000000000000000000000001111)](contracts/L1/DepositFeed.sol#L14)\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "14adc89c437b961183112ca2328ae0e07b627d12995c5555d2c2fca5d4dbe1aa", "check": "too-many-digits", "impact": "Informational", "confidence": "Medium"}] +[{"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2866, "length": 1475, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 5187, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 3134, "length": 90, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [76], "starting_column": 9, "ending_column": 99}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2866, "length": 1475, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 5187, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}}}], "description": "L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256) (contracts/L1/L2OutputOracle.sol#69-98) uses a dangerous strict equality:\n\t- require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/L2OutputOracle.sol#76)\n", "markdown": "[L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256)](contracts/L1/L2OutputOracle.sol#L69-L98) uses a dangerous strict equality:\n\t- [require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/L2OutputOracle.sol#L76)\n", "first_markdown_element": "contracts/L1/L2OutputOracle.sol#L69-L98", "id": "6b3c4e2b8a4f6d93d3d999172ff1f3c665c26f908c4371ebfd6497f4da0bcae1", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2822, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4836, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 3090, "length": 90, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [75], "starting_column": 9, "ending_column": 99}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2822, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4836, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}}}], "description": "L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256) (contracts/L1/L2OutputOracle.sol#68-97) uses a dangerous strict equality:\n\t- require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/L2OutputOracle.sol#75)\n", "markdown": "[L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256)](contracts/L1/L2OutputOracle.sol#L68-L97) uses a dangerous strict equality:\n\t- [require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/L2OutputOracle.sol#L75)\n", "first_markdown_element": "contracts/L1/L2OutputOracle.sol#L68-L97", "id": "5d96abf0f353837ac9dd7491c5f9aa1c3d77a1eb32cd71c603e3a4235ed19e4c", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2764, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4778, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 3032, "length": 90, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [74], "starting_column": 9, "ending_column": 99}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2764, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4778, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}}}], "description": "L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256) (contracts/L1/L2OutputOracle.sol#67-96) uses a dangerous strict equality:\n\t- require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/L2OutputOracle.sol#74)\n", "markdown": "[L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256)](contracts/L1/L2OutputOracle.sol#L67-L96) uses a dangerous strict equality:\n\t- [require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/L2OutputOracle.sol#L74)\n", "first_markdown_element": "contracts/L1/L2OutputOracle.sol#L67-L96", "id": "24228b71a4962875f71c3df68448d2aa61f627308da50eac1efcd59c2e55c440", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1102, "length": 648, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-59) has payable functions:\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#38-58)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L59) has payable functions:\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L38-L58)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "be013b000d4c176d4d893619bdca725d93e4761e4b2e22fa77a64144e53abb26", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 2010, "length": 88, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 97}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}}}], "description": "MockL2OutputOracle.appendL2Output(bytes32,uint256) (contracts/L1/MockL2OutputOracle.sol#45-51) uses a dangerous strict equality:\n\t- require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/MockL2OutputOracle.sol#48)\n", "markdown": "[MockL2OutputOracle.appendL2Output(bytes32,uint256)](contracts/L1/MockL2OutputOracle.sol#L45-L51) uses a dangerous strict equality:\n\t- [require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/MockL2OutputOracle.sol#L48)\n", "first_markdown_element": "contracts/L1/MockL2OutputOracle.sol#L45-L51", "id": "74ee9955ede80e105221045625f8b4f963a0ca8422674891166ad65bdcdba57a", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}, {"type": "node", "name": "OFFSET = uint160(0x1111000000000000000000000000000000001111)", "source_mapping": {"start": 284, "length": 85, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [14], "starting_column": 5, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}}}], "description": "DepositFeed.slitherConstructorConstantVariables() (contracts/L1/DepositFeed.sol#7-59) uses literals with too many digits:\n\t- OFFSET = uint160(0x1111000000000000000000000000000000001111) (contracts/L1/DepositFeed.sol#14)\n", "markdown": "[DepositFeed.slitherConstructorConstantVariables()](contracts/L1/DepositFeed.sol#L7-L59) uses literals with too many digits:\n\t- [OFFSET = uint160(0x1111000000000000000000000000000000001111)](contracts/L1/DepositFeed.sol#L14)\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "14adc89c437b961183112ca2328ae0e07b627d12995c5555d2c2fca5d4dbe1aa", "check": "too-many-digits", "impact": "Informational", "confidence": "Medium"}] From a1b0e5ecd8126bd71cb5202a02e5c82932b6964a Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 14:04:09 -0400 Subject: [PATCH 351/585] Add foundry.toml For some reason this file is not being read when using the yarn build and test scripts, so we need to keep the additional arguments in those scripts, however this file makes it easier to run forge without yarn which is nice. --- packages/contracts/README.md | 6 +++++- packages/contracts/foundry.toml | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 packages/contracts/foundry.toml diff --git a/packages/contracts/README.md b/packages/contracts/README.md index c722948f27c9..bf4da246011d 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -22,7 +22,11 @@ yarn build ## Running Tests -The full test suite can be executed via `yarn`: +First get the dependencies: + +`git submodule init` and `git submodule update` + +Then the full test suite can be executed via `yarn`: ```shell yarn test diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml new file mode 100644 index 000000000000..6aeda3f1c787 --- /dev/null +++ b/packages/contracts/foundry.toml @@ -0,0 +1,5 @@ +[default] +src = 'contracts' + # We need to build seperate artifacts for forge and hh, because they each expect a different + # structure for the artifacts directory. +out = 'forge-artifacts' From 7640dbe026b0deb09bb11d9cbca0f55a45550fd4 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 14:23:07 -0400 Subject: [PATCH 352/585] Fix typo and event declaration ordering --- packages/contracts/.solhint.json | 1 + packages/contracts/contracts/L1/L2OutputOracle.sol | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/contracts/.solhint.json b/packages/contracts/.solhint.json index d33c0727b407..2a633721a88a 100644 --- a/packages/contracts/.solhint.json +++ b/packages/contracts/.solhint.json @@ -10,6 +10,7 @@ "modifier-name-mixedcase": "error", "ordering": "warn", "avoid-low-level-calls": "off", + "event-name-camelcase": "off", "reason-string": "off", "avoid-tx-origin": "off", "func-visibility": ["warn", { "ignoreConstructors": true }] diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 5154cb7d26d9..4610b7da4190 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -9,8 +9,6 @@ import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownab // The payable keyword is used on appendL2Output to save gas on the msg.value check. // slither-disable-next-line locked-ether contract L2OutputOracle is Ownable { - event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); - // The interval in seconds at which checkpoints must be submitted. uint256 public immutable submissionInterval; @@ -29,6 +27,9 @@ contract L2OutputOracle is Ownable { // A mapping from L2 timestamps to the output root for the block with that timestamp mapping(uint256 => bytes32) public l2Outputs; + // Emitted when an output is appended + event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + /** * Initialize the L2OutputOracle contract. * @param _submissionInterval The desired interval in seconds at which @@ -78,7 +79,7 @@ contract L2OutputOracle is Ownable { // This check allows the sequencer to append an output based on a given L1 block, // without fear that it will be reorged out. // It will also revert if the blockheight provided is more than 256 blocks behind the - // chain tip (as the hash will return as zero). This does open the door to a grieffing + // chain tip (as the hash will return as zero). This does open the door to a griefing // attack in which the sequencer's submission is censored until the block is no longer // retrievable, if the sequencer is experiencing this attack it can simply leave out the // blockhash value, and delay submission until it is confident that the L1 block is From 61437ff0a4198f1b3f33392da370b70451b286d1 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 14:30:42 -0400 Subject: [PATCH 353/585] Add getL2Output function and make mapping internal --- packages/contracts/contracts/L1/L2OutputOracle.sol | 10 +++++++++- packages/contracts/contracts/test/L2OutputOracle.t.sol | 10 ++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 4610b7da4190..3a10558be140 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -25,7 +25,7 @@ contract L2OutputOracle is Ownable { uint256 public latestBlockTimestamp; // A mapping from L2 timestamps to the output root for the block with that timestamp - mapping(uint256 => bytes32) public l2Outputs; + mapping(uint256 => bytes32) internal l2Outputs; // Emitted when an output is appended event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); @@ -104,6 +104,14 @@ contract L2OutputOracle is Ownable { return latestBlockTimestamp + submissionInterval; } + /** + * Returns the L2 output root given a target L2 block timestamp. Returns 0 if none is found. + * @param _l2Timestamp The L2 block timestamp of the target block. + */ + function getL2Output(uint256 _l2Timestamp) external view returns (bytes32) { + return l2Outputs[_l2Timestamp]; + } + /** * Computes the L2 block number given a target L2 block timestamp. * @param _l2timestamp The L2 block timestamp of the target block. diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index ad23fa0dbbc9..ea11dfa11918 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -51,7 +51,7 @@ contract L2OutputOracleTest_Constructor is L2OutputOracle_Initializer { assertEq(oracle.historicalTotalBlocks(), historicalTotalBlocks); assertEq(oracle.latestBlockTimestamp(), startingBlockTimestamp); assertEq(oracle.startingBlockTimestamp(), startingBlockTimestamp); - assertEq(oracle.l2Outputs(startingBlockTimestamp), genesisL2Output); + assertEq(oracle.getL2Output(startingBlockTimestamp), genesisL2Output); } } @@ -76,9 +76,11 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(oracle.latestBlockTimestamp(), appendedTimestamp); } - // Test: getL2Outputs() should return the correct value - function test_getL2Outputs() external { - assertEq(oracle.l2Outputs(appendedTimestamp), appendedOutput1); + // Test: getL2Output() should return the correct value + function test_getL2Output() external { + assertEq(oracle.getL2Output(appendedTimestamp), appendedOutput1); + assertEq(oracle.getL2Output(appendedTimestamp + 1), 0); + } // Test: nextTimestamp() should return the correct value From 820e7de355ea12f1db0190b776d8e648da195b53 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 25 Mar 2022 11:00:09 -0400 Subject: [PATCH 354/585] Update spec to match implementation --- .../contracts/contracts/L1/L2OutputOracle.sol | 1 + specs/proposals.md | 47 +++++++------------ 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 3a10558be140..26cac56ee539 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -60,6 +60,7 @@ contract L2OutputOracle is Ownable { * Accepts an L2 output checkpoint and the timestamp of the corresponding L2 * block. The timestamp must be equal to the current value returned by * `nextTimestamp()` in order to be accepted. + * This function may only be called by the Sequencer. * @param _l2Output The L2 output of the checkpoint block. * @param _l2timestamp The L2 block timestamp that resulted in _l2Output. * @param _blockhash A block hash which must be included in the current chain. diff --git a/specs/proposals.md b/specs/proposals.md index 3ba0fadee752..e6a22c8a0ec0 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -14,7 +14,6 @@ - [L1 Reorgs](#l1-reorgs) - [Summary of Definitions](#summary-of-definitions) - [Constants](#constants) - - [Types](#types) @@ -42,6 +41,10 @@ If there is no newly finalized output, the service continues querying until it r output, and the appropriate timestamp, to the [L2 Output Commitment](#l2-output-commitment-smart-contract) contract's `appendL2Output()` function. The timestamp MUST be the next multiple of the `SUBMISSION_INTERVAL` value. +> **Note regarding future work:** In the initial version of the system, the proposer will be the same entity as the +> sequencer, which is a trusted role. In the future proposers will need to submit a bond in order to post L2 output +> roots, and some or all of this bond may be taken in the event of a faulty proposal. + ## L2 Output Commitment Construction This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in @@ -91,32 +94,28 @@ based on L2 time. It is OK to have L2 outputs submitted at larger or small inter The L2 Output Oracle contract implements the following interface: ```js -/** - * Data necessary to ensure that the output is being written to the expected fork of the L1 chain. - * This protects against an erroneous commitment in the event of an L1 reorg. - */ -struct ForkSpec { - uint256 blockHeight; - bytes32 blockHash; -} - /** * Accepts an L2 output checkpoint and the timestamp of the corresponding L2 * block. The timestamp must be equal to the current value returned by * `nextTimestamp()` in order to be accepted. + * This function may only be called by the Sequencer. * @param _l2Output The L2 output of the checkpoint block. - * @param _timestamp The L2 block timestamp that resulted in _l2Output. - * @param _forkSpecifier A commitment to a specific fork. + * @param _l2timestamp The L2 block timestamp that resulted in _l2Output. + * @param _blockhash A block hash which must be included in the current chain. + * @param _blocknumber The block number with the specified block hash. */ -function appendL2Output(bytes32 _l2Output, uint256 _timestamp, ForkSpec _forkSpecifier) external +function appendL2Output( + bytes32 _l2Output, + uint256 _l2timestamp, + bytes32 _blockhash, + uint256 _blocknumber +) /** * Computes the timestamp of the next L2 block that needs to be checkpointed. */ -function nextTimestamp() public view returns (uint256) { - return latestBlockTimestamp + submissionInterval; -} +function nextTimestamp() public view returns (uint256) /** * Computes the L2 block number given a target L2 block timestamp. @@ -130,8 +129,9 @@ function computeL2BlockNumber(uint256 _timestamp) public view returns (uint256) ### L1 Reorgs If the L1 has a reorg after an output has been generated and submitted, the L2 state and correct output may change -leading to a faulty proposal. This is mitigated against in the OutputOracle by checking that the block at -`_forkSpecifier.blockHeight` has the expected hash `_forkSpecifier.blockHash`. +leading to a faulty proposal. This is mitigated against by allowing the sequencer to submit an +L1 block number and hash to the Output Oracle when appending a new output; in the event of a reorg, the block hash +will not match that of the block with that number and the call will revert. ## Summary of Definitions @@ -141,14 +141,3 @@ leading to a faulty proposal. This is mitigated against in the OutputOracle by c | ---------------------- | ----- | ------- | | `SUBMISSION_INTERVAL` | `1800` | seconds | | `L2_BLOCK_TIME` | `2` | seconds | - -### Types - -The `ForkSpec` type contains the height and blockhash for a block in the L1 chain. - -```js -struct ForkSpec { - uint256 blockHeight; - bytes32 blockHash; -} -``` From 67d4c7930f045d47583dab190365bda90021671f Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 25 Mar 2022 12:29:58 -0400 Subject: [PATCH 355/585] Rename reorg protection vars to with L1 prefix --- packages/contracts/contracts/L1/L2OutputOracle.sol | 12 ++++++------ .../contracts/contracts/test/L2OutputOracle.t.sol | 14 +++++++------- specs/proposals.md | 8 ++++---- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 26cac56ee539..a9b8e6133f56 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -63,20 +63,20 @@ contract L2OutputOracle is Ownable { * This function may only be called by the Sequencer. * @param _l2Output The L2 output of the checkpoint block. * @param _l2timestamp The L2 block timestamp that resulted in _l2Output. - * @param _blockhash A block hash which must be included in the current chain. - * @param _blocknumber The block number with the specified block hash. + * @param _l1Blockhash A block hash which must be included in the current chain. + * @param _l1Blocknumber The block number with the specified block hash. */ function appendL2Output( bytes32 _l2Output, uint256 _l2timestamp, - bytes32 _blockhash, - uint256 _blocknumber + bytes32 _l1Blockhash, + uint256 _l1Blocknumber ) external payable onlyOwner { require(_l2timestamp < block.timestamp, "Cannot append L2 output in future"); require(_l2timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp"); require(_l2Output != bytes32(0), "Cannot submit empty L2 output"); - if (_blockhash != bytes32(0)) { + if (_l1Blockhash != bytes32(0)) { // This check allows the sequencer to append an output based on a given L1 block, // without fear that it will be reorged out. // It will also revert if the blockheight provided is more than 256 blocks behind the @@ -86,7 +86,7 @@ contract L2OutputOracle is Ownable { // blockhash value, and delay submission until it is confident that the L1 block is // finalized. require( - blockhash(_blocknumber) == _blockhash, + blockhash(_l1Blocknumber) == _l1Blockhash, "Blockhash does not match the hash at the expected height." ); } diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index ea11dfa11918..433412b0d828 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -144,16 +144,16 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { vm.roll(100); // Get the number and hash of a previous block in the chain - uint256 blockNumber = block.number - 1; - bytes32 blockHash = blockhash(blockNumber); + uint256 l1BlockNumber = block.number - 1; + bytes32 l1BlockHash = blockhash(l1BlockNumber); uint256 nextTimestamp = oracle.nextTimestamp(); vm.warp(nextTimestamp + 1); vm.prank(sequencer); - // Changing the blockNumber argument should break this tests, however it does not + // Changing the l1BlockNumber argument should break this tests, however it does not // per the comment preceding this test. - oracle.appendL2Output(nonZeroHash, nextTimestamp, blockHash, blockNumber); + oracle.appendL2Output(nonZeroHash, nextTimestamp, l1BlockHash, l1BlockNumber); } /*************************** @@ -215,14 +215,14 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { vm.roll(100); // Get the number and hash of a previous block in the chain - uint256 blockNumber = block.number - 1; - bytes32 blockHash = blockhash(blockNumber); + uint256 l1BlockNumber = block.number - 1; + bytes32 l1BlockHash = blockhash(l1BlockNumber); uint256 nextTimestamp = oracle.nextTimestamp(); vm.warp(nextTimestamp + 1); vm.prank(sequencer); // This will fail when foundry no longer returns zerod block hashes - oracle.appendL2Output(nonZeroHash, nextTimestamp, blockHash, blockNumber - 1); + oracle.appendL2Output(nonZeroHash, nextTimestamp, l1BlockHash, l1BlockNumber - 1); } } diff --git a/specs/proposals.md b/specs/proposals.md index e6a22c8a0ec0..286f9cb65cf7 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -101,14 +101,14 @@ The L2 Output Oracle contract implements the following interface: * This function may only be called by the Sequencer. * @param _l2Output The L2 output of the checkpoint block. * @param _l2timestamp The L2 block timestamp that resulted in _l2Output. - * @param _blockhash A block hash which must be included in the current chain. - * @param _blocknumber The block number with the specified block hash. + * @param _l1Blockhash A block hash which must be included in the current chain. + * @param _l1Blocknumber The block number with the specified block hash. */ function appendL2Output( bytes32 _l2Output, uint256 _l2timestamp, - bytes32 _blockhash, - uint256 _blocknumber + bytes32 _l1Blockhash, + uint256 _l1Blocknumber ) From 7702527dc294dc222db362edc70d8110523a52bf Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 28 Mar 2022 15:37:41 -0400 Subject: [PATCH 356/585] fix: linter ignore node_modules in sub dirs --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index dbc93d2248db..1777a77ae033 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "scripts": { "setup": "yarn install && cargo install lychee", "lint": "yarn lint:fix && yarn lint:check", - "lint:fix": "markdownlint-cli2-fix \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", - "lint:check": "markdownlint-cli2 \"./opnode/README.md\" \"./specs/**/*.md\" \"#node_modules\"", + "lint:fix": "markdownlint-cli2-fix \"./opnode/README.md\" \"./specs/**/*.md\" \"#**/node_modules\"", + "lint:check": "markdownlint-cli2 \"./opnode/README.md\" \"./specs/**/*.md\" \"#**/node_modules\"", "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./opnode/README.md\" \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"", "lint:toc": "doctoc --title=\"**Table of Contents**\" ./specs ./meta" } From 069ea2e30eb54560ffa157ae629a9a104976c664 Mon Sep 17 00:00:00 2001 From: Murphy Law Date: Mon, 28 Mar 2022 17:52:49 -0400 Subject: [PATCH 357/585] Implement opnode RPC server (#282) - Initial RPC server implementation in rollup-node - Implement optimism_outputAtBlock to be used by L2OSS - /healthz endpoint - Output root construction - getProof RPC util to pull and verify account Co-authored-by: protolambda --- Makefile | 2 +- go.sum | 5 -- opnode/cmd/main.go | 2 +- opnode/flags/flags.go | 28 +++++++++ opnode/node/api.go | 76 ++++++++++++++++++++++++ opnode/node/config.go | 6 ++ opnode/node/node.go | 21 ++++++- opnode/node/server.go | 108 +++++++++++++++++++++++++++++++++++ opnode/node/server_test.go | 97 +++++++++++++++++++++++++++++++ opnode/node/util.go | 78 +++++++++++++++++++++++++ opnode/predeploys.go | 5 ++ opnode/rollup/driver/step.go | 2 +- opnode/service.go | 20 +++++-- opnode/test/system_test.go | 6 +- ops/docker-compose.yml | 10 +++- 15 files changed, 448 insertions(+), 18 deletions(-) create mode 100644 opnode/node/api.go create mode 100644 opnode/node/server.go create mode 100644 opnode/node/server_test.go create mode 100644 opnode/node/util.go create mode 100644 opnode/predeploys.go diff --git a/Makefile b/Makefile index 362616e69b10..4c07adf1b9d9 100644 --- a/Makefile +++ b/Makefile @@ -21,4 +21,4 @@ devnet-up: devnet-down: @(cd ./ops && docker-compose down) -.PHONY: devnet-stop \ No newline at end of file +.PHONY: devnet-stop diff --git a/go.sum b/go.sum index 09dacfce5899..9eab70a0d83d 100644 --- a/go.sum +++ b/go.sum @@ -84,7 +84,6 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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= @@ -460,7 +459,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -519,7 +517,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v 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.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -573,11 +570,9 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index d7af2124fc35..29967fc455df 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -73,7 +73,7 @@ func RollupNodeMain(ctx *cli.Context) error { return err } - n, err := node.New(context.Background(), cfg, logCfg.NewLogger()) + n, err := node.New(context.Background(), cfg, logCfg.NewLogger(), VersionWithMeta) if err != nil { log.Error("Unable to create the rollup node", "error", err) return err diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go index c2913a54f16b..65849d1f3ea1 100644 --- a/opnode/flags/flags.go +++ b/opnode/flags/flags.go @@ -31,6 +31,24 @@ var ( Required: true, EnvVar: prefixEnvVar("ROLLUP_CONFIG"), } + L2EthNodeAddr = cli.StringFlag{ + Name: "l2.eth", + Usage: "Address of L2 User JSON-RPC endpoint to use (eth namespace required)", + Required: true, + EnvVar: prefixEnvVar("L2_ETH_RPC"), + } + RPCListenAddr = cli.StringFlag{ + Name: "rpc.addr", + Usage: "RPC listening address", + Required: true, + EnvVar: prefixEnvVar("RPC_ADDR"), + } + RPCListenPort = cli.IntFlag{ + Name: "rpc.port", + Usage: "RPC listening port", + Required: true, + EnvVar: prefixEnvVar("RPC_PORT"), + } /* Optional Flags */ @@ -47,6 +65,12 @@ var ( EnvVar: prefixEnvVar("BATCHSUBMITTER_KEY"), } + WithdrawalContractAddr = cli.StringFlag{ + Name: "rpc.withdrawalcontractaddress", + Usage: "Address of the Withdrawal contract. By default, this is set to the withdrawal contract predeploy", + EnvVar: prefixEnvVar("WITHDRAWAL_CONTRACT_ADDR"), + } + LogLevelFlag = cli.StringFlag{ Name: "log.level", Usage: "The lowest log level that will be output", @@ -70,11 +94,15 @@ var requiredFlags = []cli.Flag{ L1NodeAddr, L2EngineAddrs, RollupConfig, + L2EthNodeAddr, + RPCListenAddr, + RPCListenPort, } var optionalFlags = []cli.Flag{ SequencingEnabledFlag, BatchSubmitterKeyFlag, + WithdrawalContractAddr, LogLevelFlag, LogFormatFlag, LogColorFlag, diff --git a/opnode/node/api.go b/opnode/node/api.go new file mode 100644 index 000000000000..12d799e054c6 --- /dev/null +++ b/opnode/node/api.go @@ -0,0 +1,76 @@ +package node + +import ( + "context" + "fmt" + + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" +) + +type l2EthClient interface { + GetBlockHeader(ctx context.Context, blockTag string) (*types.Header, error) + // GetProof returns a proof of the account, it may return a nil result without error if the address was not found. + GetProof(ctx context.Context, address common.Address, blockTag string) (*AccountResult, error) +} + +type nodeAPI struct { + client l2EthClient + withdrawalContractAddr common.Address + log log.Logger +} + +func newNodeAPI(l2Client l2EthClient, withdrawalContractAddr common.Address, log log.Logger) *nodeAPI { + return &nodeAPI{ + client: l2Client, + withdrawalContractAddr: withdrawalContractAddr, + log: log, + } +} + +func (n *nodeAPI) OutputAtBlock(ctx context.Context, number rpc.BlockNumber) ([]l2.Bytes32, error) { + // TODO: rpc.BlockNumber doesn't support the "safe" tag. Need a new type + + head, err := n.client.GetBlockHeader(ctx, toBlockNumArg(number)) + if err != nil { + n.log.Error("failed to get block", "err", err) + return nil, err + } + if head == nil { + return nil, ethereum.NotFound + } + + proof, err := n.client.GetProof(ctx, n.withdrawalContractAddr, toBlockNumArg(number)) + if err != nil { + n.log.Error("failed to get contract proof", "err", err) + return nil, err + } + if proof == nil { + return nil, ethereum.NotFound + } + // make sure that the proof (including storage hash) that we retrieved is correct by verifying it against the state-root + if err := proof.Verify(head.Root); err != nil { + n.log.Error("invalid withdrawal root detected in block", "stateRoot", head.Root, "blocknum", number, "msg", err) + return nil, fmt.Errorf("invalid withdrawal root hash") + } + + var l2OutputRootVersion l2.Bytes32 // it's zero for now + l2OutputRoot := ComputeL2OutputRoot(l2OutputRootVersion, head.Hash(), head.Root, proof.StorageHash) + + return []l2.Bytes32{l2OutputRootVersion, l2OutputRoot}, nil +} + +func toBlockNumArg(number rpc.BlockNumber) string { + if number == rpc.LatestBlockNumber { + return "latest" + } + if number == rpc.PendingBlockNumber { + return "pending" + } + return hexutil.EncodeUint64(uint64(number.Int64())) +} diff --git a/opnode/node/config.go b/opnode/node/config.go index 79a71758d23d..9f4b85e240ee 100644 --- a/opnode/node/config.go +++ b/opnode/node/config.go @@ -5,12 +5,14 @@ import ( "fmt" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common" ) type Config struct { // L1 and L2 nodes L1NodeAddr string // Address of L1 User JSON-RPC endpoint to use (eth namespace required) L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required) + L2NodeAddr string // Address of L2 User JSON-RPC endpoint to use (eth namespace required) Rollup rollup.Config @@ -19,6 +21,10 @@ type Config struct { // SubmitterPrivKey, temporary config var while the batch-submitter is part of the rollup node SubmitterPrivKey *ecdsa.PrivateKey + + RPCListenAddr string + RPCListenPort int + WithdrawalContractAddr common.Address } // Check verifies that the given configuration makes sense diff --git a/opnode/node/node.go b/opnode/node/node.go index 675f2dc8ffb0..21da16db66e9 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -24,6 +24,7 @@ type OpNode struct { log log.Logger l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) l2Engines []*driver.Driver // engines to keep synced + server *rpcServer done chan struct{} } @@ -47,7 +48,7 @@ func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) return ret, nil } -func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { +func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (*OpNode, error) { if err := cfg.Check(); err != nil { return nil, err } @@ -88,10 +89,20 @@ func New(ctx context.Context, cfg *Config, log log.Logger) (*OpNode, error) { l2Engines = append(l2Engines, engine) } + l2Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L2NodeAddr) + if err != nil { + return nil, fmt.Errorf("failed to dial l2 address (%s): %w", cfg.L2NodeAddr, err) + } + server, err := newRPCServer(ctx, cfg.RPCListenAddr, cfg.RPCListenPort, &l2EthClientImpl{l2Node}, cfg.WithdrawalContractAddr, log, appVersion) + if err != nil { + return nil, err + } + n := &OpNode{ log: log, l1Source: l1Source, l2Engines: l2Engines, + server: server, done: make(chan struct{}), } @@ -150,9 +161,14 @@ func (c *OpNode) Start(ctx context.Context) error { l1Heads := make(chan eth.L1BlockRef, 10) l1HeadsFeed.Subscribe(l1Heads) + c.log.Info("Starting JSON-RPC server") + if err := c.server.Start(); err != nil { + return fmt.Errorf("unable to start RPC server: %w", err) + } + c.log.Info("Start-up complete!") - go func() { + go func() { for { select { case l1Head := <-l1Heads: @@ -181,4 +197,5 @@ func (c *OpNode) Stop() { if c.done != nil { close(c.done) } + c.server.Stop() } diff --git a/opnode/node/server.go b/opnode/node/server.go new file mode 100644 index 000000000000..667dcafc92ad --- /dev/null +++ b/opnode/node/server.go @@ -0,0 +1,108 @@ +package node + +import ( + "context" + "errors" + "fmt" + "net" + "net/http" + "strings" + + "github.com/ethereum/go-ethereum" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" +) + +// TODO(inphi): add metrics + +type rpcServer struct { + endpoint string + api *nodeAPI + httpServer *http.Server + appVersion string + listenAddr net.Addr + log log.Logger +} + +func newRPCServer(ctx context.Context, addr string, port int, l2Client l2EthClient, withdrawalContractAddress common.Address, log log.Logger, appVersion string) (*rpcServer, error) { + api := newNodeAPI(l2Client, withdrawalContractAddress, log.New("rpc", "node")) + endpoint := fmt.Sprintf("%s:%d", addr, port) + r := &rpcServer{ + endpoint: endpoint, + api: api, + appVersion: appVersion, + log: log, + } + return r, nil +} + +func (s *rpcServer) Start() error { + apis := []rpc.API{{ + Namespace: "optimism", + Service: s.api, + Public: true, + Authenticated: false, + }} + srv := rpc.NewServer() + if err := node.RegisterApis(apis, nil, srv, true); err != nil { + return err + } + + host := strings.Split(s.endpoint, ":")[0] + nodeHandler := node.NewHTTPHandlerStack(srv, nil, []string{host}, nil) + + mux := http.NewServeMux() + mux.Handle("/", nodeHandler) + mux.HandleFunc("/healthz", healthzHandler(s.appVersion)) + + listener, err := net.Listen("tcp", s.endpoint) + if err != nil { + return err + } + s.listenAddr = listener.Addr() + + s.httpServer = &http.Server{Handler: mux} + go func() { + if err := s.httpServer.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) { // todo improve error handling + s.log.Error("http server failed", "err", err) + } + }() + return nil +} + +func (r *rpcServer) Stop() { + _ = r.httpServer.Shutdown(context.Background()) +} + +func (r *rpcServer) Addr() net.Addr { + return r.listenAddr +} + +func healthzHandler(appVersion string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte(appVersion)) + } +} + +type l2EthClientImpl struct { + l2RPCClient *rpc.Client +} + +func (c *l2EthClientImpl) GetBlockHeader(ctx context.Context, blockTag string) (*types.Header, error) { + var head *types.Header + err := c.l2RPCClient.CallContext(ctx, &head, "eth_getBlockByNumber", blockTag, false) + return head, err +} + +func (c *l2EthClientImpl) GetProof(ctx context.Context, address common.Address, blockTag string) (*AccountResult, error) { + var getProofResponse *AccountResult + err := c.l2RPCClient.CallContext(ctx, &getProofResponse, "eth_getProof", address, []common.Hash{}, blockTag) + if err == nil && getProofResponse == nil { + err = ethereum.NotFound + } + return getProofResponse, err +} diff --git a/opnode/node/server_test.go b/opnode/node/server_test.go new file mode 100644 index 000000000000..4f43a4063541 --- /dev/null +++ b/opnode/node/server_test.go @@ -0,0 +1,97 @@ +package node + +import ( + "context" + "encoding/json" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/assert" +) + +func TestOutputAtBlock(t *testing.T) { + log := testlog.Logger(t, log.LvlError) + + // Test data for Merkle Patricia Trie: proof the eth2 deposit contract account contents (mainnet). + headerTestData := ` + { + "parentHash": "0x47e0bb8a195bb8c41f88451ebb6c6e19caea3538e259c4f8f576f563651b2ea0", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x3ecef08d0e2dad803847e052249bb4f8bff2d5bb", + "stateRoot": "0xb46d4bcb0e471e1b8506031a1f34ebc6f200253cbaba56246dd2320e8e2c8f13", + "transactionsRoot": "0x51cb26cf4c43af5dcc4188aa75880f4d3287ceb2ed386a45eb3ac03cd1e9af1b", + "receiptsRoot": "0xc162238f66ce50a32f2f28e704bff473ec3e24f40ac78951de228712fd70aae0", + "logsBloom": "0x4171800201004021001804029c02602220000484a2105822038000028010441800061a4444822145e002000cc30505848be96119a82220406240104b0a652018450d00090018104848430009493171202140a04081440048180000408040108002508d4002fa40010880110008018810902989f00d81040080210430c00864003a108042000000040108001a400020001934a6890b20828c600901c020180084020800051120a806202900989e2280005310024038808019a08025e2a09040000029824340600a2820215040200e044144408052cd0a4c320441a146100260002838a2180300040294100480215488a050e2420a2480a1420480085441222810", + "difficulty": "0x2eeba6b1f2d375", + "number": "0xdcdc89", + "gasLimit": "0x1c9c380", + "gasUsed": "0x4b7cf4", + "timestamp": "0x62419993", + "extraData": "0x73656f36", + "mixHash": "0x91af27781efde0b9a52631b7770a1ba3cb789e2bbf02bcf4538d22bfed01158e", + "nonce": "0x59ad2bebfd070533", + "baseFeePerGas": "0x59eab8ea2", + "hash": "0x8512bee03061475e4b069171f7b406097184f16b22c3f5c97c0abfc49591c524" + }` + var header types.Header + err := json.Unmarshal([]byte(headerTestData), &header) + assert.NoError(t, err) + + resultTestData := ` + { + "address": "0x00000000219ab540356cbb839cbe05303d7705fa", + "accountProof": [ + "0xf90211a0053de2c69b88d64fcbb62d9da3282c7100d4b87ae1fb2577c07f0a9e25c80991a0675e4b40d962dce5bf03e24da87d193dbe99a65c1b26d1d6f8738222ccb953c6a05c5479c870b639b36fd6e4c3014f6250bb961b8312775bad0e6a605e1e9c9f55a0087c6656d467c8bffdc00ad447e6b2be7e9e173139597f8e3db628a31505497fa00a2a6f22504a5a4ebff8fd869e781ef24ab657e64ce4e6ef0228ea9ebb6283f7a0ca22287cb61d05a6f39fbf62a92ae7ffbad20102ba6462261866008d3930c8c8a00d5899983ed06e619dd6fdd6a9b678a3da6ffebf62debedc6981ea7c41934a37a02b7efb0aa93b02ed4c232a6d420c3f772ef915bc71397b98c4d128847058fc95a0d018a365d4c1eaa02c7f63153bda7dbbf66fc3e40b51f1bc2f9c9bcc7e8020d1a0eff9b494995139443a09365e928a74f36cc2cca2f0f675f3df530f65c4e6470ea012c7419fe80ec73ffc5ef2c9839593e2dec3e6911d21db20b2323e5f6801417ea09db162242bc6382a6fb0dce195157c8bf47c13ebcc9506dcf1b466a1ff3bfe59a0f96c17b003d5ec293f5332fb830bc34667b396dcd3d4e2ed508ff77d965f78c5a04099fe09f64b53cdb90f3537a10c5b1f8f6e8dfa2a4308acdbd6b3496629869ea0efd2b1a33d4562cab8c20748fb3bdb60aabd85cd6c112e826738af3a3bcb7b3ca03b701015938a78fca54055e8797fdbe2b63e029e3d88e519d81e4aa74f52516c80", + "0xf90211a07a61b559adab3b69960d88a06052127b6c4e1f052adaa714a78a94cf77db6bdda00773c97a11c32dbe5f6d5dc2bf4e4cc25bf0408a3cb5fe54bb7f65ad548eb08fa0278563f7e29d7edfccb56a1da17f2e171f28eac51e3e4b0b425c0e8472a5686ba0893e1be872339b57d89d3741df456d9a91754a00ee080aa7aa175f674f57c84da0c523ed9cfe7927f8ec7e47a65155a69d77c0e9485b50d52d240cf6836e3a02a4a07c9e0b7c24c780fc2657d2f902ccaa749ac284c3ac7c192d1c6509bcf858a536a05595963f4d1e353e660d79382b41681d7e006af420dae1c0de7fc22e1b9df86ca0d299e02df563fa2904626a4ed6de01b0bffb49204885cc9e82bb04348bb87e63a069e72616ce71f8b72cbd7b37eefab216fa3b9324947d0870ff1e133b93b74818a01caf32199ac1573b5f8ceb82b454424fab10fce895544f1eb7e327c94f0a235ea0795525db25d2453b0c41e3fe939b4fbca046820c7b498736cc6f98a9afc6b56aa0f41cca6a5e1791eccd77c12318ea9a8d7fff643d84db7b716abda7e2b4fffdf1a0f6e9e0abfbe843102ad697567ae36c3c1486ec167956a4e149cce9da89980d2da0a48b1793b3deb902a3d35d7c98528c37005495f252e46ef06e7cba54e17ad638a0c4a38db3d5324e46f18ede4bfbe566932fa8cc8fa7891eac5b03c751a72ee65da01199874c07a3e9234f54158d49fe26e0eb9e174f3a245a10b0bb399e715ef73e80", + "0xf90211a0151a549c4bda6b7ad536eb85a0955cfdc9baef3859722a02641b4995a765e039a00d6c2898c6f9c5c5cbb225e5ce25092f8214da069847fcc92d2d5cd262abd426a08cf5d2ec077fb3c36df58d7cbcd5c7245de7de6cbf0faea7879c07210e2178e4a0991e0d147c3d0b0257509ed8ecb7d46d817287823a2c7632d7e545a07e5c05efa0650dd56a943e6eabbc57507a843a81fc049de047d6194606ed29b3abf3b8fb98a0814c4a99d93d88f88033ca3813f37e4476b3be1a8a20f2b387ed2af666014843a090c8ce86b3e8bb37bb41bbceac49a851feaf0a7d7f958d3733d46c35321d6113a03a59be04ecd3bd7ef287d55ca44eba754ceb73b11984eb07f5c9ef662473e264a0b8dcabc2461c7aa0d5e9e64c00471c866c61221ba12abd7230d1cf6363074d8aa01c822a721bbdf3a25cfc5c039a2203d7dde065077d8e9e2a79d785634049651da0956f1b89b07519c33567bf334ed83b22ee76ef5b057831f52c227bf87b12e7d4a0f5bc6aacd26c0cfe7e6854cc61ef085195e7ecf5f04a656272eaaca0910a570ba00538ca73976dc9d42683bfd6c81f85fffe7594532b2f2d60f035c7662ee636f3a0481681e232913e57fc0dcdf3e41558726c475bd824efd190e87c4cc6c59c5abfa0421a065bd09dd47510c9b5f05bdcce6992f8f290252ff5ac039ec3b74b784b54a06fecfc2bb7fb3fddd8988453f1687e4c7eefa73fae5b23a8a6c00c6c2347c70780", + "0xf90211a030229b7cca8cc53d7edd465792b917c92da8a54e9ab1dd2fbe13c1952f49bb15a0d8ce8468603b262264ae9c1086f98a8f6cf9b89bf9b08c7e03c7e3d78a1e28afa0f0874b64554052fb583cea8da9939bd8b6f6f083a15424dd3613bdaabccd723ca0a9293e5b4cc2cf664296a87b3bdb9ad066af00b425a2efb29dfdda2c6d2b5b7ba0e19e1cd86832a1998da1c117a1ba38634de7030f7f396a3e1728bee5953feabca02f0c836b4fe1536c4ec538857318355dd2b98c71e3f11244bcb62d9a77f53a9aa0b3891659442e5da4b5a87bc30e6d646f14ddf99aac6ead34d2dd0929b425650ca073861564bc6b774edce16d69fef0209c1ae6cc7c7ae9abf66aa22ebff6db3baca09c2bc83919d84f12158f0fb3075107fe29d9e9f0e1225676f72e9119f4db3ea2a0751f8378a2e268d8bf15f572061dd8f50090156af8ad210143f9fb434ec3314ca0f3710dbc5a154804c31b7390f681e4ce7569350ebccaa1763c644781d8afc4c8a082295baf1fb8f3c98c52554b95a08bc5457b0fdc936a1d6ae69aa3316388c568a097ca8b1bdfbc6b0156a2ff293f4bdfe421dabcf9634ccc12d2ba399020ec3027a0302946c9212085e56c22ad229a87fba0b5c728f5904b1ed5e905fcfba3c83f09a032e8579104775cc6ebed949b21d3afd1a6ff9d66c3377384b147ebc99b4d3780a0c26e0c54ec91c56c6bd4a84029ad24fb890635c51df16fd1d56a6d83d0dca81680", + "0xf90211a0dd0f9c581d9abf2b4d97e6540f3026ad0c84fd32c77ca28178bc345f095ee8a0a0743c851689b4bf826b25307c8b0af143fa5ed754cb54b6365f6db0b43178a49fa0fca51828e9a618deac1de3ae0f3f8ac851bc26386c41a279cc43236b22d636eca0be49b0fd047089e186855a6d18c3b70399204c01a612bd7e7ff447999b188484a0fe48aeb769431c737ed50395843234d6bd2ed2c6e8be916df4f1724981675810a087c33eebdeece82fa8a21649b6c3b1e9fcd3de4d5bb68729433deb7e32e87481a083226a8b46c513232ab509daa733ffa1573b9763b0a1f7e8915fe98e0e69e358a07b0ee3cc203cc3ece1cb4b1714d1cb01224ec6244101ff77f599609798efaecca088c32b6ccc3c1afb2e1d5a4df69089cfca7351bc171b7f8bf4b52d2e2588cba6a0204d7c392ed55dd9576ba8c6ecce8affadd967a1bc62141922fecab72bbf4907a00d8cf034eeb5f9686c3ebeacde2ac4eef1fefd9a2006ff8f144207e874da70c6a0637929a730614ab1f0b780c5bef785afba18e12f0ea283789cb66fe6923f4278a08374de3370417c480be77f025eee79151f73ded8d071b518e5b258123d923af1a0d3f27cd43be2c58b528372c9187b99a49a8d06f504ffa2d5ff4cd3ec74bd3ccca02104bbd4bee7770c4663e95ec8881005062b77324b436812e399b44c93961d7fa035847ce3af7e94228ab92d86a0fbb23ba5b6a1f8ced7779eafcfe6b8da466d0680", + "0xf90211a078ec3c13d353c11178ffa862501bf35e40e36bc86f396dac2e17602a0c747d5ba0d851ff649a0d78647807f486a934a35fc9e41ddbb64a09bbebbe205abd338ee8a019d1ce172e5a45e3dc0866eb071e38a13338ae6dbbfdc70aad3b2f82cc072f8fa062c437592bd2721d81a7197318c91b103c6d568a9746d3a1c806ed6370271fc1a056507388b75afefff70474a547d48d53ebe1eff4916af8a712fbd012d9b6c07ca05038b123df05284a4aa84e4f1bea52da64b7d3ee155817580901846606963669a032547a9a4c4c0a8300ae1620f6d5a2ea1a6b2e3e27f642260e132cf2ebf2a98ca03a46dd79b41568b2c53bf2889b4fdc5b6d454ddafaeb1f5abb2d3e010f39443fa04c98fa07640c08f77e2830d4053b2bc10346486216d7c5a6010f5c2c40665a67a06f3b8df2ce37cd2c596caf3750bfb7019091c29037edf66cae2cdfc273e567bda0e4b49398795c71b86a8dd3944953427e14d6e5e427ca0fde443e4505b9e2b9b8a06547bdf50b77d8ca8a059f8f96f10c89626b3fb4a99f944f596175a2f88de4d8a0f4558270c5aa5669fcc36424e4fc85758f41a17b9b1f0c3aa316488c5fcbc669a02778702c7a3769967dd42e639e24828de01ca11f47bd648fc4e0695b645fb469a009a0263ae6917980edc3950ea0e403ea36abed481a2da0f6d3de028af5b48029a004851336aece6f248c375b386aacf154b033caa45a2d35611ff11e0a53d8798480", + "0xf8b1a09210595a62367dd0b3e8d43c941192fc5a916469c0a9b24517fb66d71ebd5a16808080808080a025ffe43610f734105480952603c8f0355e1b2ab509c66855ddd0cee3a332cc2880a0a6a4c159ee14e6e3a86df23d83bda0d84d1d061080c95e6cbbd0fe40024a3919808080a0eb0c333ce277240253bbf0fd22337c556342f58ba89503ac9cfdbc5de3facfff80a0f9589bb8289e455a36f1435e4612fbd1fee38851f0d8eae90da6f9122eaf51b280", + "0xf8719d3e9a3e589d5f55bf39fc2428b31e3ec8ffcb7107dd2d1c5503fa1bdfb8b851f84f018b08e9358ffc243096c55045a0c1917a80cb25ccc50d0d1921525a44fb619b4601194ca726ae32312f08a799f8a06c029a231254fadb724d63be769f75eedd66362df034a3e663252b49d062a666" + ], + "balance": "0x8e9358ffc243096c55045", + "codeHash": "0x6c029a231254fadb724d63be769f75eedd66362df034a3e663252b49d062a666", + "nonce": "0x1", + "storageHash": "0xc1917a80cb25ccc50d0d1921525a44fb619b4601194ca726ae32312f08a799f8" + }` + var result AccountResult + err = json.Unmarshal([]byte(resultTestData), &result) + assert.NoError(t, err) + + l2Client := &mockL2Client{ + head: &header, + result: &result, + } + + addr := common.HexToAddress("0x00000000219ab540356cBB839Cbe05303d7705Fa") + server, err := newRPCServer(context.Background(), "localhost", 0, l2Client, addr, log, "0.0") + assert.NoError(t, err) + assert.NoError(t, server.Start()) + defer server.Stop() + + client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) + assert.NoError(t, err) + + var out []l2.Bytes32 + err = client.CallContext(context.Background(), &out, "optimism_outputAtBlock", "latest") + assert.NoError(t, err) + assert.Len(t, out, 2) +} + +type mockL2Client struct { + head *types.Header + result *AccountResult +} + +func (c *mockL2Client) GetBlockHeader(ctx context.Context, blockTag string) (*types.Header, error) { + return c.head, nil +} + +func (c *mockL2Client) GetProof(ctx context.Context, address common.Address, blockTag string) (*AccountResult, error) { + return c.result, nil +} diff --git a/opnode/node/util.go b/opnode/node/util.go new file mode 100644 index 000000000000..b50bfcfcadee --- /dev/null +++ b/opnode/node/util.go @@ -0,0 +1,78 @@ +package node + +import ( + "bytes" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/ethdb/memorydb" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rlp" + + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/trie" +) + +func ComputeL2OutputRoot(l2OutputRootVersion l2.Bytes32, blockHash common.Hash, blockRoot common.Hash, storageRoot common.Hash) l2.Bytes32 { + var buf bytes.Buffer + buf.Write(l2OutputRootVersion[:]) + buf.Write(blockRoot.Bytes()) + buf.Write(storageRoot[:]) + buf.Write(blockHash.Bytes()) + return l2.Bytes32(crypto.Keccak256Hash(buf.Bytes())) +} + +type AccountResult struct { + AccountProof []hexutil.Bytes `json:"accountProof"` + + Address common.Address `json:"address"` + Balance *hexutil.Big `json:"balance"` + CodeHash common.Hash `json:"codeHash"` + Nonce hexutil.Uint64 `json:"nonce"` + StorageHash common.Hash `json:"storageHash"` + // storageProof field is ignored, we only need to proof the account contents, + // we do not access any individual storage values. +} + +// Verify an account proof from the getProof RPC. See https://eips.ethereum.org/EIPS/eip-1186 +func (res *AccountResult) Verify(stateRoot common.Hash) error { + accountClaimed := []interface{}{uint64(res.Nonce), (*big.Int)(res.Balance).Bytes(), res.StorageHash, res.CodeHash} + accountClaimedValue, err := rlp.EncodeToBytes(accountClaimed) + if err != nil { + return fmt.Errorf("failed to encode account from retrieved values: %v", err) + } + + // create a db with all trie nodes + db := memorydb.New() + for i, encodedNode := range res.AccountProof { + nodeKey := crypto.Keccak256(encodedNode) + if err := db.Put(nodeKey, encodedNode); err != nil { + return fmt.Errorf("failed to load proof value %d into mem db: %v", i, err) + } + } + + key := crypto.Keccak256Hash(res.Address[:]) + trieDB := trie.NewDatabase(db) + + // wrap our DB of trie nodes with a Trie interface, and anchor it at the trusted state root + proofTrie, err := trie.New(stateRoot, trieDB) + if err != nil { + return fmt.Errorf("failed to load db wrapper around kv store") + } + + // now get the full value from the account proof, and check that it matches the JSON contents + accountProofValue, err := proofTrie.TryGet(key[:]) + if err != nil { + return fmt.Errorf("failed to retrieve account value: %v", err) + } + + if !bytes.Equal(accountClaimedValue, accountProofValue) { + return fmt.Errorf("L1 RPC is tricking us, account proof does not match provided deserialized values:\n"+ + " claimed: %x\n"+ + " proof: %x", accountClaimedValue, accountProofValue) + } + return err +} diff --git a/opnode/predeploys.go b/opnode/predeploys.go new file mode 100644 index 000000000000..3ab61c47e034 --- /dev/null +++ b/opnode/predeploys.go @@ -0,0 +1,5 @@ +package opnode + +import "github.com/ethereum/go-ethereum/common" + +var WithdrawalContractAddress = common.HexToAddress("0x4200000000000000000000000000000000000015") diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index d6dbdf26ed50..7686b63965da 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -95,7 +95,7 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa // An incomplete sequencing window will result in an incomplete L2 chain if so. // // After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. -func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (out eth.BlockID, err error) { +func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.BlockID, error) { // Sanity Checks if len(l1Input) == 0 { return l2Head, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Head) diff --git a/opnode/service.go b/opnode/service.go index 12fd6dcfd5d5..ca1f3e3fdc84 100644 --- a/opnode/service.go +++ b/opnode/service.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/flags" "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/urfave/cli" ) @@ -38,12 +39,21 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) { } } + withdrawalContractAddress := WithdrawalContractAddress + if value := ctx.GlobalString(flags.WithdrawalContractAddr.Name); value != "" { + withdrawalContractAddress = common.HexToAddress(value) + } + cfg := &node.Config{ - L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), - L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), - Rollup: *rollupConfig, - Sequencer: enableSequencing, - SubmitterPrivKey: batchSubmitterKey, + L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), + L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), + L2NodeAddr: ctx.GlobalString(flags.L2EthNodeAddr.Name), + Rollup: *rollupConfig, + Sequencer: enableSequencing, + SubmitterPrivKey: batchSubmitterKey, + RPCListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name), + RPCListenPort: ctx.GlobalInt(flags.RPCListenPort.Name), + WithdrawalContractAddr: withdrawalContractAddress, } if err := cfg.Check(); err != nil { return nil, err diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 710db9c0bbc4..23d404fbb611 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -160,6 +160,7 @@ func TestSystemE2E(t *testing.T) { nodeCfg := &rollupNode.Config{ L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2Verifier.nodeConfig)}, + L2NodeAddr: endpoint(cfg.l2Verifier.nodeConfig), Rollup: rollup.Config{ Genesis: rollup.Genesis{ L1: l1GenesisID, @@ -176,7 +177,7 @@ func TestSystemE2E(t *testing.T) { BatchSenderAddress: submitterAddress, }, } - node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlError)) + node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlError), "") require.Nil(t, err) err = node.Start(context.Background()) @@ -187,6 +188,7 @@ func TestSystemE2E(t *testing.T) { sequenceCfg := &rollupNode.Config{ L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2Sequencer.nodeConfig)}, + L2NodeAddr: endpoint(cfg.l2Verifier.nodeConfig), Rollup: rollup.Config{ Genesis: rollup.Genesis{ L1: l1GenesisID, @@ -205,7 +207,7 @@ func TestSystemE2E(t *testing.T) { Sequencer: true, SubmitterPrivKey: bssPrivKey, } - sequencer, err := rollupNode.New(context.Background(), sequenceCfg, testlog.Logger(t, log.LvlError)) + sequencer, err := rollupNode.New(context.Background(), sequenceCfg, testlog.Logger(t, log.LvlError), "") require.Nil(t, err) err = sequencer.Start(context.Background()) diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index bc130d85c9f1..c1d366627da2 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -34,6 +34,8 @@ services: build: context: ../ dockerfile: ./ops/Dockerfile.opnode + ports: + - "7545:8545" volumes: - ${PWD}/bss-key.txt:/config/bss-key.txt - ${PWD}/rollup.json:/config/rollup.json @@ -47,4 +49,10 @@ services: - "--rollup.config" - "/config/rollup.json" - "--batchsubmitter.key" - - "/config/bss-key.txt" \ No newline at end of file + - "/config/bss-key.txt" + - "--l2.eth" + - "http://l2:8545" + - "--rpc.addr" + - "0.0.0.0" + - "--rpc.port" + - "8545" From 9bfa248e1d3a1da78bd488643a1cfeb82dd539f2 Mon Sep 17 00:00:00 2001 From: inphi Date: Tue, 29 Mar 2022 09:15:26 -0400 Subject: [PATCH 358/585] l2os: Submit l2 output root via opnode --- l2os/config.go | 4 ++++ l2os/drivers/l2output/driver.go | 40 +++++++++++++++++++++++---------- l2os/flags/flags.go | 7 ++++++ l2os/l2_output_submitter.go | 29 +++++++++++++++++++----- opnode/test/system_test.go | 16 +++++++++++-- 5 files changed, 76 insertions(+), 20 deletions(-) diff --git a/l2os/config.go b/l2os/config.go index 78ec5a61e367..20dd9c2c742c 100644 --- a/l2os/config.go +++ b/l2os/config.go @@ -17,6 +17,9 @@ type Config struct { // L2EthRpc is the HTTP provider URL for L1. L2EthRpc string + // RollupRpc is the HTTP provider URL for the rollup node. + RollupRpc string + // L2OOAddress is the L2OutputOracle contract address. L2OOAddress string @@ -58,6 +61,7 @@ func NewConfig(ctx *cli.Context) Config { /* Required Flags */ L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name), L2EthRpc: ctx.GlobalString(flags.L2EthRpcFlag.Name), + RollupRpc: ctx.GlobalString(flags.RollupRpc.Name), L2OOAddress: ctx.GlobalString(flags.L2OOAddressFlag.Name), PollInterval: ctx.GlobalDuration(flags.PollIntervalFlag.Name), NumConfirmations: ctx.GlobalUint64(flags.NumConfirmationsFlag.Name), diff --git a/l2os/drivers/l2output/driver.go b/l2os/drivers/l2output/driver.go index 3a782fece72e..fb49dd1ff34c 100644 --- a/l2os/drivers/l2output/driver.go +++ b/l2os/drivers/l2output/driver.go @@ -8,24 +8,29 @@ import ( "strings" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" ) var bigOne = big.NewInt(1) +var supportedL2OutputVersion = l2.Bytes32{} type Config struct { - Name string - L1Client *ethclient.Client - L2Client *ethclient.Client - L2OOAddr common.Address - ChainID *big.Int - PrivKey *ecdsa.PrivateKey + Name string + L1Client *ethclient.Client + L2Client *ethclient.Client + RollupClient *rpc.Client + L2OOAddr common.Address + ChainID *big.Int + PrivKey *ecdsa.PrivateKey } type Driver struct { @@ -160,9 +165,8 @@ func (d *Driver) CraftTx( // Fetch the final block in the range, as this is the only L2 output we need // to submit. nextCheckpointBlock := new(big.Int).Sub(end, bigOne) - checkpointBlock, err := d.cfg.L2Client.HeaderByNumber( - ctx, nextCheckpointBlock, - ) + + l2OutputRoot, err := d.outputRootAtBlock(ctx, nextCheckpointBlock) if err != nil { return nil, err } @@ -205,9 +209,7 @@ func (d *Driver) CraftTx( opts.Nonce = nonce opts.NoSend = true - return d.l2ooContract.AppendL2Output( - opts, checkpointBlock.Root, timestamp, - ) + return d.l2ooContract.AppendL2Output(opts, l2OutputRoot, timestamp) } // UpdateGasPrice signs an otherwise identical txn to the one provided but with @@ -241,3 +243,17 @@ func (d *Driver) SendTransaction( return d.cfg.L1Client.SendTransaction(ctx, tx) } + +func (d *Driver) outputRootAtBlock(ctx context.Context, blockNum *big.Int) (l2.Bytes32, error) { + var output []l2.Bytes32 + if err := d.cfg.RollupClient.CallContext(ctx, &output, "optimism_outputAtBlock", hexutil.EncodeBig(blockNum)); err != nil { + return l2.Bytes32{}, err + } + if len(output) != 2 { + return l2.Bytes32{}, fmt.Errorf("invalid outputAtBlock response") + } + if version := output[0]; version != supportedL2OutputVersion { + return l2.Bytes32{}, fmt.Errorf("unsupported l2 output version") + } + return output[1], nil +} diff --git a/l2os/flags/flags.go b/l2os/flags/flags.go index 5a5a927415bd..8a8a7bab0485 100644 --- a/l2os/flags/flags.go +++ b/l2os/flags/flags.go @@ -25,6 +25,12 @@ var ( Required: true, EnvVar: "L2_ETH_RPC", } + RollupRpc = cli.StringFlag{ + Name: "rollup-rpc", + Usage: "HTTP provider URL for the rollup node", + Required: true, + EnvVar: "ROLLUP_RPC", + } L2OOAddressFlag = cli.StringFlag{ Name: "l2oo-address", Usage: "Address of the L2OutputOracle contract", @@ -88,6 +94,7 @@ var ( var requiredFlags = []cli.Flag{ L1EthRpcFlag, L2EthRpcFlag, + RollupRpc, L2OOAddressFlag, PollIntervalFlag, NumConfirmationsFlag, diff --git a/l2os/l2_output_submitter.go b/l2os/l2_output_submitter.go index 191020d36a44..2463f6f48317 100644 --- a/l2os/l2_output_submitter.go +++ b/l2os/l2_output_submitter.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" hdwallet "github.com/miguelmota/go-ethereum-hdwallet" "github.com/urfave/cli" ) @@ -117,6 +118,11 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er return nil, err } + rollupClient, err := dialRpcClientWithTimeout(ctx, cfg.RollupRpc) + if err != nil { + return nil, err + } + chainID, err := l1Client.ChainID(ctx) if err != nil { return nil, err @@ -130,12 +136,13 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er } l2OutputDriver, err := l2output.NewDriver(l2output.Config{ - Name: "L2Output Submitter", - L1Client: l1Client, - L2Client: l2Client, - L2OOAddr: l2ooAddress, - ChainID: chainID, - PrivKey: l2OutputPrivKey, + Name: "L2Output Submitter", + L1Client: l1Client, + L2Client: l2Client, + RollupClient: rollupClient, + L2OOAddr: l2ooAddress, + ChainID: chainID, + PrivKey: l2OutputPrivKey, }) if err != nil { return nil, err @@ -175,6 +182,16 @@ func dialEthClientWithTimeout(ctx context.Context, url string) ( return ethclient.DialContext(ctxt, url) } +// dialRpcClientWithTimeout attempts to dial the RPC provider using the provided +// URL. If the dial doesn't complete within defaultDialTimeout seconds, this +// method will return an error. +func dialRpcClientWithTimeout(ctx context.Context, url string) (*rpc.Client, error) { + ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) + defer cancel() + + return rpc.DialContext(ctxt, url) +} + // parseAddress parses an ETH address from a hex string. This method will fail if // the address is not a valid hexadecimal address. func parseAddress(address string) (common.Address, error) { diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 23d404fbb611..9e3078ce3aa6 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" @@ -23,12 +24,14 @@ import ( "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" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" ) @@ -206,6 +209,8 @@ func TestSystemE2E(t *testing.T) { }, Sequencer: true, SubmitterPrivKey: bssPrivKey, + RPCListenAddr: "127.0.0.1", + RPCListenPort: 9093, } sequencer, err := rollupNode.New(context.Background(), sequenceCfg, testlog.Logger(t, log.LvlError), "") require.Nil(t, err) @@ -214,6 +219,9 @@ func TestSystemE2E(t *testing.T) { require.Nil(t, err) defer sequencer.Stop() + rollupClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", sequenceCfg.RPCListenAddr, sequenceCfg.RPCListenPort)) + require.Nil(t, err) + // Deploy StateRootOracle l2OutputPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ URL: accounts.URL{ @@ -253,6 +261,7 @@ func TestSystemE2E(t *testing.T) { l2OutputSubmitter, err := l2os.NewL2OutputSubmitter(l2os.Config{ L1EthRpc: endpoint(cfg.l1.nodeConfig), L2EthRpc: endpoint(cfg.l2Verifier.nodeConfig), + RollupRpc: fmt.Sprintf("http://%s:%d", sequenceCfg.RPCListenAddr, sequenceCfg.RPCListenPort), L2OOAddress: l2ooAddr.String(), PollInterval: 5 * time.Second, NumConfirmations: 1, @@ -374,9 +383,12 @@ loop: // finalized. ctx, cancel = context.WithTimeout(context.Background(), time.Second) defer cancel() - l2Block, err := l2Client.BlockByNumber(ctx, l2ooBlockNumber) + var l2Output []l2.Bytes32 + err = rollupClient.CallContext(ctx, &l2Output, "optimism_outputAtBlock", hexutil.EncodeBig(l2ooBlockNumber)) require.Nil(t, err) - require.Equal(t, l2Block.Root(), common.Hash(committedL2Output)) + require.Len(t, l2Output, 2) + + require.Equal(t, l2Output[1][:], committedL2Output[:]) break } From 383f45ef3c23f281286ba615e27156144f9a0916 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 29 Mar 2022 10:38:26 -0700 Subject: [PATCH 359/585] opnode: New blockref format (#285) * opnode: Switch to BlockRefs in state loop This removes having to separately keep track of L1Origin and L1Base. This is nice because those name are confusing and separately used and it means less information to keep track of. * opnode: Restructure Block References This flattens the Block ID fields and adds a time field to the Block References. The time field is important for sequencing. It needs to be in the BlockRef instead of the BlockID because it is hard to reliably fill out the timestamp field for Parent and L1Origin block ids. This approach also removes the ParentNumber because it can be easily calculated if needed, but was not being used. --- opnode/eth/heads.go | 14 ++--- opnode/eth/id.go | 60 +++++++++++++++++--- opnode/l1/source.go | 26 ++++----- opnode/l2/api.go | 65 +++++++++++++++++----- opnode/node/node.go | 2 +- opnode/rollup/derive/invert.go | 23 +++++--- opnode/rollup/driver/driver.go | 4 +- opnode/rollup/driver/fake_chain.go | 15 +++-- opnode/rollup/driver/state.go | 88 ++++++++++++++++-------------- opnode/rollup/driver/state_test.go | 22 ++++---- opnode/rollup/driver/step.go | 26 ++++++--- opnode/rollup/sync/start.go | 8 +-- opnode/rollup/sync/start_test.go | 18 +++--- 13 files changed, 238 insertions(+), 133 deletions(-) diff --git a/opnode/eth/heads.go b/opnode/eth/heads.go index d9c6ad2b35de..ee76dcb973bb 100644 --- a/opnode/eth/heads.go +++ b/opnode/eth/heads.go @@ -27,14 +27,12 @@ func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) ( for { select { case header := <-headChanges: - hash := header.Hash() - height := header.Number.Uint64() - self := BlockID{Hash: hash, Number: height} - parent := BlockID{} - if height > 0 { - parent = BlockID{Hash: header.ParentHash, Number: height - 1} - } - fn(L1BlockRef{Parent: parent, Self: self}) + fn(L1BlockRef{ + Hash: header.Hash(), + Number: header.Number.Uint64(), + ParentHash: header.ParentHash, + Time: header.Time, + }) case err := <-sub.Err(): return err case <-ctx.Done(): diff --git a/opnode/eth/id.go b/opnode/eth/id.go index 44d48ddf4e83..eb1707f585ce 100644 --- a/opnode/eth/id.go +++ b/opnode/eth/id.go @@ -22,32 +22,74 @@ func (id BlockID) TerminalString() string { } type L2BlockRef struct { - Self BlockID `json:"self"` - Parent BlockID `json:"parent"` - L1Origin BlockID `json:"l1_origin"` + Hash common.Hash `json:"hash"` + Number uint64 `json:"number"` + ParentHash common.Hash `json:"parentHash"` + Time uint64 `json:"timestamp"` + L1Origin BlockID `json:"l1origin"` } func (id L2BlockRef) String() string { - return fmt.Sprintf("%s:%d", id.Self.Hash.String(), id.Self.Number) + return fmt.Sprintf("%s:%d", id.Hash.String(), id.Number) } // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. func (id L2BlockRef) TerminalString() string { - return fmt.Sprintf("%s:%d", id.Self.Hash.TerminalString(), id.Self.Number) + return fmt.Sprintf("%s:%d", id.Hash.TerminalString(), id.Number) } type L1BlockRef struct { - Self BlockID `json:"self"` - Parent BlockID `json:"parent"` + Hash common.Hash `json:"hash"` + Number uint64 `json:"number"` + ParentHash common.Hash `json:"parentHash"` + Time uint64 `json:"timestamp"` } func (id L1BlockRef) String() string { - return fmt.Sprintf("%s:%d", id.Self.Hash.String(), id.Self.Number) + return fmt.Sprintf("%s:%d", id.Hash.String(), id.Number) } // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. func (id L1BlockRef) TerminalString() string { - return fmt.Sprintf("%s:%d", id.Self.Hash.TerminalString(), id.Self.Number) + return fmt.Sprintf("%s:%d", id.Hash.TerminalString(), id.Number) +} + +func (id L1BlockRef) ID() BlockID { + return BlockID{ + Hash: id.Hash, + Number: id.Number, + } +} + +func (id L1BlockRef) ParentID() BlockID { + n := id.ID().Number + // Saturate at 0 with subtraction + if n > 0 { + n -= 1 + } + return BlockID{ + Hash: id.ParentHash, + Number: n, + } +} + +func (id L2BlockRef) ID() BlockID { + return BlockID{ + Hash: id.Hash, + Number: id.Number, + } +} + +func (id L2BlockRef) ParentID() BlockID { + n := id.ID().Number + // Saturate at 0 with subtraction + if n > 0 { + n -= 1 + } + return BlockID{ + Hash: id.ParentHash, + Number: n, + } } diff --git a/opnode/l1/source.go b/opnode/l1/source.go index e40bc2ade487..f5e69268fdfc 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -108,14 +108,12 @@ func (s Source) l1BlockRefByNumber(ctx context.Context, number *big.Int) (eth.L1 // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. return eth.L1BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", number, err) } - l1Num := header.Number.Uint64() - parentNum := l1Num - if parentNum > 0 { - parentNum -= 1 - } + return eth.L1BlockRef{ - Self: eth.BlockID{Hash: header.Hash(), Number: l1Num}, - Parent: eth.BlockID{Hash: header.ParentHash, Number: parentNum}, + Hash: header.Hash(), + Number: header.Number.Uint64(), + ParentHash: header.ParentHash, + Time: header.Time, }, nil } @@ -125,8 +123,8 @@ func (s Source) L1Range(ctx context.Context, begin eth.BlockID) ([]eth.BlockID, if canonicalBegin, err := s.L1BlockRefByNumber(ctx, begin.Number); err != nil { return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) } else { - if canonicalBegin.Self != begin { - return nil, fmt.Errorf("Re-org at begin block. Expected: %v. Actual: %v", begin, canonicalBegin.Self) + if canonicalBegin.Hash != begin.Hash { + return nil, fmt.Errorf("Re-org at begin block. Expected: %v. Actual: %v", begin, canonicalBegin) } } @@ -136,8 +134,8 @@ func (s Source) L1Range(ctx context.Context, begin eth.BlockID) ([]eth.BlockID, } maxBlocks := MaxBlocksInL1Range // Cap maxBlocks if there are less than maxBlocks between `begin` and the head of the chain. - if l1head.Self.Number-begin.Number <= maxBlocks { - maxBlocks = l1head.Self.Number - begin.Number + if l1head.Number-begin.Number <= maxBlocks { + maxBlocks = l1head.Number - begin.Number } if maxBlocks == 0 { @@ -153,11 +151,11 @@ func (s Source) L1Range(ctx context.Context, begin eth.BlockID) ([]eth.BlockID, return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) } // TODO(Joshua): Look into why this fails around the genesis block - if n.Parent.Number != 0 && n.Parent.Hash != prevHash { + if n.Number != 1 && n.ParentHash != prevHash { return nil, errors.New("re-organization occurred while attempting to get l1 range") } - prevHash = n.Self.Hash - res = append(res, n.Self) + prevHash = n.Hash + res = append(res, n.ID()) } return res, nil diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 06f4d4f03bbb..3acc0843540e 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" ) @@ -88,28 +89,64 @@ type Data = hexutil.Bytes type PayloadID = hexutil.Bytes type ExecutionPayload struct { - ParentHash common.Hash `json:"parentHash"` - FeeRecipient common.Address `json:"feeRecipient"` - StateRoot Bytes32 `json:"stateRoot"` - ReceiptsRoot Bytes32 `json:"receiptsRoot"` - LogsBloom Bytes256 `json:"logsBloom"` - Random Bytes32 `json:"random"` - BlockNumber Uint64Quantity `json:"blockNumber"` - GasLimit Uint64Quantity `json:"gasLimit"` - GasUsed Uint64Quantity `json:"gasUsed"` - Timestamp Uint64Quantity `json:"timestamp"` - ExtraData BytesMax32 `json:"extraData"` - BaseFeePerGas Uint256Quantity `json:"baseFeePerGas"` - BlockHash common.Hash `json:"blockHash"` + ParentHashField common.Hash `json:"parentHash"` + FeeRecipient common.Address `json:"feeRecipient"` + StateRoot Bytes32 `json:"stateRoot"` + ReceiptsRoot Bytes32 `json:"receiptsRoot"` + LogsBloom Bytes256 `json:"logsBloom"` + Random Bytes32 `json:"random"` + BlockNumber Uint64Quantity `json:"blockNumber"` + GasLimit Uint64Quantity `json:"gasLimit"` + GasUsed Uint64Quantity `json:"gasUsed"` + Timestamp Uint64Quantity `json:"timestamp"` + ExtraData BytesMax32 `json:"extraData"` + BaseFeePerGas Uint256Quantity `json:"baseFeePerGas"` + BlockHash common.Hash `json:"blockHash"` // Array of transaction objects, each object is a byte list (DATA) representing // TransactionType || TransactionPayload or LegacyTransaction as defined in EIP-2718 - Transactions []Data `json:"transactions"` + TransactionsField []Data `json:"transactions"` } func (payload *ExecutionPayload) ID() eth.BlockID { return eth.BlockID{Hash: payload.BlockHash, Number: uint64(payload.BlockNumber)} } +// Implement block interface to enable derive.BlockReferences over a payload +// type Block interface { +// Hash() common.Hash +// NumberU64() uint64 +// ParentHash() common.Hash +// Transactions() types.Transactions +// } + +func (payload *ExecutionPayload) Hash() common.Hash { + return payload.BlockHash +} + +func (payload *ExecutionPayload) NumberU64() uint64 { + return uint64(payload.BlockNumber) +} + +func (payload *ExecutionPayload) Time() uint64 { + return uint64(payload.Timestamp) +} + +func (payload *ExecutionPayload) ParentHash() common.Hash { + return payload.ParentHashField +} + +func (payload *ExecutionPayload) Transactions() types.Transactions { + res := make([]*types.Transaction, len(payload.TransactionsField)) + for i, t := range payload.TransactionsField { + res[i] = new(types.Transaction) + err := res[i].UnmarshalBinary(t) + if err != nil { + panic(err) + } + } + return res +} + type PayloadAttributes struct { // value for the timestamp field of the new payload Timestamp Uint64Quantity `json:"timestamp"` diff --git a/opnode/node/node.go b/opnode/node/node.go index 21da16db66e9..cecba41df519 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -172,7 +172,7 @@ func (c *OpNode) Start(ctx context.Context) error { for { select { case l1Head := <-l1Heads: - c.log.Info("New L1 head", "head", l1Head.Self, "parent", l1Head.Parent) + c.log.Info("New L1 head", "head", l1Head, "parent", l1Head.ParentHash) // TODO: maybe log other info on interval or other chain events (individual engines also log things) case <-c.done: c.log.Info("Closing OpNode") diff --git a/opnode/rollup/derive/invert.go b/opnode/rollup/derive/invert.go index 58c1b01a729d..b17a79270265 100644 --- a/opnode/rollup/derive/invert.go +++ b/opnode/rollup/derive/invert.go @@ -33,19 +33,25 @@ type Block interface { NumberU64() uint64 ParentHash() common.Hash Transactions() types.Transactions + Time() uint64 } // BlockReferences takes a L2 block and determines which L1 block it was derived from, its L2 parent id, and its own id. func BlockReferences(l2Block Block, genesis *rollup.Genesis) (eth.L2BlockRef, error) { - self := eth.BlockID{Hash: l2Block.Hash(), Number: l2Block.NumberU64()} - if self.Number <= genesis.L2.Number { - if self.Hash != genesis.L2.Hash { - return eth.L2BlockRef{}, fmt.Errorf("unexpected L2 genesis block: %s, expected %s", self, genesis.L2) - } - return eth.L2BlockRef{Self: self, L1Origin: genesis.L1}, nil + id := eth.L2BlockRef{ + Hash: l2Block.Hash(), + Number: l2Block.NumberU64(), + ParentHash: l2Block.ParentHash(), + Time: l2Block.Time(), } - l2Parent := eth.BlockID{Hash: l2Block.ParentHash(), Number: l2Block.NumberU64() - 1} + if id.Number <= genesis.L2.Number { + if id.Hash != genesis.L2.Hash { + return eth.L2BlockRef{}, fmt.Errorf("unexpected L2 genesis block: %s:%d, expected %s", id.Hash, id.Number, genesis.L2) + } + id.L1Origin = genesis.L1 + return id, nil + } txs := l2Block.Transactions() if len(txs) == 0 || txs[0].Type() != types.DepositTxType { @@ -55,5 +61,6 @@ func BlockReferences(l2Block Block, genesis *rollup.Genesis) (eth.L2BlockRef, er if err != nil { return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) } - return eth.L2BlockRef{Self: self, Parent: l2Parent, L1Origin: eth.BlockID{Hash: l1Hash, Number: l1Number}}, nil + id.L1Origin = eth.BlockID{Hash: l1Hash, Number: l1Number} + return id, nil } diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 8d363c3470c7..d4921df5158c 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -51,8 +51,8 @@ type L2Chain interface { } type outputInterface interface { - step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.BlockID, error) - newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) + step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) + newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.L2BlockRef, l2Safe eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) } func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index f95985151e66..0b83a2edd8cd 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -30,7 +30,8 @@ func fakeL1Block(self rune, parent rune, num uint64) eth.L1BlockRef { if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L1BlockRef{Self: fakeID(self, num), Parent: parentID} + id := fakeID(self, num) + return eth.L1BlockRef{Hash: id.Hash, Number: id.Number, ParentHash: parentID.Hash} } func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2BlockRef { @@ -38,7 +39,9 @@ func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L2BlockRef{Self: fakeID(self, num), Parent: parentID, L1Origin: l1parent} + id := fakeID(self, num) + + return eth.L2BlockRef{Hash: id.Hash, Number: id.Number, ParentHash: parentID.Hash, L1Origin: l1parent} } func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { @@ -53,7 +56,7 @@ func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { func chainL2(l1 []eth.L1BlockRef, ids string) (out []eth.L2BlockRef) { var prevID rune for i, id := range ids { - out = append(out, fakeL2Block(id, prevID, l1[i].Self, uint64(i))) + out = append(out, fakeL2Block(id, prevID, l1[i].ID(), uint64(i))) prevID = id } return @@ -93,9 +96,9 @@ func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID) ([]eth. found := false for i, b := range m.l1s[m.l1reorg] { if found { - out = append(out, b.Self) + out = append(out, b.ID()) } - if b.Self == base { + if b.ID() == base { found = true } if i == m.l1head { @@ -144,7 +147,7 @@ func (m *fakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { m.log.Trace("L2BlockRefByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.l2reorg) for i, bl := range m.l2s[m.l2reorg] { - if bl.Self.Hash == l2Hash { + if bl.Hash == l2Hash { return m.L2BlockRefByNumber(ctx, big.NewInt(int64(i))) } } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 74cd580673a2..d3eeebb1329c 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -13,13 +13,11 @@ import ( type state struct { // Chain State - l1Head eth.BlockID // Latest recorded head of the L1 Chain - l2Head eth.BlockID // L2 Unsafe Head - l1Origin eth.BlockID // L1 Origin of the L2 Unsafe head. For sequencing only. - l2SafeHead eth.BlockID // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) - l1Base eth.BlockID // L1 Parent of L2 Safe Head block - l2Finalized eth.BlockID // L2 Block that will never be reversed - l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. + l1Head eth.L1BlockRef // Latest recorded head of the L1 Chain + l2Head eth.L2BlockRef // L2 Unsafe Head + l2SafeHead eth.L2BlockRef // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) + l2Finalized eth.BlockID // L2 Block that will never be reversed + l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. // Rollup config Config rollup.Config @@ -59,12 +57,12 @@ func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error return err } - // TODO: Don't start everything from L2 heads - s.l1Head = l1Head.Self - s.l1Origin = s.l1Head - s.l2Head = l2Head.Self // TODO: Makes sense? - s.l2SafeHead = l2Head.Self - s.l1Base = l2Head.L1Origin + // TODO: + // 1. Pull safehead from sync-start algorithm + // 2. Check if heads are below genesis & if so, bump to genesis. + s.l1Head = l1Head + s.l2Head = l2Head + s.l2SafeHead = l2Head s.l1Heads = l1Heads go s.loop() @@ -80,7 +78,7 @@ func (s *state) Close() error { // This is either the last block of the window, or the L1 base block if the window is not populated. func (s *state) l1WindowEnd() eth.BlockID { if len(s.l1Window) == 0 { - return s.l1Base + return s.l2Head.L1Origin } return s.l1Window[len(s.l1Window)-1] } @@ -106,6 +104,19 @@ func (s *state) sequencingWindow() ([]eth.BlockID, bool) { return s.l1Window[:int(s.Config.SeqWindowSize)], true } +func (s *state) findNextL1Origin(ctx context.Context) (eth.BlockID, error) { + return s.l1Head.ID(), nil // Temporary until timestamps are working correctly + // [prev L2 + blocktime, L1 Bock) + // currentL1Origin := s.l2Head.L1Origin + // s.log.Info("Find next l1Origin", "l2Head", s.l2Head, "l1Origin", currentL1Origin) + // if s.l2Head.Time+int64(s.Config.BlockTime) >= currentL1Origin.Time { + // ref, err := s.l1.L1BlockRefByNumber(ctx, currentL1Origin.Number+1) + // s.log.Info("Lookuing up new L1 Origin", "nextL1Origin", ref) + // return ref.Self, err + // } + // return currentL1Origin, nil +} + func (s *state) loop() { s.log.Info("State loop started") ctx := context.Background() @@ -139,20 +150,18 @@ func (s *state) loop() { case <-s.done: return case <-l2BlockCreation: - // 1. Check if new epoch (new L1 head) - firstOfEpoch := false - if s.l1Head != s.l1Origin { - firstOfEpoch = true - s.l1Origin = s.l1Head + nextOrigin, err := s.findNextL1Origin(context.Background()) + if err != nil { + continue } // Don't produce blocks until past the L1 genesis - if s.l1Origin.Number <= s.Config.Genesis.L1.Number { + if nextOrigin.Number <= s.Config.Genesis.L1.Number { continue } // 2. Ask output to create new block - newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2Head, s.l2SafeHead, s.l1Origin, firstOfEpoch) + newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2Head, s.l2SafeHead.ID(), nextOrigin) if err != nil { - s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", s.l1Origin) + s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", nextOrigin) continue } // 3. Update unsafe l2 head + epoch @@ -167,41 +176,41 @@ func (s *state) loop() { }() case newL1Head := <-s.l1Heads: - s.log.Trace("Received new L1 Head", "new_head", newL1Head.Self, "old_head", s.l1Head) + s.log.Trace("Received new L1 Head", "new_head", newL1Head, "old_head", s.l1Head) // Check if we have a stutter step. May be due to a L1 Poll operation. - if s.l1Head == newL1Head.Self { - log.Trace("Received L1 head signal that is the same as the current head", "l1_head", newL1Head.Self) + if s.l1Head.Hash == newL1Head.Hash { + log.Trace("Received L1 head signal that is the same as the current head", "l1_head", newL1Head) continue } // Typically get linear extension, but if not, handle a re-org - if s.l1Head == newL1Head.Parent { + if s.l1Head.Hash == newL1Head.ParentHash { s.log.Trace("Linear extension") - s.l1Head = newL1Head.Self - if s.l1WindowEnd() == newL1Head.Parent { - s.l1Window = append(s.l1Window, newL1Head.Self) + s.l1Head = newL1Head + if s.l1WindowEnd().Hash == newL1Head.ParentHash { + s.l1Window = append(s.l1Window, newL1Head.ID()) } } else { - s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.Parent, "new_l1_head", newL1Head.Self) + s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.ParentHash, "new_l1_head", newL1Head) // TODO(Joshua): Fix having to make this call when being careful about the exact state l2Head, err := s.l2.L2BlockRefByNumber(context.Background(), nil) if err != nil { s.log.Error("Could not get fetch L2 head when trying to handle a re-org", "err", err) continue } - nextL2Head, err := sync.FindSafeL2Head(ctx, l2Head.Self, s.l1, s.l2, &s.Config.Genesis) + nextL2Head, err := sync.FindSafeL2Head(ctx, l2Head.ID(), s.l1, s.l2, &s.Config.Genesis) if err != nil { s.log.Error("Could not get new safe L2 head when trying to handle a re-org", "err", err) continue } - s.l1Head = newL1Head.Self - // TODO: Unsafe head here + s.l1Head = newL1Head s.l1Window = nil - s.l1Base = nextL2Head.L1Origin - s.l2SafeHead = nextL2Head.Self + s.l2Head = nextL2Head + s.l2SafeHead = nextL2Head // TODO: Handle this more carefully } + // Run step if we are able to - if s.l1Head.Number-s.l1Base.Number >= s.Config.SeqWindowSize { + if s.l1Head.Number-s.l2Head.L1Origin.Number >= s.Config.SeqWindowSize { requestStep() } case <-stepRequest: @@ -214,7 +223,7 @@ func (s *state) loop() { if len(s.l1Window) < int(s.Config.SeqWindowSize) { err := s.extendL1Window(context.Background()) if err != nil { - s.log.Error("Could not extend the cached L1 window", "err", err, "l1Head", s.l1Head, "l1Base", s.l1Base, "window_end", s.l1WindowEnd()) + s.log.Error("Could not extend the cached L1 window", "err", err, "l1Head", s.l1Head, "window_end", s.l1WindowEnd()) continue } } @@ -223,7 +232,7 @@ func (s *state) loop() { if window, ok := s.sequencingWindow(); ok { s.log.Trace("Have enough cached blocks to run step.") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - newL2Head, err := s.output.step(ctx, s.l2SafeHead, s.l2Finalized, s.l2Head, window) + newL2Head, err := s.output.step(ctx, s.l2SafeHead, s.l2Finalized, s.l2Head.ID(), window) cancel() if err != nil { s.log.Error("Error in running the output step.", "err", err, "l2SafeHead", s.l2SafeHead, "l2Finalized", s.l2Finalized, "window", window) @@ -233,7 +242,6 @@ func (s *state) loop() { s.l2Head = newL2Head } s.l2SafeHead = newL2Head - s.l1Base = s.l1Window[0] s.l1Window = s.l1Window[1:] // TODO: l2Finalized } else { @@ -241,7 +249,7 @@ func (s *state) loop() { } // Immediately run next step if we have enough blocks. - if s.l1Head.Number-s.l1Base.Number >= s.Config.SeqWindowSize { + if s.l1Head.Number-s.l2Head.L1Origin.Number >= s.Config.SeqWindowSize { requestStep() } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index b3848e476fab..a91b57a88914 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -38,13 +38,13 @@ func (id testID) ID() eth.BlockID { } } -type outputHandlerFn func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l2Unsafe eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) +type outputHandlerFn func(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) -func (fn outputHandlerFn) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l2Unsafe eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { - return fn(ctx, l2Head, l2Finalized, l2Unsafe, l1Window) +func (fn outputHandlerFn) step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) { + return fn(ctx, l2Head, l2Finalized, unsafeL2Head, l1Input) } -func (fn outputHandlerFn) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { +func (fn outputHandlerFn) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.L2BlockRef, l2Safe eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { panic("Unimplemented") } @@ -55,7 +55,7 @@ type outputArgs struct { } type outputReturnArgs struct { - l2Head eth.BlockID + l2Head eth.L2BlockRef err error } @@ -104,7 +104,7 @@ func advanceL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo for i := range expectedWindow { assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") } - outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1).Self, err: nil} + outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} } func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { @@ -115,7 +115,7 @@ func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") } src.reorgL2() - outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1).Self, err: nil} + outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} } type stateTestCase struct { @@ -134,8 +134,8 @@ func (tc *stateTestCase) Run(t *testing.T) { // Unbuffered channels to force a sync point between the test and the state loop. outputIn := make(chan outputArgs) outputReturn := make(chan outputReturnArgs) - outputHandler := func(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, l2Unsafe eth.BlockID, l1Window []eth.BlockID) (eth.BlockID, error) { - outputIn <- outputArgs{l2Head: l2Head, l2Finalized: l2Finalized, l1Window: l1Window} + outputHandler := func(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) { + outputIn <- outputArgs{l2Head: l2Head.ID(), l2Finalized: l2Finalized, l1Window: l1Input} r := <-outputReturn return r.l2Head, r.err } @@ -157,8 +157,8 @@ func (tc *stateTestCase) Run(t *testing.T) { step.l2act(t, step.window, state, chainSource, outputIn, outputReturn) <-time.After(5 * time.Millisecond) - assert.Equal(t, step.l1head.ID(), state.l1Head, "l1 head") - assert.Equal(t, step.l2head.ID(), state.l2SafeHead, "l2 head") + assert.Equal(t, step.l1head.ID(), state.l1Head.ID(), "l1 head") + assert.Equal(t, step.l2head.ID(), state.l2SafeHead.ID(), "l2 head") } } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 7686b63965da..0cfbd11bd961 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -23,14 +23,15 @@ type outputImpl struct { Config rollup.Config } -func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.BlockID, l2Safe eth.BlockID, l1Origin eth.BlockID, includeDeposits bool) (eth.BlockID, *derive.BatchData, error) { - d.log.Info("creating new block", "l2Parent", l2Parent, "l1Origin", l1Origin, "includeDeposits", includeDeposits) +func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.L2BlockRef, l2Safe eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { + d.log.Info("creating new block", "l2Parent", l2Parent) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() l2Info, err := d.l2.BlockByHash(fetchCtx, l2Parent.Hash) if err != nil { return l2Parent, nil, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Parent, err) } + l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Origin) if err != nil { return l2Parent, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) @@ -42,7 +43,12 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa } var receipts types.Receipts - if includeDeposits { + l2BLockRef, err := derive.BlockReferences(l2Info, &d.Config.Genesis) + if err != nil { + return l2Parent, nil, fmt.Errorf("failed to derive L2BlockRef from l2Block: %w", err) + } + // Include deposits if this is the first block of an epoch + if l2BLockRef.L1Origin.Number != l1Origin.Number { receipts, err = d.dl.FetchReceipts(fetchCtx, l1Origin, l1Info.ReceiptHash()) if err != nil { return l2Parent, nil, fmt.Errorf("failed to fetch receipts of %s: %v", l1Origin, err) @@ -84,18 +90,18 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa BatchV1: derive.BatchV1{ Epoch: rollup.Epoch(l1Info.NumberU64()), Timestamp: uint64(payload.Timestamp), - Transactions: payload.Transactions[depositStart:], + Transactions: payload.TransactionsField[depositStart:], }, } - - return payload.ID(), batch, nil + ref, err := derive.BlockReferences(payload, &d.Config.Genesis) + return ref, batch, err } // DriverStep derives and processes one or more L2 blocks from the given sequencing window of L1 blocks. // An incomplete sequencing window will result in an incomplete L2 chain if so. // // After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. -func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.BlockID, error) { +func (d *outputImpl) step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) { // Sanity Checks if len(l1Input) == 0 { return l2Head, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Head) @@ -174,7 +180,11 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.BlockID, l2Finalized e if err != nil { return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) } - last = payload.ID() + newLast, err := derive.BlockReferences(payload, &d.Config.Genesis) + if err != nil { + return last, fmt.Errorf("failed to derive block references: %w", err) + } + last = newLast // TODO(Joshua): Update this to handle verifiers + sequencers fc.HeadBlockHash = last.Hash fc.SafeBlockHash = last.Hash diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 1c245cf994c4..ba7ff7e5d64e 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -79,21 +79,21 @@ func FindSafeL2Head(ctx context.Context, start eth.BlockID, l1 L1Chain, l2 L2Cha // L1 block not found, keep walking chain } else { // L1 Block found, check if matches & should keep walking the chain - if l1header.Self.Hash == n.L1Origin.Hash { + if l1header.Hash == n.L1Origin.Hash { return n, nil } } // Don't walk past genesis. If we were at the L2 genesis, but could not find the L1 genesis // pointed to from it, we are on the wrong L1 chain. - if n.Self.Hash == genesis.L2.Hash || n.Self.Number == genesis.L2.Number { + if n.Hash == genesis.L2.Hash || n.Number == genesis.L2.Number { return eth.L2BlockRef{}, WrongChainErr } // Pull L2 parent for next iteration - n, err = l2.L2BlockRefByHash(ctx, n.Parent.Hash) + n, err = l2.L2BlockRefByHash(ctx, n.ParentHash) if err != nil { - return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.Parent.Hash, err) + return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) } reorgDepth++ if reorgDepth >= MaxReorgDepth { diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index c3364ce83354..d7cd55e14f78 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -23,9 +23,9 @@ func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID) ([]eth. found := false for _, b := range m.L1 { if found { - out = append(out, b.Self) + out = append(out, b.ID()) } - if b.Self == base { + if b.ID() == base { found = true } } @@ -63,7 +63,7 @@ func (m *fakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { for i, bl := range m.L2 { - if bl.Self.Hash == l2Hash { + if bl.Hash == l2Hash { return m.L2BlockRefByNumber(ctx, big.NewInt(int64(i))) } } @@ -84,7 +84,8 @@ func fakeL1Block(self rune, parent rune, num uint64) eth.L1BlockRef { if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L1BlockRef{Self: fakeID(self, num), Parent: parentID} + id := fakeID(self, num) + return eth.L1BlockRef{Hash: id.Hash, Number: id.Number, ParentHash: parentID.Hash} } func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2BlockRef { @@ -92,7 +93,8 @@ func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L if num != 0 { parentID = fakeID(parent, num-1) } - return eth.L2BlockRef{Self: fakeID(self, num), Parent: parentID, L1Origin: l1parent} + id := fakeID(self, num) + return eth.L2BlockRef{Hash: id.Hash, Number: id.Number, ParentHash: parentID.Hash, L1Origin: l1parent} } func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { @@ -107,7 +109,7 @@ func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { func chainL2(l1 []eth.L1BlockRef, ids string) (out []eth.L2BlockRef) { var prevID rune for i, id := range ids { - out = append(out, fakeL2Block(id, prevID, l1[i].Self, uint64(i))) + out = append(out, fakeL2Block(id, prevID, l1[i].ID(), uint64(i))) prevID = id } return @@ -150,7 +152,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { } head, err := msr.L2BlockRefByNumber(context.Background(), nil) require.Nil(t, err) - refL2, err := FindSafeL2Head(context.Background(), head.Self, msr, msr, genesis) + refL2, err := FindSafeL2Head(context.Background(), head.ID(), msr, msr, genesis) if c.ExpectedErr != nil { assert.Error(t, err, "Expecting an error in this test case") @@ -158,7 +160,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { } else { nextRefL1s, err := msr.L1Range(context.Background(), refL2.L1Origin) require.Nil(t, err) - expectedRefL2 := refToRune(refL2.Self) + expectedRefL2 := refToRune(refL2.ID()) var expectedRefsL1 []rune for _, ref := range nextRefL1s { expectedRefsL1 = append(expectedRefsL1, refToRune(ref)) From ae72864ae51d5d16024c73d6d19caa28bcfdf3b8 Mon Sep 17 00:00:00 2001 From: inphi Date: Tue, 29 Mar 2022 16:39:11 -0400 Subject: [PATCH 360/585] create rollupclient package; fix flag name --- l2os/config.go | 2 +- l2os/drivers/l2output/driver.go | 9 ++++----- l2os/flags/flags.go | 4 ++-- l2os/l2_output_submitter.go | 3 ++- l2os/rollupclient/rollupclient.go | 24 ++++++++++++++++++++++++ opnode/test/system_test.go | 9 ++++----- 6 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 l2os/rollupclient/rollupclient.go diff --git a/l2os/config.go b/l2os/config.go index 20dd9c2c742c..84f6efac2394 100644 --- a/l2os/config.go +++ b/l2os/config.go @@ -61,7 +61,7 @@ func NewConfig(ctx *cli.Context) Config { /* Required Flags */ L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name), L2EthRpc: ctx.GlobalString(flags.L2EthRpcFlag.Name), - RollupRpc: ctx.GlobalString(flags.RollupRpc.Name), + RollupRpc: ctx.GlobalString(flags.RollupRpcFlag.Name), L2OOAddress: ctx.GlobalString(flags.L2OOAddressFlag.Name), PollInterval: ctx.GlobalDuration(flags.PollIntervalFlag.Name), NumConfirmations: ctx.GlobalUint64(flags.NumConfirmationsFlag.Name), diff --git a/l2os/drivers/l2output/driver.go b/l2os/drivers/l2output/driver.go index fb49dd1ff34c..d22983d8d955 100644 --- a/l2os/drivers/l2output/driver.go +++ b/l2os/drivers/l2output/driver.go @@ -8,16 +8,15 @@ import ( "strings" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" + "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" ) var bigOne = big.NewInt(1) @@ -27,7 +26,7 @@ type Config struct { Name string L1Client *ethclient.Client L2Client *ethclient.Client - RollupClient *rpc.Client + RollupClient *rollupclient.RollupClient L2OOAddr common.Address ChainID *big.Int PrivKey *ecdsa.PrivateKey @@ -245,8 +244,8 @@ func (d *Driver) SendTransaction( } func (d *Driver) outputRootAtBlock(ctx context.Context, blockNum *big.Int) (l2.Bytes32, error) { - var output []l2.Bytes32 - if err := d.cfg.RollupClient.CallContext(ctx, &output, "optimism_outputAtBlock", hexutil.EncodeBig(blockNum)); err != nil { + output, err := d.cfg.RollupClient.OutputAtBlock(ctx, blockNum) + if err != nil { return l2.Bytes32{}, err } if len(output) != 2 { diff --git a/l2os/flags/flags.go b/l2os/flags/flags.go index 8a8a7bab0485..9db9631e585c 100644 --- a/l2os/flags/flags.go +++ b/l2os/flags/flags.go @@ -25,7 +25,7 @@ var ( Required: true, EnvVar: "L2_ETH_RPC", } - RollupRpc = cli.StringFlag{ + RollupRpcFlag = cli.StringFlag{ Name: "rollup-rpc", Usage: "HTTP provider URL for the rollup node", Required: true, @@ -94,7 +94,7 @@ var ( var requiredFlags = []cli.Flag{ L1EthRpcFlag, L2EthRpcFlag, - RollupRpc, + RollupRpcFlag, L2OOAddressFlag, PollIntervalFlag, NumConfirmationsFlag, diff --git a/l2os/l2_output_submitter.go b/l2os/l2_output_submitter.go index 2463f6f48317..fc32eaeba887 100644 --- a/l2os/l2_output_submitter.go +++ b/l2os/l2_output_submitter.go @@ -9,6 +9,7 @@ import ( "time" "github.com/ethereum-optimism/optimistic-specs/l2os/drivers/l2output" + "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" @@ -139,7 +140,7 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er Name: "L2Output Submitter", L1Client: l1Client, L2Client: l2Client, - RollupClient: rollupClient, + RollupClient: rollupclient.NewRollupClient(rollupClient), L2OOAddr: l2ooAddress, ChainID: chainID, PrivKey: l2OutputPrivKey, diff --git a/l2os/rollupclient/rollupclient.go b/l2os/rollupclient/rollupclient.go new file mode 100644 index 000000000000..3ee19ab1df91 --- /dev/null +++ b/l2os/rollupclient/rollupclient.go @@ -0,0 +1,24 @@ +package rollupclient + +import ( + "context" + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" +) + +type RollupClient struct { + rpc *rpc.Client +} + +func NewRollupClient(rpc *rpc.Client) *RollupClient { + return &RollupClient{rpc} +} + +func (r *RollupClient) OutputAtBlock(ctx context.Context, blockNum *big.Int) ([]l2.Bytes32, error) { + var output []l2.Bytes32 + err := r.rpc.CallContext(ctx, &output, "optimism_outputAtBlock", hexutil.EncodeBig(blockNum)) + return output, err +} diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 9e3078ce3aa6..bebb0f7209bc 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -9,10 +9,10 @@ import ( "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" + "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" @@ -24,7 +24,6 @@ import ( "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" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/ethconfig" @@ -219,8 +218,9 @@ func TestSystemE2E(t *testing.T) { require.Nil(t, err) defer sequencer.Stop() - rollupClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", sequenceCfg.RPCListenAddr, sequenceCfg.RPCListenPort)) + rollupRPCClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", sequenceCfg.RPCListenAddr, sequenceCfg.RPCListenPort)) require.Nil(t, err) + rollupClient := rollupclient.NewRollupClient(rollupRPCClient) // Deploy StateRootOracle l2OutputPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ @@ -383,8 +383,7 @@ loop: // finalized. ctx, cancel = context.WithTimeout(context.Background(), time.Second) defer cancel() - var l2Output []l2.Bytes32 - err = rollupClient.CallContext(ctx, &l2Output, "optimism_outputAtBlock", hexutil.EncodeBig(l2ooBlockNumber)) + l2Output, err := rollupClient.OutputAtBlock(ctx, l2ooBlockNumber) require.Nil(t, err) require.Len(t, l2Output, 2) From 95834ed431755f868cd93f016f420436fda38273 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 29 Mar 2022 15:55:19 -0600 Subject: [PATCH 361/585] Add devnet docs + deposit task (#269) * Add devnet docs + deposit task * Update Makefile Co-authored-by: Maurelian Co-authored-by: Maurelian --- .github/workflows/markdown-ci.yml | 2 +- Makefile | 4 +++ README.md | 33 +++++++++++++++++++ ops/docker-compose.yml | 4 +-- packages/contracts/hardhat.config.ts | 1 + packages/contracts/package.json | 2 +- packages/contracts/slither.db.json | 2 +- packages/contracts/tasks/deposits.ts | 47 ++++++++++++++++++++++++++++ packages/contracts/tsconfig.json | 3 +- packages/contracts/yarn.lock | 8 ++--- 10 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 packages/contracts/tasks/deposits.ts diff --git a/.github/workflows/markdown-ci.yml b/.github/workflows/markdown-ci.yml index 7d8645210ce8..4c5374bbbc29 100644 --- a/.github/workflows/markdown-ci.yml +++ b/.github/workflows/markdown-ci.yml @@ -53,5 +53,5 @@ jobs: - name: Link Checker uses: lycheeverse/lychee-action@v1.2.0 with: - args: --verbose --no-progress --exclude twitter.com --exclude-mail README.md "./specs/**/*.md" "./meta/**/*.md" "./opnode/**/*.md" + args: --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude-mail README.md "./specs/**/*.md" "./meta/**/*.md" "./opnode/**/*.md" fail: true diff --git a/Makefile b/Makefile index 4c07adf1b9d9..c53e204bfa6c 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,10 @@ opnode: go build -o ./bin/op ./opnode/cmd .PHONY: opnode +contracts: + cd ./packages/contracts && yarn build +.PHONY: contracts + clean: rm -rf ./bin .PHONY: clean diff --git a/README.md b/README.md index 6677d1791e84..010b11dbf040 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,39 @@ the `alpha` branch. Please note that this specification is currently under heavy construction. +## Local Devnet Setup + +You can spin up a local devnet via `docker-compose`. For convenence, we have defined `make` targets to start and stop the devnet with a single command. To run the devnet, you will need `docker` and `docker-compose` installed. Then, as a precondition, make sure that you have compiled the contracts by `cd`ing into `packages/contracts` and running `yarn` followed by `yarn build`. You'll only need to do this if you change the contracts in the future. + +Then, run the following: + +```bash +make devnet-up # starts the devnet +make devnet-down # stops the devnet +make devnet-clean # removes the devnet by deleting images and persistent volumes +``` + +L1 is accessible at `http://localhost:8545`, and L2 is accessible at `http://localhost:8546`. Any Ethereum tool - Metamask, `seth`, etc. - can use these endpoints. Note that you will need to specify the L2 chain ID manually if you use Metamask. The devnet's L2 chain ID is 901. + +The devnet comes with a pre-funded account you can use as a faucet: + +- Address: `0xde3829a23df1479438622a08a116e8eb3f620bb5` +- Private key: `bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7` + +The faucet account exists on both L1 and L2. To deposit onto L2 from L1, you can use the `deposit` hardhat task. Run the following from the `packags/contracts` directory: + +```bash +npx hardhat deposit --amount-eth --to
+```` + +You'll need a `.env` with the following contents: + +``` +L1_PROVIDER_URL=http://localhost:8545 +L2_PROVIDER_URL=http://localhost:8546 +PRIVATE_KEY=bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 +``` + ## Contributing ### Basic Contributions diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index c1d366627da2..36f48e9f8914 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -12,7 +12,7 @@ services: args: DEPOSIT_FEED_BYTECODE: $DEPOSIT_FEED_BYTECODE ports: - - "9545:8545" + - "8545:8545" volumes: - "l1_data:/db" @@ -23,7 +23,7 @@ services: args: L1_BLOCK_INFO_BYTECODE: $L1_BLOCK_INFO_BYTECODE ports: - - "8545:8545" + - "9545:8545" volumes: - "l2_data:/db" diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index b21653a8b4ae..7b79f2075c2e 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -3,6 +3,7 @@ import '@nomiclabs/hardhat-waffle' import '@typechain/hardhat' import 'hardhat-gas-reporter' import 'solidity-coverage' +import './tasks/deposits' task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { const accounts = await hre.ethers.getSigners() diff --git a/packages/contracts/package.json b/packages/contracts/package.json index c26f39d00217..5c584eee6869 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -37,7 +37,7 @@ "@typescript-eslint/eslint-plugin": "^4.29.1", "@typescript-eslint/parser": "^4.29.1", "chai": "^4.2.0", - "dotenv": "^10.0.0", + "dotenv": "^16.0.0", "eslint": "^7.29.0", "eslint-config-prettier": "^8.3.0", "eslint-config-standard": "^16.0.3", diff --git a/packages/contracts/slither.db.json b/packages/contracts/slither.db.json index 1ce4b1b35d52..877ba1a66143 100644 --- a/packages/contracts/slither.db.json +++ b/packages/contracts/slither.db.json @@ -1 +1 @@ -[{"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2866, "length": 1475, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 5187, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 3134, "length": 90, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [76], "starting_column": 9, "ending_column": 99}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2866, "length": 1475, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 5187, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}}}], "description": "L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256) (contracts/L1/L2OutputOracle.sol#69-98) uses a dangerous strict equality:\n\t- require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/L2OutputOracle.sol#76)\n", "markdown": "[L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256)](contracts/L1/L2OutputOracle.sol#L69-L98) uses a dangerous strict equality:\n\t- [require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/L2OutputOracle.sol#L76)\n", "first_markdown_element": "contracts/L1/L2OutputOracle.sol#L69-L98", "id": "6b3c4e2b8a4f6d93d3d999172ff1f3c665c26f908c4371ebfd6497f4da0bcae1", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2822, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4836, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 3090, "length": 90, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [75], "starting_column": 9, "ending_column": 99}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2822, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4836, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}}}], "description": "L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256) (contracts/L1/L2OutputOracle.sol#68-97) uses a dangerous strict equality:\n\t- require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/L2OutputOracle.sol#75)\n", "markdown": "[L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256)](contracts/L1/L2OutputOracle.sol#L68-L97) uses a dangerous strict equality:\n\t- [require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/L2OutputOracle.sol#L75)\n", "first_markdown_element": "contracts/L1/L2OutputOracle.sol#L68-L97", "id": "5d96abf0f353837ac9dd7491c5f9aa1c3d77a1eb32cd71c603e3a4235ed19e4c", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2764, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4778, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 3032, "length": 90, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [74], "starting_column": 9, "ending_column": 99}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 2764, "length": 1476, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L2OutputOracle", "source_mapping": {"start": 308, "length": 4778, "filename_used": "contracts/L1/L2OutputOracle.sol", "filename_relative": "contracts/L1/L2OutputOracle.sol", "filename_absolute": "contracts/L1/L2OutputOracle.sol", "filename_short": "contracts/L1/L2OutputOracle.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256,bytes32,uint256)"}}}}], "description": "L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256) (contracts/L1/L2OutputOracle.sol#67-96) uses a dangerous strict equality:\n\t- require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/L2OutputOracle.sol#74)\n", "markdown": "[L2OutputOracle.appendL2Output(bytes32,uint256,bytes32,uint256)](contracts/L1/L2OutputOracle.sol#L67-L96) uses a dangerous strict equality:\n\t- [require(bool,string)(_l2timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/L2OutputOracle.sol#L74)\n", "first_markdown_element": "contracts/L1/L2OutputOracle.sol#L67-L96", "id": "24228b71a4962875f71c3df68448d2aa61f627308da50eac1efcd59c2e55c440", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1102, "length": 648, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-59) has payable functions:\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#38-58)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L59) has payable functions:\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L38-L58)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "be013b000d4c176d4d893619bdca725d93e4761e4b2e22fa77a64144e53abb26", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 2010, "length": 88, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 97}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}}}], "description": "MockL2OutputOracle.appendL2Output(bytes32,uint256) (contracts/L1/MockL2OutputOracle.sol#45-51) uses a dangerous strict equality:\n\t- require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/MockL2OutputOracle.sol#48)\n", "markdown": "[MockL2OutputOracle.appendL2Output(bytes32,uint256)](contracts/L1/MockL2OutputOracle.sol#L45-L51) uses a dangerous strict equality:\n\t- [require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/MockL2OutputOracle.sol#L48)\n", "first_markdown_element": "contracts/L1/MockL2OutputOracle.sol#L45-L51", "id": "74ee9955ede80e105221045625f8b4f963a0ca8422674891166ad65bdcdba57a", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}, {"type": "node", "name": "OFFSET = uint160(0x1111000000000000000000000000000000001111)", "source_mapping": {"start": 284, "length": 85, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [14], "starting_column": 5, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}}}], "description": "DepositFeed.slitherConstructorConstantVariables() (contracts/L1/DepositFeed.sol#7-59) uses literals with too many digits:\n\t- OFFSET = uint160(0x1111000000000000000000000000000000001111) (contracts/L1/DepositFeed.sol#14)\n", "markdown": "[DepositFeed.slitherConstructorConstantVariables()](contracts/L1/DepositFeed.sol#L7-L59) uses literals with too many digits:\n\t- [OFFSET = uint160(0x1111000000000000000000000000000000001111)](contracts/L1/DepositFeed.sol#L14)\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "14adc89c437b961183112ca2328ae0e07b627d12995c5555d2c2fca5d4dbe1aa", "check": "too-many-digits", "impact": "Informational", "confidence": "Medium"}] +[{"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1102, "length": 648, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-59) has payable functions:\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#38-58)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L59) has payable functions:\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L38-L58)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "be013b000d4c176d4d893619bdca725d93e4761e4b2e22fa77a64144e53abb26", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 2010, "length": 88, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 97}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}}}], "description": "MockL2OutputOracle.appendL2Output(bytes32,uint256) (contracts/L1/MockL2OutputOracle.sol#45-51) uses a dangerous strict equality:\n\t- require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/MockL2OutputOracle.sol#48)\n", "markdown": "[MockL2OutputOracle.appendL2Output(bytes32,uint256)](contracts/L1/MockL2OutputOracle.sol#L45-L51) uses a dangerous strict equality:\n\t- [require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/MockL2OutputOracle.sol#L48)\n", "first_markdown_element": "contracts/L1/MockL2OutputOracle.sol#L45-L51", "id": "74ee9955ede80e105221045625f8b4f963a0ca8422674891166ad65bdcdba57a", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}, {"type": "node", "name": "OFFSET = uint160(0x1111000000000000000000000000000000001111)", "source_mapping": {"start": 284, "length": 85, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [14], "starting_column": 5, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}}}], "description": "DepositFeed.slitherConstructorConstantVariables() (contracts/L1/DepositFeed.sol#7-59) uses literals with too many digits:\n\t- OFFSET = uint160(0x1111000000000000000000000000000000001111) (contracts/L1/DepositFeed.sol#14)\n", "markdown": "[DepositFeed.slitherConstructorConstantVariables()](contracts/L1/DepositFeed.sol#L7-L59) uses literals with too many digits:\n\t- [OFFSET = uint160(0x1111000000000000000000000000000000001111)](contracts/L1/DepositFeed.sol#L14)\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "14adc89c437b961183112ca2328ae0e07b627d12995c5555d2c2fca5d4dbe1aa", "check": "too-many-digits", "impact": "Informational", "confidence": "Medium"}] diff --git a/packages/contracts/tasks/deposits.ts b/packages/contracts/tasks/deposits.ts new file mode 100644 index 000000000000..6d547e03f225 --- /dev/null +++ b/packages/contracts/tasks/deposits.ts @@ -0,0 +1,47 @@ +import { task, types } from 'hardhat/config' +import { Contract, providers, utils, Wallet } from 'ethers' +import dotenv from 'dotenv' + +task('deposit', 'Deposits funds onto L2.') + .addParam('l1ProviderUrl', 'L1 provider URL.', null, types.string) + .addParam('to', 'Recipient address.', null, types.string) + .addParam('amountEth', 'Amount in ETH to send.', null, types.string) + .addOptionalParam( + 'depositContractAddr', + 'Address of deposit contract.', + 'deaddeaddeaddeaddeaddeaddeaddeaddead0001', + types.string + ) + .setAction(async ({ l1ProviderUrl, to, amountEth, depositContractAddr }) => { + const depositFeedArtifact = require('../artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json') + + dotenv.config() + + if (!process.env.PRIVATE_KEY) { + throw new Error('You must define PRIVATE_KEY in your environment.') + } + + const l1Provider = new providers.JsonRpcProvider(l1ProviderUrl) + const l1Wallet = new Wallet(process.env.PRIVATE_KEY!, l1Provider) + const depositFeed = new Contract( + depositContractAddr, + depositFeedArtifact.abi + ).connect(l1Wallet) + + const amountWei = utils.parseEther(amountEth) + console.log(`Depositing ${amountEth} ETH to ${to}...`) + // Below adds 0.01 ETH to account for gas. + const tx = await depositFeed.depositTransaction( + to, + amountWei, + '3000000', + false, + [], + { + value: amountWei.add(utils.parseEther('0.01')), + } + ) + console.log(`Got TX hash ${tx.hash}. Waiting...`) + await tx.wait() + console.log('Done.') + }) diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index 47f802e43de1..6ca4a9b39307 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -5,7 +5,8 @@ "strict": true, "esModuleInterop": true, "outDir": "dist", - "declaration": true + "declaration": true, + "resolveJsonModule": true }, "include": ["./scripts", "./test", "./typechain"], "files": ["./hardhat.config.ts"] diff --git a/packages/contracts/yarn.lock b/packages/contracts/yarn.lock index ad3a127b70ef..667b4624186b 100644 --- a/packages/contracts/yarn.lock +++ b/packages/contracts/yarn.lock @@ -3165,10 +3165,10 @@ dom-walk@^0.1.0: resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== -dotenv@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== +dotenv@^16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" + integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== dotignore@~0.1.2: version "0.1.2" From 1f02e0aa93697b594e7fca55b0ae3ad6df0e51b1 Mon Sep 17 00:00:00 2001 From: inphi Date: Wed, 30 Mar 2022 01:19:28 -0400 Subject: [PATCH 362/585] Migrate DepositFeed spec to forge test contract This is nice because: * it's consistent with the existing contract testing * smaller test spec - easier to read and maintain * no need for the DummyContract to simulate contract calls --- .../contracts/test/DepositFeed.t.sol | 126 +++++++ .../contracts/test/DummyContract.sol | 23 -- .../contracts/test/L1/DepositFeed.spec.ts | 315 ------------------ 3 files changed, 126 insertions(+), 338 deletions(-) create mode 100644 packages/contracts/contracts/test/DepositFeed.t.sol delete mode 100644 packages/contracts/contracts/test/DummyContract.sol delete mode 100644 packages/contracts/test/L1/DepositFeed.spec.ts diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol new file mode 100644 index 000000000000..a92aebe1bc94 --- /dev/null +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -0,0 +1,126 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { DepositFeed } from "../L1/DepositFeed.sol"; + +contract DepositFeedTest is DSTest { + Vm vm = Vm(HEVM_ADDRESS); + address immutable ZERO_ADDRESS = address(0); + address immutable NON_ZERO_ADDRESS = address(1); + uint256 immutable NON_ZERO_VALUE = 100; + uint256 immutable ZERO_VALUE = 0; + uint256 immutable NON_ZERO_GASLIMIT = 50000; + bytes NON_ZERO_DATA = "0x1111"; + + DepositFeed df; + + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 mint, + uint256 value, + uint256 gasLimit, + bool isCreation, + bytes data + ); + + function setUp() external { + df = new DepositFeed(); + } + + function addressAlias() internal view returns(address) { + return address(uint160(address(this)) + uint160(0x1111000000000000000000000000000000001111)); + } + + // Test: depositTransaction fails when contract creation has a non-zero destination address + function test_depositTransaction_ContractCreationReverts() external { + vm.expectRevert(abi.encodeWithSignature("NonZeroCreationTarget()")); + df.depositTransaction(NON_ZERO_ADDRESS, NON_ZERO_VALUE, NON_ZERO_GASLIMIT, true, '0x'); + } + + // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value + function test_depositTransaction_NoValueEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(address(this), NON_ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + + df.depositTransaction(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + } + + // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value + function test_depositTransaction_NoValueContract() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(addressAlias(), NON_ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + + df.depositTransaction(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + } + + // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value + function test_depositTransaction_createWithZeroValueForEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(address(this), ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + + df.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + } + + // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value + function test_depositTransaction_createWithZeroValueForContract() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(addressAlias(), ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + + df.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + } + + // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH + function test_depositTransaction_withEthValueFromEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(address(this), NON_ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, '0x'); + + uint256 balanceBefore = address(df).balance; + df.depositTransaction{value: NON_ZERO_VALUE}(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, '0x'); + uint256 balanceAfter = address(df).balance; + assertEq(balanceAfter - balanceBefore, NON_ZERO_VALUE); + } + + // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH + function test_depositTransaction_withEthValueFromContract() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(addressAlias(), NON_ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + + df.depositTransaction{value: NON_ZERO_VALUE}(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + } + + // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH + function test_depositTransaction_withEthValueAndEOAContractCreation() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(address(this), ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, '0x'); + + uint256 balanceBefore = address(df).balance; + df.depositTransaction{value: NON_ZERO_VALUE}(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, '0x'); + uint256 balanceAfter = address(df).balance; + assertEq(balanceAfter - balanceBefore, NON_ZERO_VALUE); + } + + // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH + function test_depositTransaction_withEthValueAndContractContractCreation() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited(addressAlias(), ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + + uint256 balanceBefore = address(df).balance; + df.depositTransaction{value: NON_ZERO_VALUE}(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + uint256 balanceAfter = address(df).balance; + assertEq(balanceAfter - balanceBefore, NON_ZERO_VALUE); + } +} diff --git a/packages/contracts/contracts/test/DummyContract.sol b/packages/contracts/contracts/test/DummyContract.sol deleted file mode 100644 index 6ce8e40fc24d..000000000000 --- a/packages/contracts/contracts/test/DummyContract.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.10; - -/** - * For use in testing with a call from a contract rather than an EOA. - */ -contract Dummy { - error Failed(); - - /** - * Forwards a call. - * @param _target Address to call - * @param _data Data to forward - */ - function forward(address _target, bytes calldata _data) external payable { - uint256 amount = address(this).balance; - (bool success, ) = _target.call{ value: amount }(_data); - // Silence the 'Return value of low-level calls not used' warning. - if (!success) { - revert Failed(); - } - } -} diff --git a/packages/contracts/test/L1/DepositFeed.spec.ts b/packages/contracts/test/L1/DepositFeed.spec.ts deleted file mode 100644 index f355d66dbc93..000000000000 --- a/packages/contracts/test/L1/DepositFeed.spec.ts +++ /dev/null @@ -1,315 +0,0 @@ -import { expect } from 'chai' -import { ethers } from 'hardhat' -import { Contract, ContractFactory, Signer, BigNumber } from 'ethers' -import { applyL1ToL2Alias } from '@eth-optimism/core-utils' - -import { DepositFeed__factory, DepositFeed } from '../../typechain' - -const ZERO_ADDRESS = '0x' + '00'.repeat(20) -const ZERO_BIGNUMBER = BigNumber.from(0) -const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) -const NON_ZERO_GASLIMIT = BigNumber.from(50_000) -const NON_ZERO_VALUE = BigNumber.from(100) -const NON_ZERO_DATA = '0x' + '11'.repeat(42) - -const decodeDepositEvent = async ( - depositFeed: DepositFeed -): Promise<{ - from: string - to: string - mint: BigNumber - value: BigNumber - gasLimit: BigNumber - isCreation: boolean - data: string -}> => { - const events = await depositFeed.queryFilter( - depositFeed.filters.TransactionDeposited() - ) - - const eventArgs = events[events.length - 1].args - - return { - from: eventArgs.from, - to: eventArgs.to, - mint: eventArgs.mint, - value: eventArgs.value, - gasLimit: eventArgs.gasLimit, - isCreation: eventArgs.isCreation, - data: eventArgs.data, - } -} - -describe('DepositFeed', () => { - let signer: Signer - let signerAddress: string - let depositFeed: DepositFeed - before(async () => { - ;[signer] = await ethers.getSigners() - signerAddress = await signer.getAddress() - depositFeed = await new DepositFeed__factory(signer).deploy() - await depositFeed.deployed() - }) - it('Should revert if a contract creation has a non-zero destination address', async () => { - await expect( - depositFeed.depositTransaction( - NON_ZERO_ADDRESS, - NON_ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - '0x' - ) - ).to.be.revertedWith('NonZeroCreationTarget()') - }) - - describe('Should emit the correct log values...', async () => { - it('when an EOA deposits a transaction with 0 value.', async () => { - const receipt = await ( - await depositFeed.depositTransaction( - NON_ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ) - ).wait() - await expect(receipt.status).to.equal(1) - - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(eventArgs).to.deep.equal({ - from: signerAddress, - to: NON_ZERO_ADDRESS, - mint: ZERO_BIGNUMBER, - value: ZERO_BIGNUMBER, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: false, - data: NON_ZERO_DATA, - }) - }) - - it('when a contract deposits a transaction with 0 value.', async () => { - // Deploy a dummy contract so we can impersonate it - const dummy = await (await ethers.getContractFactory('Dummy')).deploy() - await dummy.deployed() - - await expect( - dummy.forward( - depositFeed.address, - depositFeed.interface.encodeFunctionData('depositTransaction', [ - NON_ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA, - ]) - ) - ).to.not.be.reverted - - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(eventArgs).to.deep.equal({ - from: applyL1ToL2Alias(dummy.address), - to: NON_ZERO_ADDRESS, - value: ZERO_BIGNUMBER, - mint: ZERO_BIGNUMBER, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: false, - data: NON_ZERO_DATA, - }) - }) - - it('when an EOA deposits a contract creation with 0 value.', async () => { - const receipt = await ( - await depositFeed.depositTransaction( - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA - ) - ).wait() - await expect(receipt.status).to.equal(1) - - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(eventArgs).to.deep.equal({ - from: signerAddress, - to: ZERO_ADDRESS, - value: ZERO_BIGNUMBER, - mint: ZERO_BIGNUMBER, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: true, - data: NON_ZERO_DATA, - }) - }) - - it('when a contract deposits a contract creation with 0 value.', async () => { - // Deploy a dummy contract so we can impersonate it - const dummy = await (await ethers.getContractFactory('Dummy')).deploy() - await dummy.deployed() - - const receipt = await ( - await dummy.forward( - depositFeed.address, - depositFeed.interface.encodeFunctionData('depositTransaction', [ - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA, - ]) - ) - ).wait() - await expect(receipt.status).to.equal(1) - - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(eventArgs).to.deep.equal({ - from: applyL1ToL2Alias(dummy.address), - to: ZERO_ADDRESS, - value: ZERO_BIGNUMBER, - mint: ZERO_BIGNUMBER, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: true, - data: NON_ZERO_DATA, - }) - }) - - describe('and increase its eth balance...', async () => { - it('when an EOA deposits a transaction with an ETH value.', async () => { - const balBefore = await ethers.provider.getBalance(depositFeed.address) - const receipt = await ( - await depositFeed.depositTransaction( - NON_ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - false, - '0x', - { - value: NON_ZERO_VALUE, - } - ) - ).wait() - await expect(receipt.status).to.equal(1) - - const balAfter = await ethers.provider.getBalance(depositFeed.address) - - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(balAfter.sub(balBefore)).to.equal(NON_ZERO_VALUE) - expect(eventArgs).to.deep.equal({ - from: signerAddress, - to: NON_ZERO_ADDRESS, - value: ZERO_BIGNUMBER, - mint: NON_ZERO_VALUE, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: false, - data: '0x', - }) - }) - - it('when a contract deposits a transaction with an ETH value.', async () => { - // Deploy a dummy contract so we can impersonate it - const dummy = await (await ethers.getContractFactory('Dummy')).deploy() - await dummy.deployed() - await expect( - dummy.forward( - depositFeed.address, - depositFeed.interface.encodeFunctionData('depositTransaction', [ - NON_ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA, - ]), - { - value: NON_ZERO_VALUE, - } - ) - ).to.not.be.reverted - - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(eventArgs).to.deep.equal({ - from: applyL1ToL2Alias(dummy.address), - to: NON_ZERO_ADDRESS, - value: ZERO_BIGNUMBER, - mint: NON_ZERO_VALUE, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: false, - data: NON_ZERO_DATA, - }) - }) - - it('when an EOA deposits a contract creation with an ETH value.', async () => { - const balBefore = await ethers.provider.getBalance(depositFeed.address) - const receipt = await ( - await depositFeed.depositTransaction( - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - '0x', - { - value: NON_ZERO_VALUE, - } - ) - ).wait() - await expect(receipt.status).to.equal(1) - - const balAfter = await ethers.provider.getBalance(depositFeed.address) - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(balAfter.sub(balBefore)).to.equal(NON_ZERO_VALUE) - expect(eventArgs).to.deep.equal({ - from: signerAddress, - to: ZERO_ADDRESS, - value: ZERO_BIGNUMBER, - mint: NON_ZERO_VALUE, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: true, - data: '0x', - }) - }) - - it('when a contract deposits a contract creation with an ETH value.', async () => { - // Deploy a dummy contract so we can impersonate it - const dummy = await (await ethers.getContractFactory('Dummy')).deploy() - await dummy.deployed() - - const balBefore = await ethers.provider.getBalance(depositFeed.address) - const receipt = await ( - await dummy.forward( - depositFeed.address, - depositFeed.interface.encodeFunctionData('depositTransaction', [ - ZERO_ADDRESS, - ZERO_BIGNUMBER, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA, - ]), - { - value: NON_ZERO_VALUE, - } - ) - ).wait() - await expect(receipt.status).to.equal(1) - - const balAfter = await ethers.provider.getBalance(depositFeed.address) - const eventArgs = await decodeDepositEvent(depositFeed) - - expect(balAfter.sub(balBefore)).to.equal(NON_ZERO_VALUE) - expect(eventArgs).to.deep.equal({ - from: applyL1ToL2Alias(dummy.address), - to: ZERO_ADDRESS, - value: ZERO_BIGNUMBER, - mint: NON_ZERO_VALUE, - gasLimit: NON_ZERO_GASLIMIT, - isCreation: true, - data: NON_ZERO_DATA, - }) - }) - }) - }) -}) From fcc3be915c46abf683ef8db992a91d6927610ace Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 22 Mar 2022 05:03:16 +0100 Subject: [PATCH 363/585] ref impl: new l1 downloader with batching and caching --- go.mod | 5 +- go.sum | 3 + opnode/flags/flags.go | 6 + opnode/l1/batching.go | 134 ++++++++ opnode/l1/batching_test.go | 266 +++++++++++++++ opnode/l1/downloader.go | 73 ---- opnode/l1/receipts.go | 50 +++ opnode/l1/source.go | 367 +++++++++++++++------ opnode/l1/source_test.go | 200 +++++++++++ opnode/l1/types.go | 148 +++++++++ opnode/node/config.go | 5 + opnode/node/node.go | 9 +- opnode/rollup/derive/invert_test.go | 47 ++- opnode/rollup/derive/payload_attributes.go | 48 +-- opnode/rollup/driver/driver.go | 11 +- opnode/rollup/driver/fake_chain.go | 4 +- opnode/rollup/driver/state.go | 44 ++- opnode/rollup/driver/step.go | 36 +- opnode/service.go | 1 + opnode/test/system_test.go | 2 + 20 files changed, 1206 insertions(+), 253 deletions(-) create mode 100644 opnode/l1/batching.go create mode 100644 opnode/l1/batching_test.go delete mode 100644 opnode/l1/downloader.go create mode 100644 opnode/l1/receipts.go create mode 100644 opnode/l1/source_test.go create mode 100644 opnode/l1/types.go diff --git a/go.mod b/go.mod index 7f9c98b5b746..765d810c6926 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,13 @@ go 1.18 require ( github.com/ethereum/go-ethereum v1.10.16 + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.0 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.5 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 + gotest.tools v2.2.0+incompatible ) require ( @@ -26,10 +28,10 @@ require ( github.com/go-stack/stack v1.8.1 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-cmp v0.5.4 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.0.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect @@ -48,6 +50,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/stretchr/objx v0.1.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect diff --git a/go.sum b/go.sum index 9eab70a0d83d..ea1b2165683c 100644 --- a/go.sum +++ b/go.sum @@ -203,6 +203,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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= @@ -408,6 +409,7 @@ github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZL github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -696,6 +698,7 @@ 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 h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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= diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go index 65849d1f3ea1..692f672859e4 100644 --- a/opnode/flags/flags.go +++ b/opnode/flags/flags.go @@ -51,6 +51,11 @@ var ( } /* Optional Flags */ + L1TrustRPC = cli.BoolFlag{ + Name: "l1.trustrpc", + Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", + EnvVar: prefixEnvVar("L1_TRUST_RPC"), + } SequencingEnabledFlag = cli.BoolFlag{ Name: "sequencing.enabled", @@ -100,6 +105,7 @@ var requiredFlags = []cli.Flag{ } var optionalFlags = []cli.Flag{ + L1TrustRPC, SequencingEnabledFlag, BatchSubmitterKeyFlag, WithdrawalContractAddr, diff --git a/opnode/l1/batching.go b/opnode/l1/batching.go new file mode 100644 index 000000000000..abfd49d6b5f2 --- /dev/null +++ b/opnode/l1/batching.go @@ -0,0 +1,134 @@ +package l1 + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" +) + +var ( + TooManyRetries = errors.New("too many retries") +) + +// parallelBatchCall creates a drop-in replacement for the standard batchCallContextFn that splits requests into more batch requests, and will parallelize and retry as configured. +func parallelBatchCall(log log.Logger, getBatch batchCallContextFn, maxRetry int, maxPerBatch int, maxParallel int) batchCallContextFn { + return func(ctx context.Context, requests []rpc.BatchElem) error { + return fetchBatched(ctx, log, requests, getBatch, maxRetry, maxPerBatch, maxParallel) + } +} + +type batchResult struct { + failed []rpc.BatchElem // if anything has to be retried + err error // if the batch as a whole failed + success int // amount of items that completed successfully +} + +// fetchBatched fetches the given requests in batches of at most maxPerBatch elements, and with at most maxRetry retries per batch. +// Batch requests may be split into maxParallel go-routines. +func fetchBatched(ctx context.Context, log log.Logger, requests []rpc.BatchElem, getBatch batchCallContextFn, maxRetry int, maxPerBatch int, maxParallel int) error { + batchRequest := func(ctx context.Context, missing []rpc.BatchElem) (failed []rpc.BatchElem, err error) { + if err := getBatch(ctx, missing); err != nil { + return nil, fmt.Errorf("failed batch-retrieval of receipts: %v", err) + } + for _, elem := range missing { + if elem.Error != nil { + log.Trace("batch request element failed", "err", elem.Error, "elem", elem.Args[0]) + elem.Error = nil // reset, we'll try this element again + failed = append(failed, elem) + continue + } + } + return failed, nil + } + + // limit capacity, don't write to underlying array on retries + requests = requests[:len(requests):len(requests)] + + expectedBatches := (len(requests) + maxPerBatch - 1) / maxPerBatch + + // don't need more go-routines than requests + if maxParallel > expectedBatches { + maxParallel = expectedBatches + } + + // capacity is sufficient for no go-routine to get stuck on writing + completed := make(chan batchResult, maxParallel) + + // queue of tasks for worker go-routines + batchRequests := make(chan []rpc.BatchElem, maxParallel) + defer close(batchRequests) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // starts worker go-routines. Closed when task channel closes + for i := 0; i < maxParallel; i++ { + go func(ctx context.Context) { + for { + batch, ok := <-batchRequests + if !ok { + return // no more batches left + } + failed, err := batchRequest(ctx, batch) + completed <- batchResult{failed: failed, err: err, success: len(batch) - len(failed)} + } + }(ctx) + } + + parallelRequests := func() int { + // we split the requests into parallel batch requests, and count how many + i := 0 + for ; i < maxParallel && len(requests) > 0; i++ { + nextBatch := requests + if len(nextBatch) > maxPerBatch { + nextBatch = requests[:maxPerBatch] + } + // don't retry this batch of requests again, unless we add them back + requests = requests[len(nextBatch):] + + // schedule the batch, this may block if all workers are busy and the queue is full + batchRequests <- nextBatch + } + return i + } + + maxCount := expectedBatches * maxRetry + + awaited := len(requests) + + // start initial round of parallel requests + count := parallelRequests() + + // We slow down additional batch requests to not spam the server. + retryTicker := time.NewTicker(time.Millisecond * 20) + defer retryTicker.Stop() + + // The main requests slice is only ever mutated by the go-routine running this loop. + // Slices of this are sent to worker go-routines, and never overwritten with different requests. + for { + // check if we've all results back successfully + if awaited <= 0 { + return nil + } + if count > maxCount { + return TooManyRetries + } + select { + case <-retryTicker.C: + count += parallelRequests() // retry batch-requests on interval + case result := <-completed: + if result.err != nil { + // batch failed, RPC may be broken, abort + return fmt.Errorf("batch request failed: %w", result.err) + } + // if any element failed, add it to the requests for re-attempt + requests = append(requests, result.failed...) + awaited -= result.success + case <-ctx.Done(): + return ctx.Err() + } + } +} diff --git a/opnode/l1/batching_test.go b/opnode/l1/batching_test.go new file mode 100644 index 000000000000..9c5c0b6e8ff9 --- /dev/null +++ b/opnode/l1/batching_test.go @@ -0,0 +1,266 @@ +package l1 + +import ( + "context" + "fmt" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + log "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/mock" + "gotest.tools/assert" +) + +type elemCall struct { + id int + err bool +} + +type batchCall struct { + elems []elemCall + err error +} + +type batchTestCase struct { + name string + items int + + batchCalls []batchCall + err error + + maxRetry int + maxPerBatch int + maxParallel int + + mock.Mock +} + +func (tc *batchTestCase) Inputs() []rpc.BatchElem { + out := make([]rpc.BatchElem, tc.items) + for i := 0; i < tc.items; i++ { + out[i] = rpc.BatchElem{ + Method: "testing_foobar", + Args: []interface{}{i}, + Result: nil, + Error: nil, + } + } + return out +} + +func (tc *batchTestCase) GetBatch(ctx context.Context, b []rpc.BatchElem) error { + return tc.Mock.MethodCalled("get", b).Get(0).([]error)[0] +} + +func (tc *batchTestCase) Run(t *testing.T) { + requests := tc.Inputs() + + // mock all the results of the batch calls + for bci, b := range tc.batchCalls { + batchCall := b + var batch []rpc.BatchElem + for _, elem := range batchCall.elems { + batch = append(batch, requests[elem.id]) + } + tc.On("get", batch).Run(func(args mock.Arguments) { + batch := args[0].([]rpc.BatchElem) + for i := range batch { + if batchCall.elems[i].err { + batch[i].Error = fmt.Errorf("mock err batch-call %d, elem call %d", bci, i) + batch[i].Result = nil + } else { + batch[i].Error = nil + batch[i].Result = fmt.Sprintf("mock result batch-call %d, elem call %d", bci, i) + } + } + }).Return([]error{batchCall.err}) // wrap to preserve nil as type of error + } + + log := testlog.Logger(t, log.LvlError) + + err := fetchBatched(context.Background(), log, requests, tc.GetBatch, tc.maxRetry, tc.maxPerBatch, tc.maxParallel) + assert.Equal(t, err, tc.err) + + tc.AssertExpectations(t) +} + +func TestFetchBatched(t *testing.T) { + testCases := []*batchTestCase{ + { + name: "empty", + items: 0, + batchCalls: []batchCall{}, + err: nil, + maxRetry: 3, + maxPerBatch: 10, + maxParallel: 10, + }, + { + name: "simple", + items: 4, + batchCalls: []batchCall{ + { + elems: []elemCall{ + {id: 0, err: false}, + {id: 1, err: false}, + {id: 2, err: false}, + {id: 3, err: false}, + }, + err: nil, + }, + }, + err: nil, + maxRetry: 3, + maxPerBatch: 10, + maxParallel: 10, + }, + { + name: "split", + items: 5, + batchCalls: []batchCall{ + { + elems: []elemCall{ + {id: 0, err: false}, + {id: 1, err: false}, + {id: 2, err: false}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 3, err: false}, + {id: 4, err: false}, + }, + err: nil, + }, + }, + err: nil, + maxRetry: 2, + maxPerBatch: 3, + maxParallel: 10, + }, + { + name: "batch split and parallel constrain", + items: 3, + batchCalls: []batchCall{ + { + elems: []elemCall{ + {id: 0, err: false}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 1, err: false}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 2, err: false}, + }, + err: nil, + }, + }, + err: nil, + maxRetry: 2, + maxPerBatch: 1, + maxParallel: 2, + }, + { + name: "efficient retry", + items: 5, + batchCalls: []batchCall{ + { + elems: []elemCall{ + {id: 0, err: false}, + {id: 1, err: true}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 2, err: false}, + {id: 3, err: false}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 4, err: false}, + {id: 1, err: false}, + }, + err: nil, + }, + }, + err: nil, + maxRetry: 2, + maxPerBatch: 2, + maxParallel: 2, + }, + { + name: "repeated sequential retries", + items: 3, + batchCalls: []batchCall{ + { + elems: []elemCall{ + {id: 0, err: false}, + {id: 1, err: true}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 2, err: false}, + {id: 1, err: true}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 1, err: false}, + }, + err: nil, + }, + }, + err: nil, + maxRetry: 2, + maxPerBatch: 2, + maxParallel: 1, + }, + { + name: "too many retries", + items: 3, + batchCalls: []batchCall{ + { + elems: []elemCall{ + {id: 0, err: false}, + {id: 1, err: true}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 2, err: false}, + {id: 1, err: true}, + }, + err: nil, + }, + { + elems: []elemCall{ + {id: 1, err: true}, + }, + err: nil, + }, + }, + err: TooManyRetries, + maxRetry: 2, + maxPerBatch: 2, + maxParallel: 1, + }, + } + for _, tc := range testCases { + t.Run(tc.name, tc.Run) + } +} diff --git a/opnode/l1/downloader.go b/opnode/l1/downloader.go deleted file mode 100644 index 6c2e22d0ce7c..000000000000 --- a/opnode/l1/downloader.go +++ /dev/null @@ -1,73 +0,0 @@ -package l1 - -import ( - "context" - "sync" - "time" - - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -const MaxConcurrentFetchesPerCall = 10 -const MaxReceiptRetry = 3 - -type EthClient interface { - BlockByHash(context.Context, common.Hash) (*types.Block, error) - TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) -} - -type Downloader struct { - client EthClient - // log log.Logger -} - -func NewDownloader(client EthClient) *Downloader { - return &Downloader{client: client} -} - -func (dl Downloader) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { - block, err := dl.client.BlockByHash(ctx, id.Hash) - if err != nil { - return nil, nil, err - } - txs := block.Transactions() - receipts := make([]*types.Receipt, len(txs)) - - semaphoreChan := make(chan struct{}, MaxConcurrentFetchesPerCall) - defer close(semaphoreChan) - var retErr error - var errMu sync.Mutex - var wg sync.WaitGroup - for idx, tx := range txs { - wg.Add(1) - i := idx - hash := tx.Hash() - go func() { - semaphoreChan <- struct{}{} - for j := 0; j < MaxReceiptRetry; j++ { - receipt, err := dl.client.TransactionReceipt(ctx, hash) - if err != nil && j == MaxReceiptRetry-1 { - // dl.log.Error("Got error in final retry of fetch", "err", err) - errMu.Lock() - retErr = err - errMu.Unlock() - } else if err == nil { - receipts[i] = receipt - break - } else { - time.Sleep(20 * time.Millisecond) - } - } - wg.Done() - <-semaphoreChan - }() - } - wg.Wait() - if retErr != nil { - return nil, nil, retErr - } - return block, receipts, nil -} diff --git a/opnode/l1/receipts.go b/opnode/l1/receipts.go new file mode 100644 index 000000000000..d22a3cb94133 --- /dev/null +++ b/opnode/l1/receipts.go @@ -0,0 +1,50 @@ +package l1 + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" + + "github.com/ethereum/go-ethereum/core/types" +) + +// fetchReceipts fetches the receipts of the transactions using RPC batching, verifies if the receipts are complete and correct, and then returns results +func fetchReceipts(ctx context.Context, receiptHash common.Hash, txs types.Transactions, getBatch batchCallContextFn) (types.Receipts, error) { + if len(txs) == 0 { + if receiptHash != types.EmptyRootHash { + return nil, fmt.Errorf("no transactions, but got non-empty receipt trie root: %s", receiptHash) + } + return nil, nil + } + + receipts := make([]*types.Receipt, len(txs)) + receiptRequests := make([]rpc.BatchElem, len(txs)) + for i := 0; i < len(txs); i++ { + receipts[i] = new(types.Receipt) + receiptRequests[i] = rpc.BatchElem{ + Method: "eth_getTransactionReceipt", + Args: []interface{}{txs[i].Hash()}, + Result: &receipts[i], // receipt may become nil, double pointer is intentional + } + } + if err := getBatch(ctx, receiptRequests); err != nil { + return nil, fmt.Errorf("failed to fetch batch of receipts: %v", err) + } + for i, r := range receipts { + if r == nil { // on reorgs or other cases the receipts may disappear before they can be retrieved. + return nil, fmt.Errorf("receipt of tx %d returns nil on retrieval", i) + } + } + + // Sanity-check: external L1-RPC sources are notorious for not returning all receipts, + // or returning them out-of-order. Verify the receipts against the expected receipt-hash. + hasher := trie.NewStackTrie(nil) + computed := types.DeriveSha(types.Receipts(receipts), hasher) + if receiptHash != computed { + return nil, fmt.Errorf("failed to fetch list of receipts: expected receipt root %s but computed %s from retrieved receipts", receiptHash, computed) + } + return receipts, nil +} diff --git a/opnode/l1/source.go b/opnode/l1/source.go index f5e69268fdfc..87faa78b8981 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -4,159 +4,332 @@ import ( "context" "errors" "fmt" - "math/big" - "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + lru "github.com/hashicorp/golang-lru" ) -const MaxBlocksInL1Range = uint64(100) +type SourceConfig struct { + MaxParallelBatching int + MaxBatchRetry int + MaxRequestsPerBatch int -type Source struct { - client *ethclient.Client - downloader *Downloader + // cache sizes + + // Number of blocks worth of receipts to cache + ReceiptsCacheSize int + // Number of blocks worth of transactions to cache + TransactionsCacheSize int + // Number of block headers to cache + HeadersCacheSize int + + // If the RPC is untrusted, then we should not use cached information from responses, + // and instead verify against the block-hash. + // Of real L1 blocks no deposits can be missed/faked, no batches can be missed/faked, + // only the wrong L1 blocks can be retrieved. + TrustRPC bool } -func NewSource(client *ethclient.Client) Source { - return Source{ - client: client, - downloader: NewDownloader(client), +func DefaultConfig(config *rollup.Config, trustRPC bool) *SourceConfig { + return &SourceConfig{ + // We only consume receipts once per block, + // we just need basic redundancy if we share the cache between multiple drivers + ReceiptsCacheSize: 20, + + // Optimal if at least a few times the size of a sequencing window. + // When smaller than a window, requests would be repeated every window shift. + // Additional cache-size for handling reorgs, and thus more unique blocks, also helps. + TransactionsCacheSize: int(config.SeqWindowSize * 4), + HeadersCacheSize: int(config.SeqWindowSize * 4), + + // TODO: tune batch params + MaxParallelBatching: 8, + MaxBatchRetry: 3, + MaxRequestsPerBatch: 20, + + TrustRPC: trustRPC, } } -func (s Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { - return s.client.SubscribeNewHead(ctx, ch) -} +type batchCallContextFn func(ctx context.Context, b []rpc.BatchElem) error -func (s Source) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return s.client.HeaderByHash(ctx, hash) +type RPCClient interface { + BatchCallContext(ctx context.Context, b []rpc.BatchElem) error + CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error + EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) + Close() } -func (s Source) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return s.client.HeaderByNumber(ctx, number) -} +// Source to retrieve L1 data from with optimized batch requests, cached results, +// and flag to not trust the RPC. +type Source struct { + client RPCClient -func (s Source) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - return s.client.TransactionReceipt(ctx, txHash) -} + batchCall batchCallContextFn -func (s Source) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return s.client.BlockByHash(ctx, hash) -} + trustRPC bool -func (s Source) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - return s.client.BlockByNumber(ctx, number) -} + // cache receipts in bundles per block hash + // common.Hash -> types.Receipts + receiptsCache *lru.Cache -func (s Source) Fetch(ctx context.Context, id eth.BlockID) (*types.Block, []*types.Receipt, error) { - return s.downloader.Fetch(ctx, id) + // cache transactions in bundles per block hash + // common.Hash -> types.Transactions + transactionsCache *lru.Cache + + // cache block headers of blocks by hash + // common.Hash -> *HeaderInfo + headersCache *lru.Cache } -func (s Source) Close() { - s.client.Close() +func NewSource(client RPCClient, log log.Logger, config *SourceConfig) (*Source, error) { + receiptsCache, err := lru.New(config.ReceiptsCacheSize) + if err != nil { + return nil, fmt.Errorf("invalid receipts cache: %v", err) + } + transactionsCache, err := lru.New(config.TransactionsCacheSize) + if err != nil { + return nil, fmt.Errorf("invalid transactions cache: %v", err) + } + headersCache, err := lru.New(config.HeadersCacheSize) + if err != nil { + return nil, fmt.Errorf("invalid headers cache: %v", err) + } + + // Batch calls will be split up to handle max-batch size, + // and parallelized since the RPC server does not parallelize batch contents otherwise. + getBatch := parallelBatchCall(log, client.BatchCallContext, + config.MaxBatchRetry, config.MaxRequestsPerBatch, config.MaxParallelBatching) + + return &Source{ + client: client, + batchCall: getBatch, + trustRPC: config.TrustRPC, + receiptsCache: receiptsCache, + transactionsCache: transactionsCache, + headersCache: headersCache, + }, nil } -func (s Source) FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) { - return s.client.BlockByHash(ctx, id.Hash) +// SubscribeNewHead subscribes to notifications about the current blockchain head on the given channel. +func (s *Source) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { + // Note that *types.Header does not cache the block hash unlike *HeaderInfo, it always recomputes. + // Inefficient if used poorly, but no trust issue. + return s.client.EthSubscribe(ctx, ch, "newHeads") } -func (s Source) FetchReceipts(ctx context.Context, id eth.BlockID, receiptHash common.Hash) ([]*types.Receipt, error) { - _, receipts, err := s.Fetch(ctx, id) +func (s *Source) headerCall(ctx context.Context, method string, id interface{}) (*HeaderInfo, error) { + var header *rpcHeader + err := s.client.CallContext(ctx, &header, method, id, false) // headers are just blocks without txs if err != nil { return nil, err } - // Sanity-check: external L1-RPC sources are notorious for not returning all receipts, - // or returning them out-of-order. Verify the receipts against the expected receipt-hash. - hasher := trie.NewStackTrie(nil) - computed := types.DeriveSha(types.Receipts(receipts), hasher) - if receiptHash != computed { - return nil, fmt.Errorf("failed to validate receipts of %s, computed receipt-hash %s does not match expected hash %d", id, computed, receiptHash) + if header == nil { + return nil, ethereum.NotFound } - return receipts, nil + info, err := header.Info(s.trustRPC) + if err != nil { + return nil, err + } + s.headersCache.Add(info.hash, info) + return info, nil } -func (s Source) FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) { - var txns []*types.Transaction - for _, id := range window { - block, err := s.client.BlockByHash(ctx, id.Hash) - if err != nil { - return nil, err +func (s *Source) blockCall(ctx context.Context, method string, id interface{}) (*HeaderInfo, types.Transactions, error) { + var block *rpcBlock + err := s.client.CallContext(ctx, &block, method, id, true) + if err != nil { + return nil, nil, err + } + if block == nil { + return nil, nil, ethereum.NotFound + } + info, txs, err := block.Info(s.trustRPC) + if err != nil { + return nil, nil, err + } + s.headersCache.Add(info.hash, info) + s.transactionsCache.Add(info.hash, txs) + return info, txs, nil +} + +func (s *Source) InfoByHash(ctx context.Context, hash common.Hash) (derive.L1Info, error) { + if header, ok := s.headersCache.Get(hash); ok { + return header.(*HeaderInfo), nil + } + return s.headerCall(ctx, "eth_getBlockByHash", hash) +} + +func (s *Source) InfoByNumber(ctx context.Context, number uint64) (derive.L1Info, error) { + // can't hit the cache when querying by number due to reorgs. + return s.headerCall(ctx, "eth_getBlockByNumber", hexutil.EncodeUint64(number)) +} + +func (s *Source) InfoHead(ctx context.Context) (derive.L1Info, error) { + // can't hit the cache when querying the head due to reorgs / changes. + return s.headerCall(ctx, "eth_getBlockByNumber", "latest") +} + +func (s *Source) InfoAndTxsByHash(ctx context.Context, hash common.Hash) (derive.L1Info, types.Transactions, error) { + if header, ok := s.headersCache.Get(hash); ok { + if txs, ok := s.transactionsCache.Get(hash); ok { + return header.(*HeaderInfo), txs.(types.Transactions), nil } - txns = append(txns, block.Transactions()...) } - return txns, nil + return s.blockCall(ctx, "eth_getBlockByHash", hash) } -func (s Source) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { - return s.l1BlockRefByNumber(ctx, nil) + +func (s *Source) InfoAndTxsByNumber(ctx context.Context, number uint64) (derive.L1Info, types.Transactions, error) { + // can't hit the cache when querying by number due to reorgs. + return s.blockCall(ctx, "eth_getBlockByNumber", hexutil.EncodeUint64(number)) } -func (s Source) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { - return s.l1BlockRefByNumber(ctx, new(big.Int).SetUint64(l1Num)) +func (s *Source) InfoAndTxsHead(ctx context.Context) (derive.L1Info, types.Transactions, error) { + // can't hit the cache when querying the head due to reorgs / changes. + return s.blockCall(ctx, "eth_getBlockByNumber", "latest") } -// l1BlockRefByNumber wraps l1.HeaderByNumber to return an eth.L1BlockRef -// This is internal because the exposed L1BlockRefByNumber takes uint64 instead of big.Ints -func (s Source) l1BlockRefByNumber(ctx context.Context, number *big.Int) (eth.L1BlockRef, error) { - header, err := s.client.HeaderByNumber(ctx, number) +func (s *Source) Fetch(ctx context.Context, blockHash common.Hash) (derive.L1Info, types.Transactions, types.Receipts, error) { + if blockHash == (common.Hash{}) { + return nil, nil, nil, ethereum.NotFound + } + info, txs, err := s.blockCall(ctx, "eth_getBlockByHash", blockHash) if err != nil { - // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. - return eth.L1BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", number, err) + return nil, nil, nil, err } - return eth.L1BlockRef{ - Hash: header.Hash(), - Number: header.Number.Uint64(), - ParentHash: header.ParentHash, - Time: header.Time, - }, nil + receipts, err := fetchReceipts(ctx, info.receiptHash, txs, s.batchCall) + if err != nil { + return nil, nil, nil, err + } + s.receiptsCache.Add(info.hash, receipts) + return info, txs, receipts, nil } -// L1Range returns a range of L1 block beginning just after `begin`. -func (s Source) L1Range(ctx context.Context, begin eth.BlockID) ([]eth.BlockID, error) { - // Ensure that we start on the expected chain. - if canonicalBegin, err := s.L1BlockRefByNumber(ctx, begin.Number); err != nil { - return nil, fmt.Errorf("failed to fetch L1 block %v %v: %w", begin.Number, begin.Hash, err) - } else { - if canonicalBegin.Hash != begin.Hash { - return nil, fmt.Errorf("Re-org at begin block. Expected: %v. Actual: %v", begin, canonicalBegin) +// FetchAllTransactions fetches transaction lists of a window of blocks, and caches each block and the transactions +func (s *Source) FetchAllTransactions(ctx context.Context, window []eth.BlockID) ([]types.Transactions, error) { + // list of transaction lists + allTxLists := make([]types.Transactions, len(window)) + + var blockRequests []rpc.BatchElem + var requestIndices []int + + for i := 0; i < len(window); i++ { + // if we are shifting the window by 1 block at a time, most of the results should already be in the cache. + txs, ok := s.transactionsCache.Get(window[i].Hash) + if ok { + allTxLists[i] = txs.(types.Transactions) + } else { + blockRequests = append(blockRequests, rpc.BatchElem{ + Method: "eth_getBlockByHash", + Args: []interface{}{window[i].Hash, true}, // request block including transactions list + Result: new(rpcBlock), + Error: nil, + }) + requestIndices = append(requestIndices, i) // remember the block index this request corresponds to } } - l1head, err := s.L1HeadBlockRef(ctx) - if err != nil { - return nil, fmt.Errorf("failed to fetch head L1 block: %w", err) + if len(blockRequests) > 0 { + if err := s.batchCall(ctx, blockRequests); err != nil { + return nil, err + } } - maxBlocks := MaxBlocksInL1Range - // Cap maxBlocks if there are less than maxBlocks between `begin` and the head of the chain. - if l1head.Number-begin.Number <= maxBlocks { - maxBlocks = l1head.Number - begin.Number + + // try to cache everything we have before halting on the results with errors + for i := 0; i < len(blockRequests); i++ { + if blockRequests[i].Error == nil { + info, txs, err := blockRequests[i].Result.(*rpcBlock).Info(s.trustRPC) + if err != nil { + return nil, fmt.Errorf("bad block data for block %s: %v", blockRequests[i].Args[0], err) + } + s.headersCache.Add(info.hash, info) + s.transactionsCache.Add(info.hash, txs) + allTxLists[requestIndices[i]] = txs + } } - if maxBlocks == 0 { - return nil, nil + for i := 0; i < len(blockRequests); i++ { + if blockRequests[i].Error != nil { + return nil, fmt.Errorf("failed to retrieve transactions of block %s in batch of %d blocks: %v", window[i], len(blockRequests), blockRequests[i].Error) + } } - prevHash := begin.Hash - var res []eth.BlockID - // TODO: Walk backwards to be able to use block by hash - for i := begin.Number + 1; i < begin.Number+maxBlocks+1; i++ { - n, err := s.L1BlockRefByNumber(ctx, i) - if err != nil { - return nil, fmt.Errorf("failed to fetch L1 block %v: %w", i, err) + return allTxLists, nil +} + +func (s *Source) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { + head, err := s.InfoHead(ctx) + if err != nil { + return eth.L1BlockRef{}, fmt.Errorf("failed to fetch head header: %v", err) + } + return head.BlockRef(), nil +} + +func (s *Source) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { + head, err := s.InfoByNumber(ctx, l1Num) + if err != nil { + return eth.L1BlockRef{}, fmt.Errorf("failed to fetch header by num %d: %v", l1Num, err) + } + return head.BlockRef(), nil +} + +// L1Range returns a range of L1 block beginning just after begin, up to max blocks. +// This batch-requests all blocks by number in the range at once, and then verifies the consistency +func (s *Source) L1Range(ctx context.Context, begin eth.BlockID, max uint64) ([]eth.BlockID, error) { + headerRequests := make([]rpc.BatchElem, max) + for i := uint64(0); i < max; i++ { + headerRequests[i] = rpc.BatchElem{ + Method: "eth_getBlockByNumber", + Args: []interface{}{hexutil.EncodeUint64(begin.Number + 1 + i), false}, + Result: new(*rpcHeader), + Error: nil, } - // TODO(Joshua): Look into why this fails around the genesis block - if n.Number != 1 && n.ParentHash != prevHash { - return nil, errors.New("re-organization occurred while attempting to get l1 range") + } + if err := s.batchCall(ctx, headerRequests); err != nil { + return nil, err + } + + out := make([]eth.BlockID, 0, max) + + // try to cache everything we have before halting on the results with errors + for i := 0; i < len(headerRequests); i++ { + result := *headerRequests[i].Result.(**rpcHeader) + if headerRequests[i].Error == nil { + if result == nil { + break // no more headers from here + } + info, err := result.Info(s.trustRPC) + if err != nil { + return nil, fmt.Errorf("bad header data for block %s: %v", headerRequests[i].Args[0], err) + } + s.headersCache.Add(info.hash, info) + out = append(out, info.ID()) + prev := begin + if i > 0 { + prev = out[i-1] + } + if prev.Hash != info.parentHash { + return nil, fmt.Errorf("inconsistent results from L1 chain range request, block %s not expected parent %s of %s", prev, info.parentHash, info.ID()) + } + } else if errors.Is(headerRequests[i].Error, ethereum.NotFound) { + break // no more headers from here + } else { + return nil, fmt.Errorf("failed to retrieve block: %s: %v", headerRequests[i].Args[0], headerRequests[i].Error) } - prevHash = n.Hash - res = append(res, n.ID()) } + return out, nil +} - return res, nil +func (s *Source) Close() { + s.client.Close() } diff --git a/opnode/l1/source_test.go b/opnode/l1/source_test.go new file mode 100644 index 000000000000..499d8a6aa934 --- /dev/null +++ b/opnode/l1/source_test.go @@ -0,0 +1,200 @@ +package l1 + +import ( + "context" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +type mockRPC struct { + mock.Mock +} + +// we catch the optimized version, instead of mocking a lot of split/parallel calls +func (m *mockRPC) batchCall(ctx context.Context, b []rpc.BatchElem) error { + return m.MethodCalled("batchCall", ctx, b).Get(0).([]error)[0] +} + +func (m *mockRPC) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + return m.MethodCalled("BatchCallContext", ctx, b).Get(0).([]error)[0] +} + +func (m *mockRPC) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + return m.MethodCalled("CallContext", ctx, result, method, args).Get(0).([]error)[0] +} + +func (m *mockRPC) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) { + called := m.MethodCalled("EthSubscribe", channel, args) + return called.Get(0).(*rpc.ClientSubscription), called.Get(1).([]error)[0] +} + +func (m *mockRPC) Close() { + m.MethodCalled("Close") +} + +var _ RPCClient = (*mockRPC)(nil) + +func randHash() (out common.Hash) { + rand.Read(out[:]) + return out +} + +func randHeader() *types.Header { + return &types.Header{ + ParentHash: randHash(), + UncleHash: randHash(), + Coinbase: common.Address{}, + Root: randHash(), + TxHash: randHash(), + ReceiptHash: randHash(), + Number: big.NewInt(1234), + Time: 123456, + MixDigest: randHash(), + BaseFee: big.NewInt(100), + } +} + +func randTransaction(i uint64) *types.Transaction { + return types.NewTx(&types.DynamicFeeTx{ + ChainID: big.NewInt(999), + Nonce: i, + GasTipCap: big.NewInt(1), + GasFeeCap: big.NewInt(100), + Gas: 21000, + To: &common.Address{0x42}, + Value: big.NewInt(0), + }) +} + +func randTxs(offset uint64, count uint64) types.Transactions { + out := make(types.Transactions, count) + for i := uint64(0); i < count; i++ { + out[i] = randTransaction(offset + i) + } + return out +} + +func TestSource_InfoByHash(t *testing.T) { + log := testlog.Logger(t, log.LvlError) + m := new(mockRPC) + hdr := randHeader() + rhdr := &rpcHeader{ + cache: rpcHeaderCacheInfo{Hash: hdr.Hash()}, + header: *hdr, + } + expectedInfo, _ := rhdr.Info(true) + h := rhdr.header.Hash() + ctx := context.Background() + m.On("CallContext", ctx, new(*rpcHeader), "eth_getBlockByHash", []interface{}{h, false}).Run(func(args mock.Arguments) { + *args[1].(**rpcHeader) = rhdr + }).Return([]error{nil}) + s, err := NewSource(m, log, DefaultConfig(&rollup.Config{SeqWindowSize: 10}, true)) + assert.NoError(t, err) + info, err := s.InfoByHash(ctx, h) + assert.NoError(t, err) + assert.Equal(t, info, expectedInfo) + m.Mock.AssertExpectations(t) + // Again, without expecting any calls from the mock, the cache will return the block + info, err = s.InfoByHash(ctx, h) + assert.NoError(t, err) + assert.Equal(t, info, expectedInfo) + m.Mock.AssertExpectations(t) +} + +func TestSource_InfoByNumber(t *testing.T) { + log := testlog.Logger(t, log.LvlError) + m := new(mockRPC) + hdr := randHeader() + rhdr := &rpcHeader{ + cache: rpcHeaderCacheInfo{Hash: hdr.Hash()}, + header: *hdr, + } + expectedInfo, _ := rhdr.Info(true) + n := hdr.Number.Uint64() + ctx := context.Background() + m.On("CallContext", ctx, new(*rpcHeader), "eth_getBlockByNumber", []interface{}{hexutil.EncodeUint64(n), false}).Run(func(args mock.Arguments) { + *args[1].(**rpcHeader) = rhdr + }).Return([]error{nil}) + s, err := NewSource(m, log, DefaultConfig(&rollup.Config{SeqWindowSize: 10}, true)) + assert.NoError(t, err) + info, err := s.InfoByNumber(ctx, n) + assert.NoError(t, err) + assert.Equal(t, info, expectedInfo) + m.Mock.AssertExpectations(t) +} + +func TestSource_FetchAllTransactions(t *testing.T) { + log := testlog.Logger(t, log.LvlError) + m := new(mockRPC) + + ctx := context.Background() + a, b := randHeader(), randHeader() + blocks := []*rpcBlock{ + { + header: rpcHeader{ + cache: rpcHeaderCacheInfo{ + Hash: a.Hash(), + }, + header: *a, + }, + extra: rpcBlockCacheInfo{ + Transactions: randTxs(0, 4), + }, + }, + { + header: rpcHeader{ + cache: rpcHeaderCacheInfo{ + Hash: b.Hash(), + }, + header: *b, + }, + extra: rpcBlockCacheInfo{ + Transactions: randTxs(4, 3), + }, + }, + } + expectedRequest := make([]rpc.BatchElem, len(blocks)) + expectedTxLists := make([]types.Transactions, len(blocks)) + for i, b := range blocks { + expectedRequest[i] = rpc.BatchElem{Method: "eth_getBlockByHash", Args: []interface{}{b.header.header.Hash(), true}, Result: new(rpcBlock)} + expectedTxLists[i] = b.extra.Transactions + } + + m.On("batchCall", ctx, expectedRequest).Run(func(args mock.Arguments) { + batch := args[1].([]rpc.BatchElem) + for i, b := range blocks { + *batch[i].Result.(*rpcBlock) = *b + } + }).Return([]error{nil}) + + s, err := NewSource(m, log, DefaultConfig(&rollup.Config{SeqWindowSize: 10}, true)) + assert.NoError(t, err) + s.batchCall = m.batchCall // override the optimized batch call + + id := func(i int) eth.BlockID { + return eth.BlockID{Hash: blocks[i].header.header.Hash(), Number: blocks[i].header.header.Number.Uint64()} + } + + txLists, err := s.FetchAllTransactions(ctx, []eth.BlockID{id(0), id(1)}) + assert.NoError(t, err) + assert.Equal(t, txLists, expectedTxLists) + m.Mock.AssertExpectations(t) + + // again, but now without expecting any calls (transactions were cached) + txLists, err = s.FetchAllTransactions(ctx, []eth.BlockID{id(0), id(1)}) + assert.NoError(t, err) + assert.Equal(t, txLists, expectedTxLists) + m.Mock.AssertExpectations(t) +} diff --git a/opnode/l1/types.go b/opnode/l1/types.go new file mode 100644 index 000000000000..c75269619104 --- /dev/null +++ b/opnode/l1/types.go @@ -0,0 +1,148 @@ +package l1 + +import ( + "encoding/json" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/trie" +) + +// Note: we do this ugly typing because we want the best, and the standard bindings are not sufficient: +// - batched calls of many block requests (standard bindings do extra uncle-header fetches, cannot be batched nicely) +// - ignore uncle data (does not even exist anymore post-Merge) +// - use cached block hash, if we trust the RPC. +// - verify transactions list matches tx-root, to ensure consistency with block-hash, if we do not trust the RPC +// +// Transaction-sender data from the RPC is not cached, since ethclient.setSenderFromServer is private, +// and we only need to compute the sender for transactions into the inbox. +// +// This way we minimize RPC calls, enable batching, and can choose to verify what the RPC gives us. + +type HeaderInfo struct { + hash common.Hash + parentHash common.Hash + root common.Hash + number uint64 + time uint64 + mixDigest common.Hash // a.k.a. the randomness field post-merge. + baseFee *big.Int + txHash common.Hash + receiptHash common.Hash +} + +var _ derive.L1Info = (*HeaderInfo)(nil) + +func (info *HeaderInfo) Hash() common.Hash { + return info.hash +} + +func (info *HeaderInfo) ParentHash() common.Hash { + return info.parentHash +} + +func (info *HeaderInfo) Root() common.Hash { + return info.root +} + +func (info *HeaderInfo) NumberU64() uint64 { + return info.number +} + +func (info *HeaderInfo) Time() uint64 { + return info.time +} + +func (info *HeaderInfo) MixDigest() common.Hash { + return info.mixDigest +} + +func (info *HeaderInfo) BaseFee() *big.Int { + return info.baseFee +} + +func (info *HeaderInfo) ID() eth.BlockID { + return eth.BlockID{Hash: info.hash, Number: info.number} +} + +func (info *HeaderInfo) BlockRef() eth.L1BlockRef { + return eth.L1BlockRef{ + Hash: info.hash, + Number: info.number, + ParentHash: info.parentHash, + Time: info.time, + } +} + +type rpcHeaderCacheInfo struct { + Hash common.Hash `json:"hash"` +} + +type rpcHeader struct { + cache rpcHeaderCacheInfo + header types.Header +} + +func (header *rpcHeader) UnmarshalJSON(msg []byte) error { + if err := json.Unmarshal(msg, &header.header); err != nil { + return err + } + return json.Unmarshal(msg, &header.cache) +} + +func (header *rpcHeader) Info(trustCache bool) (*HeaderInfo, error) { + info := HeaderInfo{ + hash: header.cache.Hash, + parentHash: header.header.ParentHash, + root: header.header.Root, + number: header.header.Number.Uint64(), + time: header.header.Time, + mixDigest: header.header.MixDigest, + baseFee: header.header.BaseFee, + txHash: header.header.TxHash, + receiptHash: header.header.ReceiptHash, + } + if !trustCache { + if computed := header.header.Hash(); computed != info.hash { + return nil, fmt.Errorf("failed to verify block hash: computed %s but RPC said %s", computed, info.hash) + } + } + return &info, nil +} + +type rpcBlockCacheInfo struct { + Transactions []*types.Transaction `json:"transactions"` +} + +type rpcBlock struct { + header rpcHeader + extra rpcBlockCacheInfo +} + +func (block *rpcBlock) UnmarshalJSON(msg []byte) error { + if err := json.Unmarshal(msg, &block.header); err != nil { + return err + } + return json.Unmarshal(msg, &block.extra) +} + +func (block *rpcBlock) Info(trustCache bool) (*HeaderInfo, types.Transactions, error) { + // verify the header data + info, err := block.header.Info(trustCache) + if err != nil { + return nil, nil, fmt.Errorf("failed to verify block from RPC: %v", err) + } + + if !trustCache { // verify the list of transactions matches the tx-root + hasher := trie.NewStackTrie(nil) + computed := types.DeriveSha(types.Transactions(block.extra.Transactions), hasher) + if expected := info.txHash; expected != computed { + return nil, nil, fmt.Errorf("failed to verify transactions list: expected transactions root %s but retrieved %s", expected, computed) + } + } + return info, block.extra.Transactions, nil +} diff --git a/opnode/node/config.go b/opnode/node/config.go index 9f4b85e240ee..ac60d3b4edb6 100644 --- a/opnode/node/config.go +++ b/opnode/node/config.go @@ -14,6 +14,11 @@ type Config struct { L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required) L2NodeAddr string // Address of L2 User JSON-RPC endpoint to use (eth namespace required) + // L1TrustRPC: if we trust the L1 RPC we do not have to validate L1 response contents like headers + // against block hashes, or cached transaction sender addresses. + // Thus we can sync faster at the risk of the source RPC being wrong. + L1TrustRPC bool + Rollup rollup.Config // Sequencer flag, enables sequencing diff --git a/opnode/node/node.go b/opnode/node/node.go index cecba41df519..be66a7bc8aff 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -22,7 +22,7 @@ import ( type OpNode struct { log log.Logger - l1Source l1.Source // Source to fetch data from (also implements the Downloader interface) + l1Source *l1.Source // Source to fetch data from (also implements the Downloader interface) l2Engines []*driver.Driver // engines to keep synced server *rpcServer done chan struct{} @@ -60,7 +60,10 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* // TODO: we may need to authenticate the connection with L1 // l1Node.SetHeader() - l1Source := l1.NewSource(ethclient.NewClient(l1Node)) + l1Source, err := l1.NewSource(l1Node, log, l1.DefaultConfig(&cfg.Rollup, cfg.L1TrustRPC)) + if err != nil { + return nil, fmt.Errorf("failed to create L1 source: %v", err) + } var l2Engines []*driver.Driver genesis := cfg.Rollup.Genesis @@ -85,7 +88,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* PrivKey: cfg.SubmitterPrivKey, } } - engine := driver.NewDriver(cfg.Rollup, client, &l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), submitter, cfg.Sequencer) + engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), submitter, cfg.Sequencer) l2Engines = append(l2Engines, engine) } diff --git a/opnode/rollup/derive/invert_test.go b/opnode/rollup/derive/invert_test.go index 9d7038a7a2df..93a152fd96be 100644 --- a/opnode/rollup/derive/invert_test.go +++ b/opnode/rollup/derive/invert_test.go @@ -5,23 +5,37 @@ import ( "math/rand" "testing" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" ) type l1MockInfo struct { + hash common.Hash + parentHash common.Hash + root common.Hash num uint64 time uint64 - hash common.Hash - baseFee *big.Int mixDigest [32]byte + baseFee *big.Int receiptRoot common.Hash } +func (l *l1MockInfo) Hash() common.Hash { + return l.hash +} + +func (l *l1MockInfo) ParentHash() common.Hash { + return l.parentHash +} + +func (l *l1MockInfo) Root() common.Hash { + return l.root +} + func (l *l1MockInfo) NumberU64() uint64 { return l.num } @@ -30,22 +44,31 @@ func (l *l1MockInfo) Time() uint64 { return l.time } -func (l *l1MockInfo) Hash() common.Hash { - return l.hash +func (l *l1MockInfo) MixDigest() common.Hash { + return l.mixDigest } func (l *l1MockInfo) BaseFee() *big.Int { return l.baseFee } -func (l *l1MockInfo) MixDigest() common.Hash { - return l.mixDigest -} - func (l *l1MockInfo) ReceiptHash() common.Hash { return l.receiptRoot } +func (l *l1MockInfo) ID() eth.BlockID { + return eth.BlockID{Hash: l.hash, Number: l.num} +} + +func (l *l1MockInfo) BlockRef() eth.L1BlockRef { + return eth.L1BlockRef{ + Hash: l.hash, + Number: l.num, + ParentHash: l.parentHash, + Time: l.time, + } +} + func randomHash(rng *rand.Rand) (out common.Hash) { rng.Read(out[:]) return @@ -53,11 +76,13 @@ func randomHash(rng *rand.Rand) (out common.Hash) { func randomL1Info(rng *rand.Rand) *l1MockInfo { return &l1MockInfo{ + parentHash: randomHash(rng), num: rng.Uint64(), time: rng.Uint64(), hash: randomHash(rng), - baseFee: big.NewInt(rng.Int63n(1000_000 * params.GWei)), // a million GWEI + baseFee: big.NewInt(rng.Int63n(1000_000 * 1e9)), // a million GWEI receiptRoot: types.EmptyRootHash, + root: randomHash(rng), } } diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 55f4426b8436..b01994a31437 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" @@ -113,13 +114,16 @@ func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.D } type L1Info interface { + Hash() common.Hash + ParentHash() common.Hash + Root() common.Hash // state-root NumberU64() uint64 Time() uint64 - Hash() common.Hash - BaseFee() *big.Int // MixDigest field, reused for randomness after The Merge (Bellatrix hardfork) MixDigest() common.Hash - ReceiptHash() common.Hash + BaseFee() *big.Int + ID() eth.BlockID + BlockRef() eth.L1BlockRef } // L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block @@ -170,27 +174,29 @@ func UserDeposits(l2BlockHeight uint64, receipts []*types.Receipt) ([]*types.Dep return out, nil } -func BatchesFromEVMTransactions(config *rollup.Config, txs []*types.Transaction) ([]*BatchData, error) { +func BatchesFromEVMTransactions(config *rollup.Config, txLists []types.Transactions) ([]*BatchData, error) { var out []*BatchData l1Signer := config.L1Signer() - for _, tx := range txs { - if to := tx.To(); to != nil && *to == config.BatchInboxAddress { - seqDataSubmitter, err := l1Signer.Sender(tx) - if err != nil { - // TODO: log error - continue // bad signature, ignore - } - // some random L1 user might have sent a transaction to our batch inbox, ignore them - if seqDataSubmitter != config.BatchSenderAddress { - // TODO: log/record metric - continue // not an authorized batch submitter, ignore - } - batches, err := DecodeBatches(config, bytes.NewReader(tx.Data())) - if err != nil { - // TODO: log/record metric - continue + for _, txs := range txLists { + for _, tx := range txs { + if to := tx.To(); to != nil && *to == config.BatchInboxAddress { + seqDataSubmitter, err := l1Signer.Sender(tx) // optimization: only derive sender if To is correct + if err != nil { + // TODO: log error + continue // bad signature, ignore + } + // some random L1 user might have sent a transaction to our batch inbox, ignore them + if seqDataSubmitter != config.BatchSenderAddress { + // TODO: log/record metric + continue // not an authorized batch submitter, ignore + } + batches, err := DecodeBatches(config, bytes.NewReader(tx.Data())) + if err != nil { + // TODO: log/record metric + continue + } + out = append(out, batches...) } - out = append(out, batches...) } } return out, nil diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index d4921df5158c..2a28bafa7405 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -23,12 +23,9 @@ type BatchSubmitter interface { } type Downloader interface { - // FetchL1Info fetches the L1 header information corresponding to a L1 block ID - FetchL1Info(ctx context.Context, id eth.BlockID) (derive.L1Info, error) - // FetchReceipts of a L1 block. The receipt-hash must be provided to sanity-check the retrieved receipts. - FetchReceipts(ctx context.Context, id eth.BlockID, receiptHash common.Hash) ([]*types.Receipt, error) - // FetchTransactions from the given window of L1 blocks - FetchTransactions(ctx context.Context, window []eth.BlockID) ([]*types.Transaction, error) + InfoByHash(ctx context.Context, hash common.Hash) (derive.L1Info, error) + Fetch(ctx context.Context, blockHash common.Hash) (derive.L1Info, types.Transactions, types.Receipts, error) + FetchAllTransactions(ctx context.Context, window []eth.BlockID) ([]types.Transactions, error) } type Engine interface { @@ -41,7 +38,7 @@ type Engine interface { type L1Chain interface { L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) - L1Range(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) + L1Range(ctx context.Context, base eth.BlockID, max uint64) ([]eth.BlockID, error) } // TODO: Extend L2 Interface to get safe/unsafe blocks (specifically for Unsafe L2 head) diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 0b83a2edd8cd..6c79f0104ea3 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -91,11 +91,11 @@ type fakeChainSource struct { log log.Logger } -func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) { +func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID, max uint64) ([]eth.BlockID, error) { var out []eth.BlockID found := false for i, b := range m.l1s[m.l1reorg] { - if found { + if found && uint64(len(out)) < max { out = append(out, b.ID()) } if b.ID() == base { diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index d3eeebb1329c..218e9927a098 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -2,6 +2,7 @@ package driver import ( "context" + "sync/atomic" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -17,7 +18,7 @@ type state struct { l2Head eth.L2BlockRef // L2 Unsafe Head l2SafeHead eth.L2BlockRef // L2 Safe Head - this is the head of the L2 chain as derived from L1 (thus it is Sequencer window blocks behind) l2Finalized eth.BlockID // L2 Block that will never be reversed - l1Window []eth.BlockID // l1Window buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. + l1WindowBuf []eth.BlockID // l1WindowBuf buffers the next L1 block IDs to derive new L2 blocks from, with increasing block height. // Rollup config Config rollup.Config @@ -32,6 +33,8 @@ type state struct { log log.Logger done chan struct{} + + closed uint32 // non-zero when closed } func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, submitter BatchSubmitter, sequencer bool) *state { @@ -74,34 +77,35 @@ func (s *state) Close() error { return nil } -// l1WindowEnd returns the last block that should be used as `base` to L1ChainWindow. +// l1WindowBufEnd returns the last block that should be used as `base` to L1ChainWindow. // This is either the last block of the window, or the L1 base block if the window is not populated. -func (s *state) l1WindowEnd() eth.BlockID { - if len(s.l1Window) == 0 { +func (s *state) l1WindowBufEnd() eth.BlockID { + if len(s.l1WindowBuf) == 0 { return s.l2Head.L1Origin } - return s.l1Window[len(s.l1Window)-1] + return s.l1WindowBuf[len(s.l1WindowBuf)-1] } // extendL1Window extends the cached L1 window by pulling blocks from L1. -// It starts just after `s.l1WindowEnd()`. +// It starts just after `s.l1WindowBufEnd()`. func (s *state) extendL1Window(ctx context.Context) error { - s.log.Trace("Extending the cached window from L1", "cached_size", len(s.l1Window), "window_end", s.l1WindowEnd()) - nexts, err := s.l1.L1Range(ctx, s.l1WindowEnd()) + s.log.Trace("Extending the cached window from L1", "cached_size", len(s.l1WindowBuf), "window_buf_end", s.l1WindowBufEnd()) + // fetch enough ids for 2 sequencing windows (we'll shift from one into the other before we run out again) + nexts, err := s.l1.L1Range(ctx, s.l1WindowBufEnd(), s.Config.SeqWindowSize*2) if err != nil { return err } - s.l1Window = append(s.l1Window, nexts...) + s.l1WindowBuf = append(s.l1WindowBuf, nexts...) return nil } // sequencingWindow returns the next sequencing window and true if it exists, (nil, false) if // there are not enough saved blocks. func (s *state) sequencingWindow() ([]eth.BlockID, bool) { - if len(s.l1Window) < int(s.Config.SeqWindowSize) { + if len(s.l1WindowBuf) < int(s.Config.SeqWindowSize) { return nil, false } - return s.l1Window[:int(s.Config.SeqWindowSize)], true + return s.l1WindowBuf[:int(s.Config.SeqWindowSize)], true } func (s *state) findNextL1Origin(ctx context.Context) (eth.BlockID, error) { @@ -148,6 +152,7 @@ func (s *state) loop() { // case <-l1Poll.C: // case <-l2Poll.C: case <-s.done: + atomic.AddUint32(&s.closed, 1) return case <-l2BlockCreation: nextOrigin, err := s.findNextL1Origin(context.Background()) @@ -170,6 +175,9 @@ func (s *state) loop() { // 4. Ask for batch submission go func() { _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches + if atomic.LoadUint32(&s.closed) > 0 { + return // closed, don't log (go-routine may be running after logger closed) + } if err != nil { s.log.Error("Error submitting batch", "err", err) } @@ -187,8 +195,8 @@ func (s *state) loop() { if s.l1Head.Hash == newL1Head.ParentHash { s.log.Trace("Linear extension") s.l1Head = newL1Head - if s.l1WindowEnd().Hash == newL1Head.ParentHash { - s.l1Window = append(s.l1Window, newL1Head.ID()) + if s.l1WindowBufEnd().Hash == newL1Head.ParentHash { + s.l1WindowBuf = append(s.l1WindowBuf, newL1Head.ID()) } } else { s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.ParentHash, "new_l1_head", newL1Head) @@ -204,7 +212,7 @@ func (s *state) loop() { continue } s.l1Head = newL1Head - s.l1Window = nil + s.l1WindowBuf = nil s.l2Head = nextL2Head s.l2SafeHead = nextL2Head // TODO: Handle this more carefully } @@ -220,10 +228,10 @@ func (s *state) loop() { } s.log.Trace("Got step request") // Extend cached window if we do not have enough saved blocks - if len(s.l1Window) < int(s.Config.SeqWindowSize) { + if len(s.l1WindowBuf) < int(s.Config.SeqWindowSize) { err := s.extendL1Window(context.Background()) if err != nil { - s.log.Error("Could not extend the cached L1 window", "err", err, "l1Head", s.l1Head, "window_end", s.l1WindowEnd()) + s.log.Error("Could not extend the cached L1 window", "err", err, "l1Head", s.l1Head, "window_buf_end", s.l1WindowBufEnd()) continue } } @@ -242,10 +250,10 @@ func (s *state) loop() { s.l2Head = newL2Head } s.l2SafeHead = newL2Head - s.l1Window = s.l1Window[1:] + s.l1WindowBuf = s.l1WindowBuf[1:] // TODO: l2Finalized } else { - s.log.Trace("Not enough cached blocks to run step", "cached_window_len", len(s.l1Window)) + s.log.Trace("Not enough cached blocks to run step", "cached_window_len", len(s.l1WindowBuf)) } // Immediately run next step if we have enough blocks. diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 0cfbd11bd961..530dd85f661f 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -31,8 +31,20 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa if err != nil { return l2Parent, nil, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Parent, err) } + l2BLockRef, err := derive.BlockReferences(l2Info, &d.Config.Genesis) + if err != nil { + return l2Parent, nil, fmt.Errorf("failed to derive L2BlockRef from l2Block: %w", err) + } - l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Origin) + var l1Info derive.L1Info + var receipts types.Receipts + // Include deposits if this is the first block of an epoch + if l2BLockRef.L1Origin.Number != l1Origin.Number { + l1Info, _, receipts, err = d.dl.Fetch(fetchCtx, l1Origin.Hash) + } else { + l1Info, err = d.dl.InfoByHash(fetchCtx, l1Origin.Hash) + // don't fetch receipts if we do not process deposits + } if err != nil { return l2Parent, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) } @@ -42,18 +54,6 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa return l2Parent, nil, errors.New("L2 Timestamp is too large") } - var receipts types.Receipts - l2BLockRef, err := derive.BlockReferences(l2Info, &d.Config.Genesis) - if err != nil { - return l2Parent, nil, fmt.Errorf("failed to derive L2BlockRef from l2Block: %w", err) - } - // Include deposits if this is the first block of an epoch - if l2BLockRef.L1Origin.Number != l1Origin.Number { - receipts, err = d.dl.FetchReceipts(fetchCtx, l1Origin, l1Info.ReceiptHash()) - if err != nil { - return l2Parent, nil, fmt.Errorf("failed to fetch receipts of %s: %v", l1Origin, err) - } - } l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) if err != nil { return l2Parent, nil, err @@ -121,24 +121,20 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalize if err != nil { return l2Head, fmt.Errorf("failed to fetch L2 block info of %s: %w", l2Head, err) } - l1Info, err := d.dl.FetchL1Info(fetchCtx, l1Input[0]) + l1Info, _, receipts, err := d.dl.Fetch(fetchCtx, l1Input[0].Hash) if err != nil { - return l2Head, fmt.Errorf("failed to fetch L1 block info of %s: %w", l1Input[0], err) + return l2Head, fmt.Errorf("failed to fetch L1 block with receipts %s: %w", l1Input[0], err) } l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) if err != nil { return l2Head, fmt.Errorf("failed to create l1InfoTx: %w", err) } - receipts, err := d.dl.FetchReceipts(fetchCtx, l1Input[0], l1Info.ReceiptHash()) - if err != nil { - return l2Head, fmt.Errorf("failed to fetch receipts of %s: %w", l1Input[0], err) - } deposits, err := derive.DeriveDeposits(l2Head.Number+1, receipts) if err != nil { return l2Head, fmt.Errorf("failed to derive deposits: %w", err) } // TODO: with sharding the blobs may be identified in more detail than L1 block hashes - transactions, err := d.dl.FetchTransactions(fetchCtx, l1Input) + transactions, err := d.dl.FetchAllTransactions(fetchCtx, l1Input) if err != nil { return l2Head, fmt.Errorf("failed to fetch transactions from %s: %v", l1Input, err) } diff --git a/opnode/service.go b/opnode/service.go index ca1f3e3fdc84..4125dd403cb3 100644 --- a/opnode/service.go +++ b/opnode/service.go @@ -48,6 +48,7 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) { L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), L2NodeAddr: ctx.GlobalString(flags.L2EthNodeAddr.Name), + L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name), Rollup: *rollupConfig, Sequencer: enableSequencing, SubmitterPrivKey: batchSubmitterKey, diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index bebb0f7209bc..26a722d33763 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -163,6 +163,7 @@ func TestSystemE2E(t *testing.T) { L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2Verifier.nodeConfig)}, L2NodeAddr: endpoint(cfg.l2Verifier.nodeConfig), + L1TrustRPC: false, // would be faster to enable, but we want to catch if the RPC is buggy Rollup: rollup.Config{ Genesis: rollup.Genesis{ L1: l1GenesisID, @@ -191,6 +192,7 @@ func TestSystemE2E(t *testing.T) { L1NodeAddr: endpoint(cfg.l1.nodeConfig), L2EngineAddrs: []string{endpoint(cfg.l2Sequencer.nodeConfig)}, L2NodeAddr: endpoint(cfg.l2Verifier.nodeConfig), + L1TrustRPC: true, // test RPC cache usage Rollup: rollup.Config{ Genesis: rollup.Genesis{ L1: l1GenesisID, From 0c075da9825c045a9d6462d67ab013b468935855 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 30 Mar 2022 15:05:30 +0400 Subject: [PATCH 364/585] opnode/l1: confirugable limit of concurrent requests to l1 source --- opnode/l1/request_sema.go | 43 +++++++++++++++++++++++++++++++++ opnode/l1/source.go | 50 ++++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 opnode/l1/request_sema.go diff --git a/opnode/l1/request_sema.go b/opnode/l1/request_sema.go new file mode 100644 index 000000000000..4a7dc892d2e4 --- /dev/null +++ b/opnode/l1/request_sema.go @@ -0,0 +1,43 @@ +package l1 + +import ( + "context" + + "github.com/ethereum/go-ethereum/rpc" +) + +type limitClient struct { + c RPCClient + sema chan struct{} +} + +// LimitRPC limits concurrent RPC requests (excluding subscriptions) to a given number by wrapping the client with a semaphore. +func LimitRPC(c RPCClient, concurrentRequests int) RPCClient { + return &limitClient{ + c: c, + // the capacity of the channel determines how many go-routines can concurrently execute requests with the wrapped client. + sema: make(chan struct{}, concurrentRequests), + } +} + +func (lc *limitClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + lc.sema <- struct{}{} + defer func() { <-lc.sema }() + return lc.c.BatchCallContext(ctx, b) +} + +func (lc *limitClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + lc.sema <- struct{}{} + defer func() { <-lc.sema }() + return lc.c.CallContext(ctx, result, method, args...) +} + +func (lc *limitClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) { + // subscription doesn't count towards request limit + return lc.c.EthSubscribe(ctx, channel, args...) +} + +func (lc *limitClient) Close() { + close(lc.sema) + lc.c.Close() +} diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 87faa78b8981..e392d75803ab 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -19,10 +19,14 @@ import ( ) type SourceConfig struct { + // batching parameters MaxParallelBatching int MaxBatchRetry int MaxRequestsPerBatch int + // limit concurrent requests, applies to the source as a whole + MaxConcurrentRequests int + // cache sizes // Number of blocks worth of receipts to cache @@ -39,6 +43,31 @@ type SourceConfig struct { TrustRPC bool } +func (c *SourceConfig) Check() error { + if c.ReceiptsCacheSize < 0 { + return fmt.Errorf("invalid receipts cache size: %d", c.ReceiptsCacheSize) + } + if c.TransactionsCacheSize < 0 { + return fmt.Errorf("invalid transactions cache size: %d", c.TransactionsCacheSize) + } + if c.HeadersCacheSize < 0 { + return fmt.Errorf("invalid headers cache size: %d", c.HeadersCacheSize) + } + if c.MaxConcurrentRequests < 1 { + return fmt.Errorf("expected at least 1 concurrent request, but max is %d", c.MaxConcurrentRequests) + } + if c.MaxParallelBatching < 1 { + return fmt.Errorf("expected at least 1 batch request to run at a time, but max is %d", c.MaxParallelBatching) + } + if c.MaxBatchRetry < 0 || c.MaxBatchRetry > 20 { + return fmt.Errorf("number of max batch retries is not reasonable: %d", c.MaxBatchRetry) + } + if c.MaxRequestsPerBatch < 1 { + return fmt.Errorf("expected at least 1 request per batch, but max is: %d", c.MaxRequestsPerBatch) + } + return nil +} + func DefaultConfig(config *rollup.Config, trustRPC bool) *SourceConfig { return &SourceConfig{ // We only consume receipts once per block, @@ -56,6 +85,8 @@ func DefaultConfig(config *rollup.Config, trustRPC bool) *SourceConfig { MaxBatchRetry: 3, MaxRequestsPerBatch: 20, + MaxConcurrentRequests: 10, + TrustRPC: trustRPC, } } @@ -92,18 +123,15 @@ type Source struct { } func NewSource(client RPCClient, log log.Logger, config *SourceConfig) (*Source, error) { - receiptsCache, err := lru.New(config.ReceiptsCacheSize) - if err != nil { - return nil, fmt.Errorf("invalid receipts cache: %v", err) - } - transactionsCache, err := lru.New(config.TransactionsCacheSize) - if err != nil { - return nil, fmt.Errorf("invalid transactions cache: %v", err) - } - headersCache, err := lru.New(config.HeadersCacheSize) - if err != nil { - return nil, fmt.Errorf("invalid headers cache: %v", err) + if err := config.Check(); err != nil { + return nil, fmt.Errorf("bad config, cannot create L1 source: %v", err) } + // no errors if the size is positive, as already validated by Check() above. + receiptsCache, _ := lru.New(config.ReceiptsCacheSize) + transactionsCache, _ := lru.New(config.TransactionsCacheSize) + headersCache, _ := lru.New(config.HeadersCacheSize) + + client = LimitRPC(client, config.MaxConcurrentRequests) // Batch calls will be split up to handle max-batch size, // and parallelized since the RPC server does not parallelize batch contents otherwise. From bc3d205356683cce938863004d9da06511c50ff0 Mon Sep 17 00:00:00 2001 From: inphi Date: Wed, 30 Mar 2022 21:28:47 -0400 Subject: [PATCH 365/585] lint DepositFeed spec; update package.json --- .../contracts/test/DepositFeed.t.sol | 165 ++++++++++++++---- packages/contracts/package.json | 2 +- 2 files changed, 131 insertions(+), 36 deletions(-) diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol index a92aebe1bc94..87e2272e56fa 100644 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -30,14 +30,15 @@ contract DepositFeedTest is DSTest { df = new DepositFeed(); } - function addressAlias() internal view returns(address) { - return address(uint160(address(this)) + uint160(0x1111000000000000000000000000000000001111)); + function addressAlias() internal view returns (address) { + return + address(uint160(address(this)) + uint160(0x1111000000000000000000000000000000001111)); } // Test: depositTransaction fails when contract creation has a non-zero destination address function test_depositTransaction_ContractCreationReverts() external { vm.expectRevert(abi.encodeWithSignature("NonZeroCreationTarget()")); - df.depositTransaction(NON_ZERO_ADDRESS, NON_ZERO_VALUE, NON_ZERO_GASLIMIT, true, '0x'); + df.depositTransaction(NON_ZERO_ADDRESS, NON_ZERO_VALUE, NON_ZERO_GASLIMIT, true, "0x"); } // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value @@ -45,26 +46,62 @@ contract DepositFeedTest is DSTest { // EOA emulation vm.prank(address(this), address(this)); vm.expectEmit(true, true, false, true); - emit TransactionDeposited(address(this), NON_ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); - - df.depositTransaction(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + emit TransactionDeposited( + address(this), + NON_ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + + df.depositTransaction( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); } - // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value - function test_depositTransaction_NoValueContract() external { + // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value + function test_depositTransaction_NoValueContract() external { vm.expectEmit(true, true, false, true); - emit TransactionDeposited(addressAlias(), NON_ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); - - df.depositTransaction(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + emit TransactionDeposited( + addressAlias(), + NON_ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + + df.depositTransaction( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); } // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value function test_depositTransaction_createWithZeroValueForEOA() external { // EOA emulation vm.prank(address(this), address(this)); - + vm.expectEmit(true, true, false, true); - emit TransactionDeposited(address(this), ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + emit TransactionDeposited( + address(this), + ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); df.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); } @@ -72,7 +109,15 @@ contract DepositFeedTest is DSTest { // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value function test_depositTransaction_createWithZeroValueForContract() external { vm.expectEmit(true, true, false, true); - emit TransactionDeposited(addressAlias(), ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + emit TransactionDeposited( + addressAlias(), + ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); df.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); } @@ -83,20 +128,46 @@ contract DepositFeedTest is DSTest { vm.prank(address(this), address(this)); vm.expectEmit(true, true, false, true); - emit TransactionDeposited(address(this), NON_ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, '0x'); - - uint256 balanceBefore = address(df).balance; - df.depositTransaction{value: NON_ZERO_VALUE}(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, '0x'); - uint256 balanceAfter = address(df).balance; - assertEq(balanceAfter - balanceBefore, NON_ZERO_VALUE); + emit TransactionDeposited( + address(this), + NON_ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + "0x" + ); + + df.depositTransaction{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + "0x" + ); + assertEq(address(df).balance, NON_ZERO_VALUE); } // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH function test_depositTransaction_withEthValueFromContract() external { vm.expectEmit(true, true, false, true); - emit TransactionDeposited(addressAlias(), NON_ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); - - df.depositTransaction{value: NON_ZERO_VALUE}(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); + emit TransactionDeposited( + addressAlias(), + NON_ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + + df.depositTransaction{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); } // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH @@ -105,22 +176,46 @@ contract DepositFeedTest is DSTest { vm.prank(address(this), address(this)); vm.expectEmit(true, true, false, true); - emit TransactionDeposited(address(this), ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, '0x'); - - uint256 balanceBefore = address(df).balance; - df.depositTransaction{value: NON_ZERO_VALUE}(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, '0x'); - uint256 balanceAfter = address(df).balance; - assertEq(balanceAfter - balanceBefore, NON_ZERO_VALUE); + emit TransactionDeposited( + address(this), + ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + "0x" + ); + + df.depositTransaction{ value: NON_ZERO_VALUE }( + ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + "0x" + ); + assertEq(address(df).balance, NON_ZERO_VALUE); } // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH function test_depositTransaction_withEthValueAndContractContractCreation() external { vm.expectEmit(true, true, false, true); - emit TransactionDeposited(addressAlias(), ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); - - uint256 balanceBefore = address(df).balance; - df.depositTransaction{value: NON_ZERO_VALUE}(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); - uint256 balanceAfter = address(df).balance; - assertEq(balanceAfter - balanceBefore, NON_ZERO_VALUE); + emit TransactionDeposited( + addressAlias(), + ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); + + df.depositTransaction{ value: NON_ZERO_VALUE }( + ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); + assertEq(address(df).balance, NON_ZERO_VALUE); } } diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 5c584eee6869..c32825163969 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -13,7 +13,7 @@ "build": "yarn build:forge && yarn build:hh", "test:hh": "yarn hardhat test", "test:forge": "forge test --root . -c contracts --out forge-artifacts", - "test": "yarn test:forge && yarn test:hh", + "test": "yarn test:forge", "slither": "slither .", "clean": "rm -rf ./artifacts ./forge-artifacts ./cache ./coverage ./tsconfig.build.tsbuildinfo", "lint:ts:check": "eslint .", From 77416ebab60b76fde48fbcb4a26f064f20581006 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 28 Mar 2022 23:57:55 -0400 Subject: [PATCH 366/585] contracts: clean up L1Block test file Makes the boiler plate code match that used in L2OutputOracle.t.sol --- packages/contracts/contracts/test/L1Block.t.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts/contracts/test/L1Block.t.sol index c86107c62125..3f5da9d1d9a8 100644 --- a/packages/contracts/contracts/test/L1Block.t.sol +++ b/packages/contracts/contracts/test/L1Block.t.sol @@ -1,14 +1,12 @@ +//SPDX-License-Identifier: MIT pragma solidity 0.8.10; import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { Vm } from "../../lib/forge-std/src/Vm.sol"; import { L1Block } from "../L2/L1Block.sol"; -interface CheatCodes { - function prank(address) external; -} - contract L1BLockTest is DSTest { - CheatCodes cheats = CheatCodes(HEVM_ADDRESS); + Vm vm = Vm(HEVM_ADDRESS); L1Block lb; address depositor; bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1)); @@ -16,7 +14,7 @@ contract L1BLockTest is DSTest { function setUp() external { lb = new L1Block(); depositor = lb.DEPOSITOR_ACCOUNT(); - cheats.prank(depositor); + vm.prank(depositor); lb.setL1BlockValues(1, 2, 3, NON_ZERO_HASH); } From a1815ebd4efa43e93bdc94928e518d13b337443b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 29 Mar 2022 00:00:12 -0400 Subject: [PATCH 367/585] contracts: Add gas snapshot script and output --- packages/contracts/.gas-snapshot | 16 ++++++++++++++++ packages/contracts/foundry.toml | 2 ++ packages/contracts/package.json | 5 +++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 packages/contracts/.gas-snapshot diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot new file mode 100644 index 000000000000..bd54603744b9 --- /dev/null +++ b/packages/contracts/.gas-snapshot @@ -0,0 +1,16 @@ +test_basefee() (gas: 1068) +test_hash() (gas: 1067) +test_number() (gas: 1068) +test_timestamp() (gas: 1089) +testCannot_appendCurrentTimestamp() (gas: 4179) +testCannot_appendEmptyOutput() (gas: 4253) +testCannot_appendFutureTimestamp() (gas: 4220) +testCannot_appendOutputIfNotSequencer() (gas: 3491) +testCannot_appendUnexpectedTimestamp() (gas: 4435) +testCannot_computePreHistoricalL2BlockNumber() (gas: 2182) +test_appendingAnotherOutput() (gas: 27894) +test_computeL2BlockNumber() (gas: 5105) +test_getL2Output() (gas: 4621) +test_latestBlockTimestamp() (gas: 1169) +test_nextTimestamp() (gas: 1572) +test_constructor() (gas: 6912) diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml index 6aeda3f1c787..f7b69a49b938 100644 --- a/packages/contracts/foundry.toml +++ b/packages/contracts/foundry.toml @@ -3,3 +3,5 @@ src = 'contracts' # We need to build seperate artifacts for forge and hh, because they each expect a different # structure for the artifacts directory. out = 'forge-artifacts' +optimizer = true +optimizer_runs = 999999 diff --git a/packages/contracts/package.json b/packages/contracts/package.json index c32825163969..b8172adb0ccd 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -8,12 +8,13 @@ "hardhat": "^2.7.1" }, "scripts": { - "build:forge": "forge build --root . -c contracts --out forge-artifacts", + "build:forge": "forge build --optimize --root . -c contracts --out forge-artifacts", "build:hh": "yarn hardhat compile", "build": "yarn build:forge && yarn build:hh", "test:hh": "yarn hardhat test", - "test:forge": "forge test --root . -c contracts --out forge-artifacts", "test": "yarn test:forge", + "test:forge": "forge test --optimize --root . -c contracts --out forge-artifacts", + "gas-snapshot": "forge snapshot --optimize --root . -c contracts --out forge-artifacts", "slither": "slither .", "clean": "rm -rf ./artifacts ./forge-artifacts ./cache ./coverage ./tsconfig.build.tsbuildinfo", "lint:ts:check": "eslint .", From 85a4443254693a6038eade6692b4806484dd9c42 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 29 Mar 2022 00:02:01 -0400 Subject: [PATCH 368/585] fix: capitalization in test function --- packages/contracts/.gas-snapshot | 41 +++++++++++-------- .../contracts/test/L2OutputOracle.t.sol | 2 +- packages/contracts/package.json | 6 +-- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index bd54603744b9..50e05d3300cf 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,16 +1,25 @@ -test_basefee() (gas: 1068) -test_hash() (gas: 1067) -test_number() (gas: 1068) -test_timestamp() (gas: 1089) -testCannot_appendCurrentTimestamp() (gas: 4179) -testCannot_appendEmptyOutput() (gas: 4253) -testCannot_appendFutureTimestamp() (gas: 4220) -testCannot_appendOutputIfNotSequencer() (gas: 3491) -testCannot_appendUnexpectedTimestamp() (gas: 4435) -testCannot_computePreHistoricalL2BlockNumber() (gas: 2182) -test_appendingAnotherOutput() (gas: 27894) -test_computeL2BlockNumber() (gas: 5105) -test_getL2Output() (gas: 4621) -test_latestBlockTimestamp() (gas: 1169) -test_nextTimestamp() (gas: 1572) -test_constructor() (gas: 6912) +DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11352) +DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 21076) +DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 21427) +DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 21094) +DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 21467) +DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 28117) +DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 25856) +DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 27785) +DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 25817) +L1BLockTest:test_basefee() (gas: 7509) +L1BLockTest:test_hash() (gas: 7508) +L1BLockTest:test_number() (gas: 7509) +L1BLockTest:test_timestamp() (gas: 7463) +L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20947) +L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19066) +L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 20979) +L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18307) +L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21227) +L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13090) +L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49528) +L2OutputOracleTest:test_computeL2BlockNumber() (gas: 15556) +L2OutputOracleTest:test_getL2Output() (gas: 15073) +L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9610) +L2OutputOracleTest:test_nextTimestamp() (gas: 11943) +L2OutputOracleTest_Constructor:test_constructor() (gas: 29122) diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 433412b0d828..fe7f5eeeb1cd 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -44,7 +44,7 @@ contract L2OutputOracle_Initializer is DSTest { // Define this test in a standalone contract to ensure it runs immediately after the constructor. contract L2OutputOracleTest_Constructor is L2OutputOracle_Initializer { - function test_Constructor() external { + function test_constructor() external { assertEq(oracle.owner(), sequencer); assertEq(oracle.submissionInterval(), submissionInterval); assertEq(oracle.l2BlockTime(), l2BlockTime); diff --git a/packages/contracts/package.json b/packages/contracts/package.json index b8172adb0ccd..582b5980d0cf 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -8,13 +8,13 @@ "hardhat": "^2.7.1" }, "scripts": { - "build:forge": "forge build --optimize --root . -c contracts --out forge-artifacts", + "build:forge": "forge build", "build:hh": "yarn hardhat compile", "build": "yarn build:forge && yarn build:hh", "test:hh": "yarn hardhat test", "test": "yarn test:forge", - "test:forge": "forge test --optimize --root . -c contracts --out forge-artifacts", - "gas-snapshot": "forge snapshot --optimize --root . -c contracts --out forge-artifacts", + "test:forge": "forge test", + "gas-snapshot": "forge snapshot", "slither": "slither .", "clean": "rm -rf ./artifacts ./forge-artifacts ./cache ./coverage ./tsconfig.build.tsbuildinfo", "lint:ts:check": "eslint .", From 6b36dcb2dbdc82df65d9f167146ce213bf415c00 Mon Sep 17 00:00:00 2001 From: Murphy Law Date: Mon, 4 Apr 2022 13:01:42 -0400 Subject: [PATCH 369/585] docs: fix typo in deposits.md --- specs/deposits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index 9b921c4724e5..54abb7b2bf7f 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -234,7 +234,7 @@ The deposit contract handles two special cases: [address-aliasing]: #address-aliasing -If the caller is not a contract, the address will be transformed by adding +If the caller is a contract, the address will be transformed by adding `0x1111000000000000000000000000000000001111` to it. This prevents attacks in which a contract on L1 has the same address as a contract on L2 but doesn't have the same code. We can safely ignore this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes From bac8e40ac7e9176168fe7b041f6ce0298984a645 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 4 Apr 2022 15:08:02 -0700 Subject: [PATCH 370/585] opnode: Extend sync algorithm to SafeHead (#299) The sync start algorithm has been modified to find both a Safe Block and Unsafe Block. The FindL2Heads function first finds the Unsafe Block, and then continues to walk back the L2 chain until it finds and L2 block that can be completely derived from the sequence window that has not been changed in the reorg (i.e. the last block of the window was the reorg base). This FindSyncStart function previously only found the Unsafe Block --- opnode/l1/source.go | 9 +- opnode/rollup/driver/driver.go | 5 +- opnode/rollup/driver/fake_chain.go | 10 + opnode/rollup/driver/state.go | 96 ++++--- opnode/rollup/driver/state_test.go | 6 +- opnode/rollup/sync/start.go | 126 ++++++--- opnode/rollup/sync/start_test.go | 418 ++++++++++++++--------------- opnode/test/setup.go | 5 +- opnode/test/system_test.go | 4 +- specs/rollup-node.md | 66 ++--- 10 files changed, 408 insertions(+), 337 deletions(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index e392d75803ab..f68addab8131 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -137,7 +137,6 @@ func NewSource(client RPCClient, log log.Logger, config *SourceConfig) (*Source, // and parallelized since the RPC server does not parallelize batch contents otherwise. getBatch := parallelBatchCall(log, client.BatchCallContext, config.MaxBatchRetry, config.MaxRequestsPerBatch, config.MaxParallelBatching) - return &Source{ client: client, batchCall: getBatch, @@ -311,6 +310,14 @@ func (s *Source) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1Bl return head.BlockRef(), nil } +func (s *Source) L1BlockRefByHash(ctx context.Context, hash common.Hash) (eth.L1BlockRef, error) { + block, err := s.InfoByHash(ctx, hash) + if err != nil { + return eth.L1BlockRef{}, fmt.Errorf("failed to fetch header by hash %v: %w", hash, err) + } + return block.BlockRef(), nil +} + // L1Range returns a range of L1 block beginning just after begin, up to max blocks. // This batch-requests all blocks by number in the range at once, and then verifies the consistency func (s *Source) L1Range(ctx context.Context, begin eth.BlockID, max uint64) ([]eth.BlockID, error) { diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 2a28bafa7405..8aafcf38e3d5 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -36,8 +36,9 @@ type Engine interface { } type L1Chain interface { - L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) - L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) + L1BlockRefByNumber(context.Context, uint64) (eth.L1BlockRef, error) + L1BlockRefByHash(context.Context, common.Hash) (eth.L1BlockRef, error) + L1HeadBlockRef(context.Context) (eth.L1BlockRef, error) L1Range(ctx context.Context, base eth.BlockID, max uint64) ([]eth.BlockID, error) } diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 6c79f0104ea3..6f3e590f3365 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -120,6 +120,16 @@ func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) return m.l1s[m.l1reorg][l1Num], nil } +func (m *fakeChainSource) L1BlockRefByHash(ctx context.Context, l1Hash common.Hash) (eth.L1BlockRef, error) { + m.log.Trace("L1BlockRefByHash", "l1Hash", l1Hash, "l1Head", m.l1head, "reorg", m.l1reorg) + for i, bl := range m.l1s[m.l1reorg] { + if bl.Hash == l1Hash { + return m.L1BlockRefByNumber(ctx, uint64(i)) + } + } + return eth.L1BlockRef{}, ethereum.NotFound +} + func (m *fakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { m.log.Trace("L1HeadBlockRef", "l1Head", m.l1head, "reorg", m.l1reorg) l := len(m.l1s[m.l1reorg]) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 218e9927a098..59f4e9e9e641 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -108,17 +108,27 @@ func (s *state) sequencingWindow() ([]eth.BlockID, bool) { return s.l1WindowBuf[:int(s.Config.SeqWindowSize)], true } -func (s *state) findNextL1Origin(ctx context.Context) (eth.BlockID, error) { - return s.l1Head.ID(), nil // Temporary until timestamps are working correctly +func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { // [prev L2 + blocktime, L1 Bock) - // currentL1Origin := s.l2Head.L1Origin - // s.log.Info("Find next l1Origin", "l2Head", s.l2Head, "l1Origin", currentL1Origin) - // if s.l2Head.Time+int64(s.Config.BlockTime) >= currentL1Origin.Time { - // ref, err := s.l1.L1BlockRefByNumber(ctx, currentL1Origin.Number+1) - // s.log.Info("Lookuing up new L1 Origin", "nextL1Origin", ref) - // return ref.Self, err - // } - // return currentL1Origin, nil + if s.l2Head.L1Origin.Hash == s.l1Head.Hash { + return s.l1Head, nil + } + curr, err := s.l1.L1BlockRefByHash(ctx, s.l2Head.L1Origin.Hash) + if err != nil { + return eth.L1BlockRef{}, err + } + + s.log.Info("Find next l1Origin", "l2Head", s.l2Head, "l1Origin", curr) + // TODO: There is an interaction with not using the L1 Genesis as an L1 Origin and + // the fact that the L2 Genesis time needs to be set around the L1 Genesis such + // that this check will return true. + if s.l2Head.Time+s.Config.BlockTime >= curr.Time { + // TODO: Need to walk more? + ref, err := s.l1.L1BlockRefByNumber(ctx, curr.Number+1) + s.log.Info("Looking up new L1 Origin", "nextL1Origin", ref) + return ref, err + } + return curr, nil } func (s *state) loop() { @@ -131,15 +141,21 @@ func (s *state) loop() { l2BlockCreation = l2BlockCreationTicker.C } - // l1Poll := time.NewTicker(1 * time.Second) - // l2Poll := time.NewTicker(1 * time.Second) stepRequest := make(chan struct{}, 1) - // defer l1Poll.Stop() - // defer l2Poll.Stop() + l2BlockCreationReq := make(chan struct{}, 1) + + createBlock := func() { + select { + case l2BlockCreationReq <- struct{}{}: + // Don't deadlock if the channel is already full + default: + } + } requestStep := func() { select { case stepRequest <- struct{}{}: + // Don't deadlock if the channel is already full default: } } @@ -148,28 +164,34 @@ func (s *state) loop() { for { select { - // TODO: Poll cases (and move to bottom) - // case <-l1Poll.C: - // case <-l2Poll.C: case <-s.done: atomic.AddUint32(&s.closed, 1) return case <-l2BlockCreation: + s.log.Trace("L2 Creation Ticker") + createBlock() + case <-l2BlockCreationReq: nextOrigin, err := s.findNextL1Origin(context.Background()) if err != nil { + s.log.Error("Error finding next L1 Origin") + continue + } + if nextOrigin.Time <= s.Config.BlockTime+s.l2Head.Time { + s.log.Trace("Skipping block production", "l2Head", s.l2Head) continue } // Don't produce blocks until past the L1 genesis if nextOrigin.Number <= s.Config.Genesis.L1.Number { + s.log.Trace("Skipping block production b/c origin behind genesis") continue } // 2. Ask output to create new block - newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2Head, s.l2SafeHead.ID(), nextOrigin) + newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2Head, s.l2SafeHead.ID(), nextOrigin.ID()) if err != nil { s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", nextOrigin) continue } - // 3. Update unsafe l2 head + epoch + // 3. Update unsafe l2 head s.l2Head = newUnsafeL2Head s.log.Trace("Created new l2 block", "l2UnsafeHead", s.l2Head) // 4. Ask for batch submission @@ -182,43 +204,40 @@ func (s *state) loop() { s.log.Error("Error submitting batch", "err", err) } }() + if nextOrigin.Time > s.l2Head.Time+s.Config.BlockTime { + s.log.Trace("Asking for a second L2 block asap", "l2Head", s.l2Head) + createBlock() + } case newL1Head := <-s.l1Heads: s.log.Trace("Received new L1 Head", "new_head", newL1Head, "old_head", s.l1Head) - // Check if we have a stutter step. May be due to a L1 Poll operation. if s.l1Head.Hash == newL1Head.Hash { log.Trace("Received L1 head signal that is the same as the current head", "l1_head", newL1Head) - continue - } - - // Typically get linear extension, but if not, handle a re-org - if s.l1Head.Hash == newL1Head.ParentHash { + } else if s.l1Head.Hash == newL1Head.ParentHash { s.log.Trace("Linear extension") s.l1Head = newL1Head if s.l1WindowBufEnd().Hash == newL1Head.ParentHash { s.l1WindowBuf = append(s.l1WindowBuf, newL1Head.ID()) } } else { + // Not strictly always a reorg, but that is the most likely case s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.ParentHash, "new_l1_head", newL1Head) - // TODO(Joshua): Fix having to make this call when being careful about the exact state - l2Head, err := s.l2.L2BlockRefByNumber(context.Background(), nil) + unsafeL2Head, safeL2Head, err := sync.FindL2Heads(ctx, s.l2Head, int(s.Config.SeqWindowSize), s.l1, s.l2, &s.Config.Genesis) if err != nil { - s.log.Error("Could not get fetch L2 head when trying to handle a re-org", "err", err) - continue - } - nextL2Head, err := sync.FindSafeL2Head(ctx, l2Head.ID(), s.l1, s.l2, &s.Config.Genesis) - if err != nil { - s.log.Error("Could not get new safe L2 head when trying to handle a re-org", "err", err) + s.log.Error("Could not get new unsafe L2 head when trying to handle a re-org", "err", err) continue } + // TODO: Fork choice update s.l1Head = newL1Head s.l1WindowBuf = nil - s.l2Head = nextL2Head - s.l2SafeHead = nextL2Head // TODO: Handle this more carefully + s.l2Head = unsafeL2Head // Note that verify only nodes can get an unsafe head because of a reorg. May want to remove that. + s.l2SafeHead = safeL2Head + s.log.Trace("State update", "l1Head", s.l1Head, "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead) } // Run step if we are able to if s.l1Head.Number-s.l2Head.L1Origin.Number >= s.Config.SeqWindowSize { + s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) requestStep() } case <-stepRequest: @@ -238,7 +257,7 @@ func (s *state) loop() { // Get next window (& ensure that it exists) if window, ok := s.sequencingWindow(); ok { - s.log.Trace("Have enough cached blocks to run step.") + s.log.Trace("Have enough cached blocks to run step.", "window", window) ctx, cancel := context.WithTimeout(ctx, 10*time.Second) newL2Head, err := s.output.step(ctx, s.l2SafeHead, s.l2Finalized, s.l2Head.ID(), window) cancel() @@ -246,9 +265,7 @@ func (s *state) loop() { s.log.Error("Error in running the output step.", "err", err, "l2SafeHead", s.l2SafeHead, "l2Finalized", s.l2Finalized, "window", window) continue } - if s.l2Head == s.l2SafeHead { - s.l2Head = newL2Head - } + s.l2Head = newL2Head s.l2SafeHead = newL2Head s.l1WindowBuf = s.l1WindowBuf[1:] // TODO: l2Finalized @@ -258,6 +275,7 @@ func (s *state) loop() { // Immediately run next step if we have enough blocks. if s.l1Head.Number-s.l2Head.L1Origin.Number >= s.Config.SeqWindowSize { + s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) requestStep() } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index a91b57a88914..5f82732c4f9d 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -115,6 +115,7 @@ func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") } src.reorgL2() + outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} } @@ -128,14 +129,15 @@ type stateTestCase struct { } func (tc *stateTestCase) Run(t *testing.T) { - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LvlTrace) chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) l1headsCh := make(chan eth.L1BlockRef, 10) // Unbuffered channels to force a sync point between the test and the state loop. outputIn := make(chan outputArgs) outputReturn := make(chan outputReturnArgs) outputHandler := func(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) { - outputIn <- outputArgs{l2Head: l2Head.ID(), l2Finalized: l2Finalized, l1Window: l1Input} + // TODO: Not sequencer, but need to pass unsafeL2Head here for the test. + outputIn <- outputArgs{l2Head: unsafeL2Head, l2Finalized: l2Finalized, l1Window: l1Input} r := <-outputReturn return r.l2Head, r.err } diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index ba7ff7e5d64e..59bd662fdc4e 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -11,9 +11,9 @@ // Each optimism block retains a reference to an L1 block and to its parent L2 block. // The L2 chain node must satisfy the following validity rules // 1. l2block.height == l2parent.block.height + 1 -// 2. l2block.l1parent.height >= l2block.l2parent.l1parent.height -// 3. l2block.l1parent is in the canonical chain on L1 -// 4. l1_rollup_genesis is reachable from l2block.l1parent +// 2. l2block.l1Origin.height >= l2block.l2parent.l1Origin.height +// 3. l2block.l1Origin is in the canonical chain on L1 +// 4. l1_rollup_genesis is an ancestor of l2block.l1Origin // // // During normal operation, both the L1 and L2 canonical chains can change, due to a reorg @@ -23,19 +23,23 @@ // - L2 reorg // - L2 extension // -// When one of these changes occurs, the rollup node needs to determine what the new L2 Head should be. +// When one of these changes occurs, the rollup node needs to determine what the new L2 Heads should be. // In a simple extension case, the L2 head remains the same, but in the case of a re-org on L1, it needs -// to find the first L2 block where the l1parent is in the L1 canonical chain. -// In the case of a re-org, it is also helpful to obtain the L1 blocks after the L1 base to re-start the -// chain derivation process. - +// to find the unsafe and safe blocks. +// +// Unsafe Block: The highest L2 block. If the L1 Attributes is ahead of the L1 head, it is assumed to be valid, +// if not, it walks back until it finds the first L2 block whose L1 Origin is canonical in the L1 chain. +// Safe Block: The highest L2 block whose sequence window has not changed during a reorg. +// +// The safe block can be found by walking back one sequence window from the "latest" L2 block. The latest L2 +// block is the first L2 block whose L1 Origin is canonical in L1. If the unsafe block is ahead of the L1 +// chain, the latest block and unsafe block are not the same. package sync import ( "context" "errors" "fmt" - "math/big" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -45,12 +49,11 @@ import ( ) type L1Chain interface { - L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) + L1BlockRefByNumber(ctx context.Context, number uint64) (eth.L1BlockRef, error) } type L2Chain interface { - L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) } @@ -59,45 +62,96 @@ var TooDeepReorgErr = errors.New("reorg is too deep") const MaxReorgDepth = 500 -// FindSafeL2Head takes the supplied L2 start block and walks the L2 chain until it finds the first L2 block reachable from the supplied -// block that is also canonical. -func FindSafeL2Head(ctx context.Context, start eth.BlockID, l1 L1Chain, l2 L2Chain, genesis *rollup.Genesis) (eth.L2BlockRef, error) { - // Starting point - l2Head, err := l2.L2BlockRefByHash(ctx, start.Hash) - if err != nil { - return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 head: %w", err) +// isCanonical returns true if the supplied block ID is canonical in the L1 chain. +// It will suppress ethereum.NotFound errors +func isCanonical(ctx context.Context, l1 L1Chain, block eth.BlockID) (bool, error) { + canonical, err := l1.L1BlockRefByNumber(ctx, block.Number) + if err != nil && !errors.Is(err, ethereum.NotFound) { + return false, err + } else if err != nil { + return false, nil } + return canonical.Hash == block.Hash, nil +} + +// FindL2Heads walks back from the supplied L2 blocks and finds the unsafe and safe L2 blocks. +// Unsafe Block: The highest L2 block. If the L1 Attributes is ahead of the L1 head, it is assumed to be valid, +// if not, it walks back until it finds the first L2 block whose L1 Origin is canonical in the L1 chain. +// Safe Block: The highest L2 block whose sequence window has not changed during a reorg. +func FindL2Heads(ctx context.Context, start eth.L2BlockRef, seqWindowSize int, + l1 L1Chain, l2 L2Chain, genesis *rollup.Genesis) (unsafe eth.L2BlockRef, safe eth.L2BlockRef, err error) { reorgDepth := 0 - // Walk L2 chain from L2 head to first L2 block which has a L1 Parent that is canonical. May walk to L2 genesis - for n := l2Head; ; { - l1header, err := l1.L1BlockRefByNumber(ctx, n.L1Origin.Number) - if err != nil { - // Generic error, bail out. - if !errors.Is(err, ethereum.NotFound) { - return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L1 block %v: %w", n.L1Origin.Number, err) - } - // L1 block not found, keep walking chain - } else { - // L1 Block found, check if matches & should keep walking the chain - if l1header.Hash == n.L1Origin.Hash { - return n, nil + var prevL1OriginHash common.Hash + // First check if the L1 Origin of the start block is ahead of the current L1 head + // If so, we assume that this should be the next unsafe head for the sequencing window + // We still need to walk back the safe head because we don't know where the reorg started. + l1Head, err := l1.L1HeadBlockRef(ctx) + if err != nil { + return eth.L2BlockRef{}, eth.L2BlockRef{}, err + } + l2Ahead := start.L1Origin.Number > l1Head.Number + var latest eth.L2BlockRef + + // Walk L2 chain until we find the "latest" L2 block. This the first L2 block whose L1 Origin is canonical. + for n := start; ; { + // Check if l1Origin is canonical when we get to a new epoch + if prevL1OriginHash != n.L1Origin.Hash { + if ok, err := isCanonical(ctx, l1, n.L1Origin); err != nil { + return eth.L2BlockRef{}, eth.L2BlockRef{}, err + } else if ok { + latest = n + break } + prevL1OriginHash = n.L1Origin.Hash } - // Don't walk past genesis. If we were at the L2 genesis, but could not find the L1 genesis // pointed to from it, we are on the wrong L1 chain. if n.Hash == genesis.L2.Hash || n.Number == genesis.L2.Number { - return eth.L2BlockRef{}, WrongChainErr + return eth.L2BlockRef{}, eth.L2BlockRef{}, WrongChainErr } - // Pull L2 parent for next iteration n, err = l2.L2BlockRefByHash(ctx, n.ParentHash) if err != nil { - return eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) + return eth.L2BlockRef{}, eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) } reorgDepth++ if reorgDepth >= MaxReorgDepth { - return eth.L2BlockRef{}, TooDeepReorgErr + return eth.L2BlockRef{}, eth.L2BlockRef{}, TooDeepReorgErr } } + depth := 1 // SeqWindowSize is a length, but we are counting elements in the window. + prevL1OriginHash = latest.L1Origin.Hash + // Walk from the latest block back 1 Sequence Window of L1 Origins to determine the safe L2 block. + for n := latest; ; { + // Advance depth if new origin + if n.L1Origin.Hash != prevL1OriginHash { + depth++ + prevL1OriginHash = n.L1Origin.Hash + } + // Walked sufficiently far + if depth == seqWindowSize { + if l2Ahead { + return start, n, nil + } else { + return latest, n, nil + } + + } + // Genesis is always safe. + if n.Hash == genesis.L2.Hash || n.Number == genesis.L2.Number { + safe = eth.L2BlockRef{Hash: genesis.L2.Hash, Number: genesis.L2.Number, Time: genesis.L2Time, L1Origin: genesis.L1} + if l2Ahead { + return start, safe, nil + } else { + return latest, safe, nil + } + + } + // Pull L2 parent for next iteration + n, err = l2.L2BlockRefByHash(ctx, n.ParentHash) + if err != nil { + return eth.L2BlockRef{}, eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) + } + } + } diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index d7cd55e14f78..3c7914b434f7 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -2,72 +2,38 @@ package sync import ( "context" - "math/big" "testing" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type fakeChainSource struct { L1 []eth.L1BlockRef - L2 []eth.L2BlockRef -} - -func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID) ([]eth.BlockID, error) { - var out []eth.BlockID - found := false - for _, b := range m.L1 { - if found { - out = append(out, b.ID()) - } - if b.ID() == base { - found = true - } - } - if found { - return out, nil - } - return nil, ethereum.NotFound -} - -func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { - if l1Num >= uint64(len(m.L1)) { - return eth.L1BlockRef{}, ethereum.NotFound - } - return m.L1[l1Num], nil + L2 map[common.Hash]eth.L2BlockRef } func (m *fakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { - l := len(m.L1) - if l == 0 { - return eth.L1BlockRef{}, ethereum.NotFound - } - return m.L1[l-1], nil + return m.L1[len(m.L1)-1], nil } -func (m *fakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { - if len(m.L2) == 0 { - panic("bad test, no l2 chain") - } - i := uint64(len(m.L2) - 1) - if l2Num != nil { - i = l2Num.Uint64() +func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, number uint64) (eth.L1BlockRef, error) { + n := int(number) + if n >= len(m.L1) { + return eth.L1BlockRef{}, ethereum.NotFound } - return m.L2[i], nil + return m.L1[n], nil } func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { - for i, bl := range m.L2 { - if bl.Hash == l2Hash { - return m.L2BlockRefByNumber(ctx, big.NewInt(int64(i))) - } + ref, ok := m.L2[l2Hash] + if !ok { + return eth.L2BlockRef{}, ethereum.NotFound } - return eth.L2BlockRef{}, ethereum.NotFound + return ref, nil } var _ L1Chain = (*fakeChainSource)(nil) @@ -97,39 +63,57 @@ func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L return eth.L2BlockRef{Hash: id.Hash, Number: id.Number, ParentHash: parentID.Hash, L1Origin: l1parent} } -func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { +func (c *syncStartTestCase) generateFakeL2() (*fakeChainSource, eth.L2BlockRef, rollup.Genesis) { + var l1 []eth.L1BlockRef + var newl1 []eth.L1BlockRef var prevID rune - for i, id := range ids { - out = append(out, fakeL1Block(id, prevID, offset+uint64(i))) + for i, id := range c.L1 { + l1 = append(l1, fakeL1Block(id, prevID, uint64(i))) + // fmt.Printf("%v\t%v\n", l1[i].Self, l1[i].Parent) + prevID = id + } + prevID = rune(0) + for i, id := range c.NewL1 { + newl1 = append(newl1, fakeL1Block(id, prevID, uint64(i))) + // fmt.Printf("%v\t%v\n", newl1[i].Self, newl1[i].Parent) prevID = id } - return -} -func chainL2(l1 []eth.L1BlockRef, ids string) (out []eth.L2BlockRef) { - var prevID rune - for i, id := range ids { - out = append(out, fakeL2Block(id, prevID, l1[i].ID(), uint64(i))) + prevID = rune(0) + var head eth.L2BlockRef + m := make(map[common.Hash]eth.L2BlockRef) + for i, id := range c.L2 { + b := fakeL2Block(id, prevID, l1[i+int(c.GenesisL1Num)].ID(), uint64(i)+c.GenesisL2Num) + m[b.Hash] = b + // fmt.Printf("%v\t%v\t%v\n", b.Self, b.Parent, b.L1Origin) prevID = id + head = b + } + genesis := rollup.Genesis{ + L1: fakeID(c.GenesisL1, c.GenesisL1Num), + L2: fakeID(c.GenesisL2, c.GenesisL2Num), } - return + return &fakeChainSource{L1: newl1, L2: m}, head, genesis + } type syncStartTestCase struct { Name string - OffsetL2 uint64 - EngineL1 string // L1 Chain prior to a re-org or other change - EngineL2 string // L2 Chain that follows from L1Chain - ActualL1 string // L1 Chain after a change may have occurred + L1 string // L1 Chain prior to a re-org or other change + L2 string // L2 Chain that follows from L1Chain + NewL1 string // New L1 chain + ReorgBase rune // Highest L1 block in the pre and post re-org L1 chian - GenesisL1 rune - GenesisL2 rune + GenesisL1 rune + GenesisL1Num uint64 + GenesisL2 rune + GenesisL2Num uint64 - ExpectedNextRefsL1 string // The L1 extension to follow (i.e. L1 after the L1 parent in the new L2 Head) - ExpectedRefL2 rune // The new L2 tip after a L1 change that may have occurred - - ExpectedErr error + SeqWindowSize int + SafeL2Head rune + UnsafeL2Head rune + ExpectedErr error } func refToRune(r eth.BlockID) rune { @@ -137,198 +121,188 @@ func refToRune(r eth.BlockID) rune { } func (c *syncStartTestCase) Run(t *testing.T) { - engL1 := chainL1(c.OffsetL2, c.EngineL1) - engL2 := chainL2(engL1, c.EngineL2) - actL1 := chainL1(0, c.ActualL1) + msr, l2Head, genesis := c.generateFakeL2() - msr := &fakeChainSource{ - L2: engL2, - L1: actL1, - } - - genesis := &rollup.Genesis{ - L1: fakeID(c.GenesisL1, c.OffsetL2), - L2: fakeID(c.GenesisL2, 0), - } - head, err := msr.L2BlockRefByNumber(context.Background(), nil) - require.Nil(t, err) - refL2, err := FindSafeL2Head(context.Background(), head.ID(), msr, msr, genesis) + unsafeL2Head, safeHead, err := FindL2Heads(context.TODO(), l2Head, c.SeqWindowSize, msr, msr, &genesis) if c.ExpectedErr != nil { - assert.Error(t, err, "Expecting an error in this test case") - assert.ErrorIs(t, err, c.ExpectedErr) + require.Error(t, err, "Expecting an error in this test case") + require.ErrorIs(t, c.ExpectedErr, err, "Unexpected error") } else { - nextRefL1s, err := msr.L1Range(context.Background(), refL2.L1Origin) - require.Nil(t, err) - expectedRefL2 := refToRune(refL2.ID()) - var expectedRefsL1 []rune - for _, ref := range nextRefL1s { - expectedRefsL1 = append(expectedRefsL1, refToRune(ref)) - } - assert.NoError(t, err) - assert.Equal(t, c.ExpectedNextRefsL1, string(expectedRefsL1), "Next L1 refs not equal") - assert.Equal(t, expectedRefL2, c.ExpectedRefL2, "Next L2 Head not equal") + require.NoError(t, err) + expectedUnsafeHead := refToRune(unsafeL2Head.ID()) + require.Equal(t, string(c.UnsafeL2Head), string(expectedUnsafeHead), "Unsafe L2 Head not equal") + + expectedSafeHead := refToRune(safeHead.ID()) + require.Equal(t, string(c.SafeL2Head), string(expectedSafeHead), "Safe L2 Head not equal") } } func TestFindSyncStart(t *testing.T) { testCases := []syncStartTestCase{ { - Name: "happy extend", - OffsetL2: 0, - EngineL1: "ab", - EngineL2: "AB", - ActualL1: "abc", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "c", - ExpectedRefL2: 'B', - ExpectedErr: nil, + Name: "already synced", + GenesisL1Num: 0, + L1: "ab", + L2: "AB", + NewL1: "ab", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'B', + SeqWindowSize: 2, + SafeL2Head: 'A', + ExpectedErr: nil, }, { - Name: "extend one at a time", - OffsetL2: 0, - EngineL1: "ab", - EngineL2: "AB", - ActualL1: "abcdef", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "cdef", - ExpectedRefL2: 'B', - ExpectedErr: nil, + Name: "small reorg long chain", + GenesisL1Num: 0, + L1: "abcdefgh", + L2: "ABCDEFGH", + NewL1: "abcdefgx", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'G', + SeqWindowSize: 2, + SafeL2Head: 'F', + ExpectedErr: nil, }, { - Name: "already synced", - OffsetL2: 0, - EngineL1: "abcde", - EngineL2: "ABCDE", - ActualL1: "abcde", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "", - ExpectedRefL2: 'E', - ExpectedErr: nil, + Name: "L1 Chain ahead", + GenesisL1Num: 0, + L1: "abcde", + L2: "ABCD", + NewL1: "abcde", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'D', + SeqWindowSize: 3, + SafeL2Head: 'B', + ExpectedErr: nil, }, { - Name: "genesis", - OffsetL2: 0, - EngineL1: "a", - EngineL2: "A", - ActualL1: "a", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "", - ExpectedRefL2: 'A', - ExpectedErr: nil, + Name: "L2 Chain ahead after reorg", + GenesisL1Num: 0, + L1: "abxyz", + L2: "ABXYZ", + NewL1: "abx", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'Z', + SeqWindowSize: 2, + SafeL2Head: 'B', + ExpectedErr: nil, }, { - Name: "reorg two steps back", - OffsetL2: 0, - EngineL1: "abc", - EngineL2: "ABC", - ActualL1: "axy", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "xy", - ExpectedRefL2: 'A', - ExpectedErr: nil, + Name: "genesis", + GenesisL1Num: 0, + L1: "a", + L2: "A", + NewL1: "a", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'A', + SeqWindowSize: 2, + SafeL2Head: 'A', + ExpectedErr: nil, }, { - Name: "Orphan block", - OffsetL2: 0, - EngineL1: "abcd", - EngineL2: "ABCD", - ActualL1: "abcx", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "x", - ExpectedRefL2: 'C', - ExpectedErr: nil, + Name: "reorg one step back", + GenesisL1Num: 0, + L1: "abcd", + L2: "ABCD", + NewL1: "abcx", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'C', + SeqWindowSize: 3, + SafeL2Head: 'A', + ExpectedErr: nil, }, { - Name: "L2 chain ahead", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "abc", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "", - ExpectedRefL2: 'C', - ExpectedErr: nil, + Name: "reorg two steps back", + GenesisL1Num: 0, + L1: "abc", + L2: "ABC", + NewL1: "axy", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'A', + SeqWindowSize: 2, + SafeL2Head: 'A', + ExpectedErr: nil, }, { - Name: "L2 chain ahead reorg", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "abcx", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "x", - ExpectedRefL2: 'C', - ExpectedErr: nil, + Name: "reorg three steps back", + GenesisL1Num: 0, + L1: "abcdef", + L2: "ABCDEF", + NewL1: "abcxyz", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'C', + SeqWindowSize: 2, + SafeL2Head: 'B', + ExpectedErr: nil, }, { - Name: "unexpected L1 chain", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "xyz", - GenesisL1: 'a', - GenesisL2: 'A', - ExpectedNextRefsL1: "", - ExpectedRefL2: 0, - ExpectedErr: WrongChainErr, + Name: "unexpected L1 chain", + GenesisL1Num: 0, + L1: "abcdef", + L2: "ABCDEF", + NewL1: "xyzwio", + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 0, + ExpectedErr: WrongChainErr, }, { - Name: "unexpected L2 chain", - OffsetL2: 0, - EngineL1: "abcdef", - EngineL2: "ABCDEF", - ActualL1: "xyz", - GenesisL1: 'a', - GenesisL2: 'X', - ExpectedNextRefsL1: "", - ExpectedRefL2: 0, - ExpectedErr: WrongChainErr, + Name: "unexpected L2 chain", + GenesisL1Num: 0, + L1: "abcdef", + L2: "ABCDEF", + NewL1: "xyzwio", + GenesisL1: 'a', + GenesisL2: 'X', + UnsafeL2Head: 0, + ExpectedErr: WrongChainErr, }, { - Name: "offset L2 genesis extend", - OffsetL2: 3, - EngineL1: "def", - EngineL2: "DEF", - ActualL1: "abcdefg", - GenesisL1: 'd', - GenesisL2: 'D', - ExpectedNextRefsL1: "g", - ExpectedRefL2: 'F', - ExpectedErr: nil, + Name: "offset L2 genesis", + GenesisL1Num: 3, + L1: "abcdef", + L2: "DEF", + NewL1: "abcdef", + GenesisL1: 'd', + GenesisL2: 'D', + UnsafeL2Head: 'F', + SeqWindowSize: 2, + SafeL2Head: 'E', + ExpectedErr: nil, }, { - Name: "offset L2 genesis reorg", - OffsetL2: 3, - EngineL1: "defgh", - EngineL2: "DEFGH", - ActualL1: "abcdx", - GenesisL1: 'd', - GenesisL2: 'D', - ExpectedNextRefsL1: "x", - ExpectedRefL2: 'D', - ExpectedErr: nil, + Name: "offset L2 genesis reorg", + GenesisL1Num: 3, + L1: "abcdefgh", + L2: "DEFGH", + NewL1: "abcdxyzw", + GenesisL1: 'd', + GenesisL2: 'D', + UnsafeL2Head: 'D', + SeqWindowSize: 2, + SafeL2Head: 'D', + ExpectedErr: nil, }, { - Name: "reorg past offset genesis", - OffsetL2: 3, - EngineL1: "abcdefgh", - EngineL2: "ABCDEFGH", - ActualL1: "abx", - GenesisL1: 'd', - GenesisL2: 'D', - ExpectedNextRefsL1: "", - ExpectedRefL2: 0, - ExpectedErr: WrongChainErr, + Name: "reorg past offset genesis", + GenesisL1Num: 3, + L1: "abcdefgh", + L2: "DEFGH", + NewL1: "abxyzwio", + GenesisL1: 'd', + GenesisL2: 'D', + UnsafeL2Head: 0, + ExpectedErr: WrongChainErr, }, } diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 0d0c62f68953..f4975da4913e 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -151,8 +151,9 @@ func initializeGenesis(cfg *systemConfig) { Difficulty: common.Big1, GasLimit: 5000000, Nonce: 4660, - Timestamp: genesisTimestamp, - BaseFee: big.NewInt(7), + // Set the L2 timestamps to be before the timestamp of the rollup genesis's L1 Block Timestamp. This is to match the current implementation of timestamps. + Timestamp: genesisTimestamp - 1, + BaseFee: big.NewInt(7), } cfg.l1.ethConfig.Genesis = l1Genesis diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 26a722d33763..470c39cdb6f9 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -312,7 +312,7 @@ func TestSystemE2E(t *testing.T) { // Finally send TX mintAmount := big.NewInt(1_000_000_000_000) - tx, err = depositContract.DepositTransaction(opts, fromAddr, mintAmount, big.NewInt(1_000_000), false, nil) + _, err = depositContract.DepositTransaction(opts, fromAddr, mintAmount, big.NewInt(1_000_000), false, nil) require.Nil(t, err, "with deposit tx") // Wait for tx to be mined on L1 (or timeout) @@ -331,7 +331,9 @@ func TestSystemE2E(t *testing.T) { defer cancel() receipt, err := l1Client.TransactionReceipt(ctx, tx.Hash()) require.Nil(t, err, "Could not get transaction receipt") + // TODO: Include fix for this. waitNumber := new(big.Int).Add(receipt.BlockNumber, common.Big2) // sequence window effect + waitNumber = new(big.Int).Mul(waitNumber, common.Big2) // Wait (or timeout) for that block to show up on L2 timeoutCh := time.After(6 * time.Second) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 9658dcc8cacc..4b68c0083943 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -373,43 +373,45 @@ The [previous section on L2 chain derivation][l2-chain-derivation] assumes linea also applicable for batch processing, meaning that any given point in time, the canonical L2 chain is given by processing the whole L1 chain since the [L2 chain inception][g-inception]. -> By itself, the previous section fully specifies the behaviour of the rollup driver. **The current section is +If the L1 Chain re-orgs, the rollup node must re-derive sections of the L2 chain such that it derives the same L2 chain +that a rollup node would derive if it only followed the new L1 chain. + +> By itself, the previous section fully specifies the behavior of the rollup driver. **The current section is > non-specificative** but shows how L1 re-orgs can be handled in practice. In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally [re-organize][g-reorg], meaning the head of the L1 chain changes to a block that is not the child of the previous head but rather another descendant of an ancestor of the previous head. In that case, the rollup driver must first search for the common L1 -ancestor, and can re-derive the L2 chain from that L1 block and onwards. - -The starting point of the re-derivation is a pair `(refL2, nextRefL1)` where `refL2` refers to the L2 block to build -upon and `nextRefL1` refers to the next L1 block to derive from (i.e. if `refL2` is derived from L1 block `refL1`, -`nextRefL1` is the canonical L1 block at height `l1Number(refL1) + 1`). - -In practice, the happy path (no re-org) and the re-org paths are merged. The happy path is simply a special case of the -re-org path where the starting point of the re-derivation is `(currentL2Head, newL1Block)`. - -After a `(currentL2Head, newL1Block)` starting point is found, derivation can continue when a complete sequencing window -of canonical L1 blocks following the starting point is retrieved. - -This re-derivation starting point can be found by applying the following algorithm: - -1. (Initialization) Set the initial `refL2` to the head block of the L2 execution engine. -2. Set `parentL2` to `refL2`'s parent block and `refL1` to the L1 block that `refL2` was derived from. -3. Fetch `currentL1`, the canonical L1 block at the same height as `refL1`. - -- If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: - - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the - re-derivation. - - It is necessary to ensure that no L1 re-org occurred during this lookup, i.e. that `nextRefL1.parent == refL1`. - - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the - process. -- Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that - requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration) (\*) -- Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this - algorithm from step 2. - - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. - - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an - extra lookup. +ancestor, and can re-derive the L2 chain from that L1 block and onward. + +The rollup node maintains two heads of the L2 Chain: the unsafe head (often called head) and the safe head. +Each L2 block has an L1 Attributes block that it references in the L1 Info deposit transaction. +The unsafe head is the head of the L2 chain. It's L1 Attributes should be canonical or potentially extending the +canonical chain (if the rollup node has not yet seen the L1 block that it is based upon). +The safe head is the the last L2 block of the last epoch whose sequencing window is complete +(i.e. the epoch with number `L1Head.number` - `SEQUENCING_WINDOW_SIZE`). + +Steps during a reorg + +1. Set "unsafe head" to equal the l2 head we retrieved, just as default +2. Set "latest block" to equal the l2 head we retrieved, also just as default +3. Walk back L2, and stop until block.l1Origin is found AND canonical, and update "latest block" to this block. +And don't override "unsafe head" if it's not found, but do override it when block.l1Origin does not match the +canonical L1 block at that height. +4. Walk back L2 from the "latest block" until a full sequencing window of L1 blocks has been passed. +This is the "safe block". + +The purpose of this is to ensure that if the sequencing window for a L2 block has changed since it was derived, +that L2 block is re-derived. + +The first L1 block of the sequencing window is the L1 attributes for that L2 block. The end of the sequencing +window is the canonical L1 block whose number is `SEQUENCING_WINDOW` larger than the start. The end of the +window must be selected by number otherwise the sequencer would not be able to create batches. The problem +with selecting the end of the window by number is that when an L1 reorg occurs, the blocks (and thus batches) +in the window could change. We must find the find the first L2 block whose complete sequencing window is +unchanged in the reorg. + +When walking back on the L2 chain, care should be taken to not walk past the rollup genesis. Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, approximately 12 minutes). From 0e126cbf47b52367c8fea3ee354893bad1529a44 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 4 Apr 2022 18:20:36 -0700 Subject: [PATCH 371/585] opnode: Reconcile epochs and handle reorgs (#309) * opnode: Switch to uint64 in FindL2Heads function * opnode: Properly initialize state loop This properly sets the L1 head, L2 Head, and L2 Unsafe Head during `state.Start()` in normal operation and when the current L1 head has not reached the L1 genesis. * opnode: Rename output functions The old names where not good. In addition, this standardizes the order of arguements and extends the returns. The returns are not fully used, but will be. * opnode: Add sanity check to L1 window in insertEpoch This make sure that the L1 window starts at the correct block. * opnode: Split out loop Now each action occurs in a seperate function. The state loop is still responsible for sequencing follow-up actions, but is not responsible for setting state. * opnode: Better name for batch prepare functions This name indicates that it provides missing batches. * opnode: Verify epochs as sequencer Sequencers now verify epochs and will reorg if they see that verified epochs do not match what they created. * opnode: Mute driver test * opnode: Set L2 Geth forkchoice on reorg This is required to handle L1 reorgs (rather than just missing batches). * opnode: Bump op-geth version Needed to fix a bug where the L2 geth node was missing the `mint` field in deposit transactions when returning them over the JSON RPC server. * opnode: Don't incorrectly advance safehead There is some L2 block that is possible to fully derive from L1; however, if it is ahead of the current state's safe head, do not advance the current state's safehead because the chain has not been verified up to that point. * opnode: Don't rebuild L1 Genesis Block ID Co-authored-by: Diederik Loerakker * opnode: More comments Co-authored-by: Diederik Loerakker * opnode: Don't cast slice Co-authored-by: Diederik Loerakker * opnode: PR comments * opnode: Better error reason in attributesMatch Include the details of the mismatched fields in addition to what field it was. Will make diagnosing errors much easier. Co-authored-by: Diederik Loerakker --- go.mod | 2 +- go.sum | 4 +- opnode/l1/types.go | 4 + opnode/rollup/derive/payload_attributes.go | 5 +- opnode/rollup/driver/driver.go | 11 +- opnode/rollup/driver/fake_chain.go | 25 +- opnode/rollup/driver/state.go | 295 +++++++++++++-------- opnode/rollup/driver/state_test.go | 17 +- opnode/rollup/driver/step.go | 175 ++++++++---- opnode/rollup/sync/start.go | 4 +- opnode/rollup/sync/start_test.go | 2 +- 11 files changed, 356 insertions(+), 188 deletions(-) diff --git a/go.mod b/go.mod index 765d810c6926..486bee48ddbd 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220316014451-777b9479e829 +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220401211315-2ee22d0d72ff // For local debugging: // replace github.com/ethereum/go-ethereum v1.10.16 => ../reference-optimistic-geth diff --git a/go.sum b/go.sum index ea1b2165683c..aec6736e591a 100644 --- a/go.sum +++ b/go.sum @@ -128,8 +128,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220316014451-777b9479e829 h1:3Ez+vrywcpoBoMo9h4UcnNqKi6d7YlS++8+97glKW6I= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220316014451-777b9479e829/go.mod h1:CCsGXufQRqVL3+3t9zMPvzcwFwYlLdZ6enPluWYM64k= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220401211315-2ee22d0d72ff h1:dwhyNDLdBw70Id7CQAmLpMkiZge0qLskZrMraRkFmjc= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220401211315-2ee22d0d72ff/go.mod h1:CCsGXufQRqVL3+3t9zMPvzcwFwYlLdZ6enPluWYM64k= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= 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= diff --git a/opnode/l1/types.go b/opnode/l1/types.go index c75269619104..0cce7ba1a4e5 100644 --- a/opnode/l1/types.go +++ b/opnode/l1/types.go @@ -78,6 +78,10 @@ func (info *HeaderInfo) BlockRef() eth.L1BlockRef { } } +func (info *HeaderInfo) ReceiptHash() common.Hash { + return info.receiptHash +} + type rpcHeaderCacheInfo struct { Hash common.Hash `json:"hash"` } diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index b01994a31437..078acf61abfb 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -124,6 +124,7 @@ type L1Info interface { BaseFee() *big.Int ID() eth.BlockID BlockRef() eth.L1BlockRef + ReceiptHash() common.Hash } // L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block @@ -250,8 +251,8 @@ type L2Info interface { Time() uint64 } -// SortedAndPreparedBatches turns a collection of batches to the input batches for a series of blocks -func SortedAndPreparedBatches(batches []*BatchData, epoch, blockTime, minL2Time, maxL2Time uint64) []*BatchData { +// FillMissingBatches turns a collection of batches to the input batches for a series of blocks +func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, maxL2Time uint64) []*BatchData { m := make(map[uint64]*BatchData) for _, b := range batches { m[b.BatchV1.Timestamp] = b diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 8aafcf38e3d5..227d79264801 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -33,6 +33,7 @@ type Engine interface { ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) ExecutePayload(ctx context.Context, payload *l2.ExecutionPayload) error BlockByHash(context.Context, common.Hash) (*types.Block, error) + BlockByNumber(context.Context, *big.Int) (*types.Block, error) } type L1Chain interface { @@ -42,15 +43,19 @@ type L1Chain interface { L1Range(ctx context.Context, base eth.BlockID, max uint64) ([]eth.BlockID, error) } -// TODO: Extend L2 Interface to get safe/unsafe blocks (specifically for Unsafe L2 head) type L2Chain interface { + ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) } type outputInterface interface { - step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) - newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.L2BlockRef, l2Safe eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) + // insertEpoch creates and inserts one epoch on top of the safe head. It prefers blocks it creates to what is recorded in the unsafe chain. + // It returns the new L2 head and L2 Safe head and if there was a reorg. This function must return if there was a reorg otherwise the L2 chain must be traversed. + insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) + + // createNewBlock builds a new block based on the L2 Head, L1 Origin, and the current mempool. + createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) } func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/rollup/driver/fake_chain.go index 6f3e590f3365..374a56fea358 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/rollup/driver/fake_chain.go @@ -2,6 +2,7 @@ package driver import ( "context" + "errors" "math/big" "github.com/ethereum/go-ethereum" @@ -9,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" ) @@ -164,6 +166,21 @@ func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Ha return eth.L2BlockRef{}, ethereum.NotFound } +func (m *fakeChainSource) ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) { + m.log.Trace("ForkchoiceUpdate", "newHead", state.HeadBlockHash, "l2Head", m.l2head, "reorg", m.l2reorg) + m.l2reorg++ + if m.l2reorg >= len(m.l2s) { + panic("No more re-org chains available") + } + for i, bl := range m.l2s[m.l2reorg] { + if bl.Hash == state.HeadBlockHash { + m.l2head = i + return nil, nil + } + } + return nil, errors.New("unable to set new head") +} + var _ L1Chain = (*fakeChainSource)(nil) var _ L2Chain = (*fakeChainSource)(nil) @@ -175,14 +192,6 @@ func (m *fakeChainSource) reorgL1() { } } -func (m *fakeChainSource) reorgL2() { - m.log.Trace("Reorg L2", "new_reorg", m.l2reorg+1, "old_reorg", m.l2reorg) - m.l2reorg++ - if m.l2reorg >= len(m.l2s) { - panic("No more re-org chains available") - } -} - func (m *fakeChainSource) setL2Head(head int) eth.L2BlockRef { m.log.Trace("Set L2 head", "new_head", head, "old_head", m.l2head) m.l2head = head diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 59f4e9e9e641..94124f93015f 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -2,10 +2,12 @@ package driver import ( "context" + "errors" "sync/atomic" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" @@ -50,22 +52,45 @@ func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, outp } } +// Start starts up the state loop. The context is only for initilization. +// The loop will have been started iff err is not nil. func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error { l1Head, err := s.l1.L1HeadBlockRef(ctx) if err != nil { return err } - l2Head, err := s.l2.L2BlockRefByNumber(ctx, nil) - if err != nil { - return err + + // Check that we are past the genesis + if l1Head.Number > s.Config.Genesis.L1.Number { + l2Head, err := s.l2.L2BlockRefByNumber(ctx, nil) + if err != nil { + return err + } + // Ensure that we are on the correct chain. Note that we cannot rely on rely on the UnsafeHead being more than + // a sequence window behind the L1 Head and must walk back 1 sequence window as we do not track the end L1 block + // hash of the sequence window when we derive an L2 block. + unsafeHead, safeHead, err := sync.FindL2Heads(ctx, l2Head, s.Config.SeqWindowSize, s.l1, s.l2, &s.Config.Genesis) + if err != nil { + return err + } + s.l2Head = unsafeHead + s.l2SafeHead = safeHead + + } else { + // Not yet reached genesis block + // TODO: Test this codepath. That requires setting up L1, letting it run, and then creating the L2 genesis from there. + // Note: This will not work for setting the the genesis normally, but if the L1 node is not yet synced we could get this case. + l2genesis := eth.L2BlockRef{ + Hash: s.Config.Genesis.L2.Hash, + Number: s.Config.Genesis.L2.Number, + Time: s.Config.Genesis.L2Time, + L1Origin: s.Config.Genesis.L1, + } + s.l2Head = l2genesis + s.l2SafeHead = l2genesis } - // TODO: - // 1. Pull safehead from sync-start algorithm - // 2. Check if heads are below genesis & if so, bump to genesis. s.l1Head = l1Head - s.l2Head = l2Head - s.l2SafeHead = l2Head s.l1Heads = l1Heads go s.loop() @@ -86,51 +111,163 @@ func (s *state) l1WindowBufEnd() eth.BlockID { return s.l1WindowBuf[len(s.l1WindowBuf)-1] } -// extendL1Window extends the cached L1 window by pulling blocks from L1. -// It starts just after `s.l1WindowBufEnd()`. -func (s *state) extendL1Window(ctx context.Context) error { - s.log.Trace("Extending the cached window from L1", "cached_size", len(s.l1WindowBuf), "window_buf_end", s.l1WindowBufEnd()) - // fetch enough ids for 2 sequencing windows (we'll shift from one into the other before we run out again) - nexts, err := s.l1.L1Range(ctx, s.l1WindowBufEnd(), s.Config.SeqWindowSize*2) +func (s *state) handleNewL1Block(ctx context.Context, newL1Head eth.L1BlockRef) error { + if s.l1Head.Hash == newL1Head.Hash { + log.Trace("Received L1 head signal that is the same as the current head", "l1Head", newL1Head) + return nil + } + + if s.l1Head.Hash == newL1Head.ParentHash { + s.log.Trace("Linear extension", "l1Head", newL1Head) + s.l1Head = newL1Head + if s.l1WindowBufEnd().Hash == newL1Head.ParentHash { + s.l1WindowBuf = append(s.l1WindowBuf, newL1Head.ID()) + } + return nil + } + // New L1 Head is not the same as the current head or a single step linear extension. + // This could either be a long L1 extension, or a reorg. Both can be handled the same way. + s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.ParentHash, "new_l1_head", newL1Head) + unsafeL2Head, safeL2Head, err := sync.FindL2Heads(ctx, s.l2Head, s.Config.SeqWindowSize, s.l1, s.l2, &s.Config.Genesis) if err != nil { + s.log.Error("Could not get new unsafe L2 head when trying to handle a re-org", "err", err) return err } - s.l1WindowBuf = append(s.l1WindowBuf, nexts...) - return nil -} - -// sequencingWindow returns the next sequencing window and true if it exists, (nil, false) if -// there are not enough saved blocks. -func (s *state) sequencingWindow() ([]eth.BlockID, bool) { - if len(s.l1WindowBuf) < int(s.Config.SeqWindowSize) { - return nil, false + // Update forkchoice + fc := l2.ForkchoiceState{ + HeadBlockHash: unsafeL2Head.Hash, + SafeBlockHash: safeL2Head.Hash, + FinalizedBlockHash: s.l2Finalized.Hash, + } + _, err = s.l2.ForkchoiceUpdate(ctx, &fc, nil) + if err != nil { + s.log.Error("Could not set new forkchoice when trying to handle a re-org", "err", err) + return err } - return s.l1WindowBuf[:int(s.Config.SeqWindowSize)], true + // State Update + s.l1Head = newL1Head + s.l1WindowBuf = nil + s.l2Head = unsafeL2Head + // Don't advance l2SafeHead past it's current value + if s.l2SafeHead.Number >= safeL2Head.Number { + s.l2SafeHead = safeL2Head + } + + return nil } +// findNextL1Origin determines what the next L1 Origin should be. +// The L1 Origin is either the L2 Head's Origin, or the following L1 block +// if the next L2 block's time is greater than or equal to the L2 Head's Origin. func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { - // [prev L2 + blocktime, L1 Bock) + // If we are at the head block, don't do a lookup. + // Don't do a timestamp check either as we are unable to get the next block even if we wanted to. if s.l2Head.L1Origin.Hash == s.l1Head.Hash { return s.l1Head, nil } + + // Grab the block ref curr, err := s.l1.L1BlockRefByHash(ctx, s.l2Head.L1Origin.Hash) if err != nil { return eth.L1BlockRef{}, err } + // Somehow reorg'd. Will let the state loop take care of it. + if curr.Hash != s.l2Head.L1Origin.Hash { + return eth.L1BlockRef{}, errors.New("Unknown L1Origin") + } - s.log.Info("Find next l1Origin", "l2Head", s.l2Head, "l1Origin", curr) // TODO: There is an interaction with not using the L1 Genesis as an L1 Origin and // the fact that the L2 Genesis time needs to be set around the L1 Genesis such // that this check will return true. if s.l2Head.Time+s.Config.BlockTime >= curr.Time { // TODO: Need to walk more? ref, err := s.l1.L1BlockRefByNumber(ctx, curr.Number+1) - s.log.Info("Looking up new L1 Origin", "nextL1Origin", ref) + s.log.Debug("Advancing L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", ref, "err", err) return ref, err } + s.log.Debug("Next L1 Origin is the same as the previous", "l2Head", s.l2Head, "l1Origin", curr) return curr, nil } +// createNewL2Block builds a L2 block on top of the L2 Head (unsafe) +func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { + nextOrigin, err := s.findNextL1Origin(context.Background()) + if err != nil { + s.log.Error("Error finding next L1 Origin", "err", err) + return eth.L1BlockRef{}, err + } + if nextOrigin.Time <= s.Config.BlockTime+s.l2Head.Time { + s.log.Trace("Skipping block production because the next block time is behind the next L1 Origin", "l2Head", s.l2Head, "l1Origin", nextOrigin) + return eth.L1BlockRef{}, nil + } + // Don't produce blocks until past the L1 genesis + if nextOrigin.Number <= s.Config.Genesis.L1.Number { + s.log.Trace("Skipping block production because the next L1 Origin is behind the L1 genesis") + return eth.L1BlockRef{}, nil + } + // Actually create the new block + newUnsafeL2Head, batch, err := s.output.createNewBlock(context.Background(), s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, nextOrigin.ID()) + if err != nil { + s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", nextOrigin) + return eth.L1BlockRef{}, err + } + // State update + s.l2Head = newUnsafeL2Head + s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) + //Submit batch + go func() { + _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches + // Note: This can cause problems as the log can run after the batch submitter / driver is shut down. + // This is tracked in issue #308 + if err != nil { + s.log.Error("Error submitting batch", "err", err) + } + }() + return nextOrigin, nil +} + +// handleEpoch attempts to insert a full L2 epoch on top of the L2 Safe Head. +// It ensures that a full sequencing window is available and updates the state as needed. +func (s *state) handleEpoch(ctx context.Context) (bool, error) { + s.log.Trace("Handling epoch", "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead) + // Extend cached window if we do not have enough saved blocks + if len(s.l1WindowBuf) < int(s.Config.SeqWindowSize) { + // attempt to buffer up to 2x the size of a sequence window of L1 blocks, to speed up later handleEpoch calls + nexts, err := s.l1.L1Range(ctx, s.l1WindowBufEnd(), 2*s.Config.SeqWindowSize) + if err != nil { + s.log.Error("Could not extend the cached L1 window", "err", err, "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead, "l1Head", s.l1Head, "window_end", s.l1WindowBufEnd()) + return false, err + } + s.l1WindowBuf = append(s.l1WindowBuf, nexts...) + + } + // Ensure that there are enough blocks in the cached window + if len(s.l1WindowBuf) < int(s.Config.SeqWindowSize) { + s.log.Debug("Not enough cached blocks to run step", "cached_window_len", len(s.l1WindowBuf)) + return false, nil + } + + // Insert the epoch + window := s.l1WindowBuf[:s.Config.SeqWindowSize] + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + newL2Head, newL2SafeHead, reorg, err := s.output.insertEpoch(ctx, s.l2Head, s.l2SafeHead, s.l2Finalized, window) + cancel() + if err != nil { + s.log.Error("Error in running the output step.", "err", err, "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead) + return false, err + } + + // State update + s.l2Head = newL2Head + s.l2SafeHead = newL2SafeHead + s.l1WindowBuf = s.l1WindowBuf[1:] + s.log.Info("Inserted a new epoch", "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead, "reorg", reorg) + // TODO: l2Finalized + return reorg, nil + +} + +// loop is the event loop that responds to L1 changes and internal timers to produce L2 blocks. func (s *state) loop() { s.log.Info("State loop started") ctx := context.Background() @@ -171,106 +308,41 @@ func (s *state) loop() { s.log.Trace("L2 Creation Ticker") createBlock() case <-l2BlockCreationReq: - nextOrigin, err := s.findNextL1Origin(context.Background()) + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + nextOrigin, err := s.createNewL2Block(ctx) + cancel() if err != nil { - s.log.Error("Error finding next L1 Origin") - continue - } - if nextOrigin.Time <= s.Config.BlockTime+s.l2Head.Time { - s.log.Trace("Skipping block production", "l2Head", s.l2Head) - continue + s.log.Error("Error creating new L2 block", "err", err) } - // Don't produce blocks until past the L1 genesis - if nextOrigin.Number <= s.Config.Genesis.L1.Number { - s.log.Trace("Skipping block production b/c origin behind genesis") - continue - } - // 2. Ask output to create new block - newUnsafeL2Head, batch, err := s.output.newBlock(context.Background(), s.l2Finalized, s.l2Head, s.l2SafeHead.ID(), nextOrigin.ID()) - if err != nil { - s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", nextOrigin) - continue - } - // 3. Update unsafe l2 head - s.l2Head = newUnsafeL2Head - s.log.Trace("Created new l2 block", "l2UnsafeHead", s.l2Head) - // 4. Ask for batch submission - go func() { - _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches - if atomic.LoadUint32(&s.closed) > 0 { - return // closed, don't log (go-routine may be running after logger closed) - } - if err != nil { - s.log.Error("Error submitting batch", "err", err) - } - }() if nextOrigin.Time > s.l2Head.Time+s.Config.BlockTime { s.log.Trace("Asking for a second L2 block asap", "l2Head", s.l2Head) createBlock() } case newL1Head := <-s.l1Heads: - s.log.Trace("Received new L1 Head", "new_head", newL1Head, "old_head", s.l1Head) - if s.l1Head.Hash == newL1Head.Hash { - log.Trace("Received L1 head signal that is the same as the current head", "l1_head", newL1Head) - } else if s.l1Head.Hash == newL1Head.ParentHash { - s.log.Trace("Linear extension") - s.l1Head = newL1Head - if s.l1WindowBufEnd().Hash == newL1Head.ParentHash { - s.l1WindowBuf = append(s.l1WindowBuf, newL1Head.ID()) - } - } else { - // Not strictly always a reorg, but that is the most likely case - s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.ParentHash, "new_l1_head", newL1Head) - unsafeL2Head, safeL2Head, err := sync.FindL2Heads(ctx, s.l2Head, int(s.Config.SeqWindowSize), s.l1, s.l2, &s.Config.Genesis) - if err != nil { - s.log.Error("Could not get new unsafe L2 head when trying to handle a re-org", "err", err) - continue - } - // TODO: Fork choice update - s.l1Head = newL1Head - s.l1WindowBuf = nil - s.l2Head = unsafeL2Head // Note that verify only nodes can get an unsafe head because of a reorg. May want to remove that. - s.l2SafeHead = safeL2Head - s.log.Trace("State update", "l1Head", s.l1Head, "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead) + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + err := s.handleNewL1Block(ctx, newL1Head) + cancel() + if err != nil { + s.log.Error("Error in handling new L1 Head", "err", err) } - // Run step if we are able to - if s.l1Head.Number-s.l2Head.L1Origin.Number >= s.Config.SeqWindowSize { + if s.l1Head.Number-s.l2SafeHead.L1Origin.Number >= s.Config.SeqWindowSize { s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) requestStep() } case <-stepRequest: - if s.sequencer { - s.log.Trace("Skipping extension based on L1 chain as sequencer") - continue - } - s.log.Trace("Got step request") - // Extend cached window if we do not have enough saved blocks - if len(s.l1WindowBuf) < int(s.Config.SeqWindowSize) { - err := s.extendL1Window(context.Background()) - if err != nil { - s.log.Error("Could not extend the cached L1 window", "err", err, "l1Head", s.l1Head, "window_buf_end", s.l1WindowBufEnd()) - continue - } + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + reorg, err := s.handleEpoch(ctx) + cancel() + if err != nil { + s.log.Error("Error in handling epoch", "err", err) } - - // Get next window (& ensure that it exists) - if window, ok := s.sequencingWindow(); ok { - s.log.Trace("Have enough cached blocks to run step.", "window", window) - ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - newL2Head, err := s.output.step(ctx, s.l2SafeHead, s.l2Finalized, s.l2Head.ID(), window) - cancel() - if err != nil { - s.log.Error("Error in running the output step.", "err", err, "l2SafeHead", s.l2SafeHead, "l2Finalized", s.l2Finalized, "window", window) - continue + if reorg { + s.log.Warn("Got reorg") + if s.sequencer { + createBlock() } - s.l2Head = newL2Head - s.l2SafeHead = newL2Head - s.l1WindowBuf = s.l1WindowBuf[1:] - // TODO: l2Finalized - } else { - s.log.Trace("Not enough cached blocks to run step", "cached_window_len", len(s.l1WindowBuf)) } // Immediately run next step if we have enough blocks. @@ -278,7 +350,6 @@ func (s *state) loop() { s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) requestStep() } - } } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 5f82732c4f9d..ded4c5b98807 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -38,13 +38,13 @@ func (id testID) ID() eth.BlockID { } } -type outputHandlerFn func(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) +type outputHandlerFn func(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) -func (fn outputHandlerFn) step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) { - return fn(ctx, l2Head, l2Finalized, unsafeL2Head, l1Input) +func (fn outputHandlerFn) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) { + return fn(ctx, l2Head, l2SafeHead, l2Finalized, l1Input) } -func (fn outputHandlerFn) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.L2BlockRef, l2Safe eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { +func (fn outputHandlerFn) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { panic("Unimplemented") } @@ -114,7 +114,6 @@ func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo for i := range expectedWindow { assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") } - src.reorgL2() outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} } @@ -129,17 +128,17 @@ type stateTestCase struct { } func (tc *stateTestCase) Run(t *testing.T) { - log := testlog.Logger(t, log.LvlTrace) + log := testlog.Logger(t, log.LvlError) chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) l1headsCh := make(chan eth.L1BlockRef, 10) // Unbuffered channels to force a sync point between the test and the state loop. outputIn := make(chan outputArgs) outputReturn := make(chan outputReturnArgs) - outputHandler := func(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) { + outputHandler := func(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) { // TODO: Not sequencer, but need to pass unsafeL2Head here for the test. - outputIn <- outputArgs{l2Head: unsafeL2Head, l2Finalized: l2Finalized, l1Window: l1Input} + outputIn <- outputArgs{l2Head: l2Head.ID(), l2Finalized: l2Finalized, l1Window: l1Input} r := <-outputReturn - return r.l2Head, r.err + return r.l2Head, r.l2Head, false, r.err } config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis, BlockTime: 2} state := NewState(log, config, chainSource, chainSource, outputHandlerFn(outputHandler), nil, false) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 530dd85f661f..fcfd87633abd 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "math/big" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -11,6 +12,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -23,17 +25,17 @@ type outputImpl struct { Config rollup.Config } -func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Parent eth.L2BlockRef, l2Safe eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { - d.log.Info("creating new block", "l2Parent", l2Parent) +func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { + d.log.Info("creating new block", "l2Head", l2Head) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - l2Info, err := d.l2.BlockByHash(fetchCtx, l2Parent.Hash) + l2Info, err := d.l2.BlockByHash(fetchCtx, l2Head.Hash) if err != nil { - return l2Parent, nil, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Parent, err) + return l2Head, nil, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Head, err) } l2BLockRef, err := derive.BlockReferences(l2Info, &d.Config.Genesis) if err != nil { - return l2Parent, nil, fmt.Errorf("failed to derive L2BlockRef from l2Block: %w", err) + return l2Head, nil, fmt.Errorf("failed to derive L2BlockRef from l2Block: %w", err) } var l1Info derive.L1Info @@ -46,24 +48,24 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa // don't fetch receipts if we do not process deposits } if err != nil { - return l2Parent, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) + return l2Head, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) } timestamp := l2Info.Time() + d.Config.BlockTime if timestamp >= l1Info.Time() { - return l2Parent, nil, errors.New("L2 Timestamp is too large") + return l2Head, nil, errors.New("L2 Timestamp is too large") } l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) if err != nil { - return l2Parent, nil, err + return l2Head, nil, err } var txns []l2.Data txns = append(txns, l1InfoTx) - deposits, err := derive.DeriveDeposits(l2Parent.Number+1, receipts) - d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Parent, "l1Origin", l1Origin) + deposits, err := derive.DeriveDeposits(l2Head.Number+1, receipts) + d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Head, "l1Origin", l1Origin) if err != nil { - return l2Parent, nil, fmt.Errorf("failed to derive deposits: %v", err) + return l2Head, nil, fmt.Errorf("failed to derive deposits: %v", err) } txns = append(txns, deposits...) @@ -77,14 +79,14 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa NoTxPool: false, } fc := l2.ForkchoiceState{ - HeadBlockHash: l2Parent.Hash, - SafeBlockHash: l2Safe.Hash, + HeadBlockHash: l2Head.Hash, + SafeBlockHash: l2SafeHead.Hash, FinalizedBlockHash: l2Finalized.Hash, } - payload, err := d.addBlock(ctx, fc, attrs, false, true) + payload, err := d.insertHeadBlock(ctx, fc, attrs, false) if err != nil { - return l2Parent, nil, fmt.Errorf("failed to extend L2 chain: %v", err) + return l2Head, nil, fmt.Errorf("failed to extend L2 chain: %v", err) } batch := &derive.BatchData{ BatchV1: derive.BatchV1{ @@ -97,66 +99,69 @@ func (d *outputImpl) newBlock(ctx context.Context, l2Finalized eth.BlockID, l2Pa return ref, batch, err } -// DriverStep derives and processes one or more L2 blocks from the given sequencing window of L1 blocks. -// An incomplete sequencing window will result in an incomplete L2 chain if so. -// -// After the step completes it returns the block ID of the last processed L2 block, even if an error occurs. -func (d *outputImpl) step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalized eth.BlockID, unsafeL2Head eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, error) { +// insertEpoch creates and inserts one epoch on top of the safe head. It prefers blocks it creates to what is recorded in the unsafe chain. +// It returns the new L2 head and L2 Safe head and if there was a reorg. This function must return if there was a reorg otherwise the L2 chain must be traversed. +func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) { // Sanity Checks if len(l1Input) == 0 { - return l2Head, fmt.Errorf("empty L1 sequencing window on L2 %s", l2Head) + return l2Head, l2SafeHead, false, fmt.Errorf("empty L1 sequencing window on L2 %s", l2SafeHead) } if len(l1Input) != int(d.Config.SeqWindowSize) { - return l2Head, errors.New("Invalid sequencing window size") + return l2Head, l2SafeHead, false, errors.New("Invalid sequencing window size") } - logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], "input_l2_parent", l2Head, "finalized_l2", l2Finalized) + logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], "input_l2_parent", l2SafeHead, "finalized_l2", l2Finalized) logger.Trace("Running update step on the L2 node") // Get inputs from L1 and L2 epoch := rollup.Epoch(l1Input[0].Number) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - l2Info, err := d.l2.BlockByHash(fetchCtx, l2Head.Hash) + l2Info, err := d.l2.BlockByHash(fetchCtx, l2SafeHead.Hash) if err != nil { - return l2Head, fmt.Errorf("failed to fetch L2 block info of %s: %w", l2Head, err) + return l2Head, l2SafeHead, false, fmt.Errorf("failed to fetch L2 block info of %s: %w", l2SafeHead, err) } l1Info, _, receipts, err := d.dl.Fetch(fetchCtx, l1Input[0].Hash) if err != nil { - return l2Head, fmt.Errorf("failed to fetch L1 block with receipts %s: %w", l1Input[0], err) + return l2Head, l2SafeHead, false, fmt.Errorf("failed to fetch L1 block info of %s: %w", l1Input[0], err) + } + if l2SafeHead.L1Origin.Hash != l1Info.ParentHash() { + return l2Head, l2SafeHead, false, fmt.Errorf("l1Info %v does not extend L1 Origin (%v) of L2 Safe Head (%v)", l1Info.Hash(), l2SafeHead.L1Origin, l2SafeHead) } l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) if err != nil { - return l2Head, fmt.Errorf("failed to create l1InfoTx: %w", err) + return l2Head, l2SafeHead, false, fmt.Errorf("failed to create l1InfoTx: %w", err) } - deposits, err := derive.DeriveDeposits(l2Head.Number+1, receipts) + deposits, err := derive.DeriveDeposits(l2SafeHead.Number+1, receipts) if err != nil { - return l2Head, fmt.Errorf("failed to derive deposits: %w", err) + return l2Head, l2SafeHead, false, fmt.Errorf("failed to derive deposits: %w", err) } // TODO: with sharding the blobs may be identified in more detail than L1 block hashes transactions, err := d.dl.FetchAllTransactions(fetchCtx, l1Input) if err != nil { - return l2Head, fmt.Errorf("failed to fetch transactions from %s: %v", l1Input, err) + return l2Head, l2SafeHead, false, fmt.Errorf("failed to fetch transactions from %s: %v", l1Input, err) } batches, err := derive.BatchesFromEVMTransactions(&d.Config, transactions) if err != nil { - return l2Head, fmt.Errorf("failed to fetch create batches from transactions: %w", err) + return l2Head, l2SafeHead, false, fmt.Errorf("failed to fetch create batches from transactions: %w", err) } // Make batches contiguous minL2Time := l2Info.Time() + d.Config.BlockTime maxL2Time := l1Info.Time() batches = derive.FilterBatches(&d.Config, epoch, minL2Time, maxL2Time, batches) - batches = derive.SortedAndPreparedBatches(batches, uint64(epoch), d.Config.BlockTime, minL2Time, maxL2Time) + batches = derive.FillMissingBatches(batches, uint64(epoch), d.Config.BlockTime, minL2Time, maxL2Time) - // Note: SafeBlockHash currently needs to be set b/c of Geth fc := l2.ForkchoiceState{ HeadBlockHash: l2Head.Hash, - SafeBlockHash: l2Head.Hash, + SafeBlockHash: l2SafeHead.Hash, FinalizedBlockHash: l2Finalized.Hash, } - updateUnsafeHead := unsafeL2Head.Hash == l2Head.Hash // If unsafe head is the same as the safe head, keep it up to date // Execute each L2 block in the epoch - last := l2Head + lastHead := l2Head + lastSafeHead := l2SafeHead + didReorg := false + var payload derive.Block + var reorg bool for i, batch := range batches { var txns []l2.Data txns = append(txns, l1InfoTx) @@ -172,24 +177,99 @@ func (d *outputImpl) step(ctx context.Context, l2Head eth.L2BlockRef, l2Finalize NoTxPool: false, } - payload, err := d.addBlock(ctx, fc, attrs, true, updateUnsafeHead) + // We are either verifying blocks (with a potential for a reorg) or inserting a safe head to the chain + if lastHead.Hash != lastSafeHead.Hash { + payload, reorg, err = d.verifySafeBlock(ctx, fc, attrs, lastSafeHead.ID()) + + } else { + payload, err = d.insertHeadBlock(ctx, fc, attrs, true) + } if err != nil { - return last, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) + return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) } + newLast, err := derive.BlockReferences(payload, &d.Config.Genesis) if err != nil { - return last, fmt.Errorf("failed to derive block references: %w", err) + return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to derive block references: %w", err) + } + if reorg { + didReorg = true + } + // If reorg or the L2 Head is not ahead of the safe head, bump the head block. + if reorg || lastHead.Hash == lastSafeHead.Hash { + lastHead = newLast + } + lastSafeHead = newLast + + fc.HeadBlockHash = lastHead.Hash + fc.SafeBlockHash = lastSafeHead.Hash + } + + return lastHead, lastSafeHead, didReorg, nil +} + +// attributesMatchBlock checks if the L2 attributes pre-inputs match the output +// nil if it is a match. If err is not nil, the error contains the reason for the mismatch +func attributesMatchBlock(attrs *l2.PayloadAttributes, parentHash common.Hash, block *types.Block) error { + if parentHash != block.ParentHash() { + return fmt.Errorf("parent hash field does not match. expected: %v. got: %v", parentHash, block.ParentHash()) + } + if uint64(attrs.Timestamp) != block.Time() { + return fmt.Errorf("timestamp field does not match. expected: %v. got: %v", uint64(attrs.Timestamp), block.Time()) + } + if attrs.Random != l2.Bytes32(block.MixDigest()) { + return fmt.Errorf("random field does not match. expected: %v. got: %v", attrs.Random, l2.Bytes32(block.MixDigest())) + } + if len(attrs.Transactions) != len(block.Transactions()) { + return fmt.Errorf("transaction count does not match. expected: %v. got: %v", len(attrs.Transactions), len(block.Transactions())) + } + btxs := block.Transactions() + for i := range attrs.Transactions { + var tx types.Transaction + err := tx.UnmarshalBinary(attrs.Transactions[i]) + if err != nil { + return fmt.Errorf("failed to decode transaction %d in attributes: %w", i, err) + } + + if tx.Hash() != btxs[i].Hash() { + return fmt.Errorf("transaction %d does not match. expected: %v. got: %v", i, tx.Hash(), btxs[i].Hash()) } - last = newLast - // TODO(Joshua): Update this to handle verifiers + sequencers - fc.HeadBlockHash = last.Hash - fc.SafeBlockHash = last.Hash } + return nil +} + +// verifySafeBlock reconciles the supplied payload attributes against the actual L2 block. +// If they do not match, it inserts the new block and sets the head and safe head to the new block in the FC. +func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, parent eth.BlockID) (derive.Block, bool, error) { + block, err := d.l2.BlockByNumber(ctx, new(big.Int).SetUint64(parent.Number+1)) + if err != nil { + return nil, false, fmt.Errorf("failed to get L2 block: %w", err) + } + err = attributesMatchBlock(attrs, parent.Hash, block) + if err != nil { + // Have reorg + d.log.Warn("Detected L2 reorg when verifying L2 safe head", "parent", parent, "prev_block", block.Hash(), "mismatch", err) + fc.HeadBlockHash = parent.Hash + fc.SafeBlockHash = parent.Hash + payload, err := d.insertHeadBlock(ctx, fc, attrs, true) + return payload, true, err + } + // If match, just bump the safe head + d.log.Debug("Verified L2 block", "number", block.Number(), "hash", block.Hash()) + fc.SafeBlockHash = block.Hash() + _, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) + if err != nil { + return nil, false, fmt.Errorf("failed to execute ForkchoiceUpdated: %w", err) + } + return block, false, nil - return last, nil } -func (d *outputImpl) addBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, updateSafe, updateUnsafe bool) (*l2.ExecutionPayload, error) { +// insertHeadBlock creates, executes, and inserts the specified block as the head block. +// It first uses the given FC to start the block creation process and then after the payload is executed, +// sets the FC to the same safe and finalized hashes, but updates the head hash to the new block. +// If updateSafe is true, the head block is considered to be the safe head as well as the head. +func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, updateSafe bool) (*l2.ExecutionPayload, error) { fcRes, err := d.l2.ForkchoiceUpdate(ctx, &fc, attrs) if err != nil { return nil, fmt.Errorf("failed to create new block via forkchoice: %w", err) @@ -206,12 +286,11 @@ func (d *outputImpl) addBlock(ctx context.Context, fc l2.ForkchoiceState, attrs if err != nil { return nil, fmt.Errorf("failed to insert execution payload: %w", err) } + fc.HeadBlockHash = payload.BlockHash if updateSafe { fc.SafeBlockHash = payload.BlockHash } - if updateUnsafe { - fc.HeadBlockHash = payload.BlockHash - } + d.log.Debug("Inserted L2 head block", "number", uint64(payload.BlockNumber), "hash", payload.BlockHash, "update_safe", updateSafe) _, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { return nil, fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", err) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 59bd662fdc4e..d60079df97ce 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -78,7 +78,7 @@ func isCanonical(ctx context.Context, l1 L1Chain, block eth.BlockID) (bool, erro // Unsafe Block: The highest L2 block. If the L1 Attributes is ahead of the L1 head, it is assumed to be valid, // if not, it walks back until it finds the first L2 block whose L1 Origin is canonical in the L1 chain. // Safe Block: The highest L2 block whose sequence window has not changed during a reorg. -func FindL2Heads(ctx context.Context, start eth.L2BlockRef, seqWindowSize int, +func FindL2Heads(ctx context.Context, start eth.L2BlockRef, seqWindowSize uint64, l1 L1Chain, l2 L2Chain, genesis *rollup.Genesis) (unsafe eth.L2BlockRef, safe eth.L2BlockRef, err error) { reorgDepth := 0 var prevL1OriginHash common.Hash @@ -119,7 +119,7 @@ func FindL2Heads(ctx context.Context, start eth.L2BlockRef, seqWindowSize int, return eth.L2BlockRef{}, eth.L2BlockRef{}, TooDeepReorgErr } } - depth := 1 // SeqWindowSize is a length, but we are counting elements in the window. + depth := uint64(1) // SeqWindowSize is a length, but we are counting elements in the window. prevL1OriginHash = latest.L1Origin.Hash // Walk from the latest block back 1 Sequence Window of L1 Origins to determine the safe L2 block. for n := latest; ; { diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 3c7914b434f7..451e92e19228 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -110,7 +110,7 @@ type syncStartTestCase struct { GenesisL2 rune GenesisL2Num uint64 - SeqWindowSize int + SeqWindowSize uint64 SafeL2Head rune UnsafeL2Head rune ExpectedErr error From b6221f36d8b82b2296774c0c5cdc175c7ab7800a Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 5 Apr 2022 02:56:48 +0200 Subject: [PATCH 372/585] go.mod: update to squashed l2 geth diff d5e1fc1a74bda3cbe5715d5732621460f9e00908 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 486bee48ddbd..1fb76d23e921 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220401211315-2ee22d0d72ff +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220405004857-d5e1fc1a74bd // For local debugging: // replace github.com/ethereum/go-ethereum v1.10.16 => ../reference-optimistic-geth diff --git a/go.sum b/go.sum index aec6736e591a..90a469608a8f 100644 --- a/go.sum +++ b/go.sum @@ -128,8 +128,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220401211315-2ee22d0d72ff h1:dwhyNDLdBw70Id7CQAmLpMkiZge0qLskZrMraRkFmjc= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220401211315-2ee22d0d72ff/go.mod h1:CCsGXufQRqVL3+3t9zMPvzcwFwYlLdZ6enPluWYM64k= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220405004857-d5e1fc1a74bd h1:9lcMyd+cWztoY/v42cAW7DvyyI0O2iqq3+zTsZhV1JI= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220405004857-d5e1fc1a74bd/go.mod h1:DE7Qn/NgxDNnrl+Oju/tczSsn1aZ7rERXZDLHmVUmC8= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= 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= From d7239ccd4314ada1bb11355a52804b3714ab0d0c Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 5 Apr 2022 03:09:51 +0200 Subject: [PATCH 373/585] opnode/rollup: use L2 block height in L1-info deposit tx block-height field (tx field, not info field) for uniqueness of deposit tx hash on L2 --- opnode/rollup/derive/invert_test.go | 2 +- opnode/rollup/derive/payload_attributes.go | 8 ++++---- opnode/rollup/driver/step.go | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/opnode/rollup/derive/invert_test.go b/opnode/rollup/derive/invert_test.go index 93a152fd96be..8ee321f6e649 100644 --- a/opnode/rollup/derive/invert_test.go +++ b/opnode/rollup/derive/invert_test.go @@ -123,7 +123,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { for i, testCase := range cases { t.Run(testCase.name, func(t *testing.T) { info := testCase.mkInfo(rand.New(rand.NewSource(int64(1234 + i)))) - depTx := L1InfoDeposit(info) + depTx := L1InfoDeposit(123, info) nr, time, baseFee, h, err := L1InfoDepositTxData(depTx.Data) assert.NoError(t, err, "expected valid deposit info") assert.Equal(t, nr, info.num) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 078acf61abfb..1c284cd4134c 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -128,7 +128,7 @@ type L1Info interface { } // L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block -func L1InfoDeposit(block L1Info) *types.DepositTx { +func L1InfoDeposit(l2BlockHeight uint64, block L1Info) *types.DepositTx { data := make([]byte, 4+8+8+32+32) offset := 0 copy(data[offset:4], L1InfoFuncBytes4) @@ -142,7 +142,7 @@ func L1InfoDeposit(block L1Info) *types.DepositTx { copy(data[offset:offset+32], block.Hash().Bytes()) return &types.DepositTx{ - BlockHeight: block.NumberU64(), + BlockHeight: l2BlockHeight, TransactionIndex: 0, // always the first transaction From: DepositContractAddr, To: &L1InfoPredeployAddr, @@ -274,8 +274,8 @@ func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, maxL2 return out } -func L1InfoDepositBytes(l1Info L1Info) (hexutil.Bytes, error) { - l1Tx := types.NewTx(L1InfoDeposit(l1Info)) +func L1InfoDepositBytes(l2BlockHeight uint64, l1Info L1Info) (hexutil.Bytes, error) { + l1Tx := types.NewTx(L1InfoDeposit(l2BlockHeight, l1Info)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { return nil, fmt.Errorf("failed to encode L1 info tx") diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index fcfd87633abd..0d7cb0126ef3 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -56,7 +56,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, return l2Head, nil, errors.New("L2 Timestamp is too large") } - l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) + l1InfoTx, err := derive.L1InfoDepositBytes(l2Head.Number+1, l1Info) if err != nil { return l2Head, nil, err } @@ -128,10 +128,6 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S if l2SafeHead.L1Origin.Hash != l1Info.ParentHash() { return l2Head, l2SafeHead, false, fmt.Errorf("l1Info %v does not extend L1 Origin (%v) of L2 Safe Head (%v)", l1Info.Hash(), l2SafeHead.L1Origin, l2SafeHead) } - l1InfoTx, err := derive.L1InfoDepositBytes(l1Info) - if err != nil { - return l2Head, l2SafeHead, false, fmt.Errorf("failed to create l1InfoTx: %w", err) - } deposits, err := derive.DeriveDeposits(l2SafeHead.Number+1, receipts) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to derive deposits: %w", err) @@ -164,6 +160,10 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S var reorg bool for i, batch := range batches { var txns []l2.Data + l1InfoTx, err := derive.L1InfoDepositBytes(lastSafeHead.Number+1, l1Info) + if err != nil { + return l2Head, l2SafeHead, false, fmt.Errorf("failed to create l1InfoTx: %w", err) + } txns = append(txns, l1InfoTx) if i == 0 { txns = append(txns, deposits...) From abebb25f90058d55bfbd398f6c17de34808080e8 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 22 Mar 2022 16:52:05 -0700 Subject: [PATCH 374/585] feat: DepositFeed receive function It is convenient for users to be able to deposit funds directly to L2 by simply doing an ETH send to an address. The prevents needing an ABI. --- packages/contracts/contracts/L1/DepositFeed.sol | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index 023c5cffcd77..85e39b6eb8ee 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -26,6 +26,14 @@ contract DepositFeed { bytes data ); + /** + * Accepts value deposits where users can send ETH directly to + * the smart contract address and have the funds be deposited + */ + receive() external payable { + depositTransaction(msg.sender, msg.value, 30000, false, bytes("")); + } + /** * Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving * deposit transactions. @@ -41,7 +49,7 @@ contract DepositFeed { uint256 _gasLimit, bool _isCreation, bytes memory _data - ) external payable { + ) public payable { if (_isCreation && _to != address(0)) { revert NonZeroCreationTarget(); } From 42f85bceeab40cc44596e32b55eae74df54f5d06 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 24 Mar 2022 16:36:39 -0400 Subject: [PATCH 375/585] Update slither db --- packages/contracts/slither.db.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/slither.db.json b/packages/contracts/slither.db.json index 877ba1a66143..ddd1e749faab 100644 --- a/packages/contracts/slither.db.json +++ b/packages/contracts/slither.db.json @@ -1 +1 @@ -[{"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1102, "length": 648, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-59) has payable functions:\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#38-58)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L59) has payable functions:\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L38-L58)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "be013b000d4c176d4d893619bdca725d93e4761e4b2e22fa77a64144e53abb26", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 2010, "length": 88, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 97}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}}}], "description": "MockL2OutputOracle.appendL2Output(bytes32,uint256) (contracts/L1/MockL2OutputOracle.sol#45-51) uses a dangerous strict equality:\n\t- require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/MockL2OutputOracle.sol#48)\n", "markdown": "[MockL2OutputOracle.appendL2Output(bytes32,uint256)](contracts/L1/MockL2OutputOracle.sol#L45-L51) uses a dangerous strict equality:\n\t- [require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/MockL2OutputOracle.sol#L48)\n", "first_markdown_element": "contracts/L1/MockL2OutputOracle.sol#L45-L51", "id": "74ee9955ede80e105221045625f8b4f963a0ca8422674891166ad65bdcdba57a", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}, {"type": "node", "name": "OFFSET = uint160(0x1111000000000000000000000000000000001111)", "source_mapping": {"start": 284, "length": 85, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [14], "starting_column": 5, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}}}], "description": "DepositFeed.slitherConstructorConstantVariables() (contracts/L1/DepositFeed.sol#7-59) uses literals with too many digits:\n\t- OFFSET = uint160(0x1111000000000000000000000000000000001111) (contracts/L1/DepositFeed.sol#14)\n", "markdown": "[DepositFeed.slitherConstructorConstantVariables()](contracts/L1/DepositFeed.sol#L7-L59) uses literals with too many digits:\n\t- [OFFSET = uint160(0x1111000000000000000000000000000000001111)](contracts/L1/DepositFeed.sol#L14)\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "14adc89c437b961183112ca2328ae0e07b627d12995c5555d2c2fca5d4dbe1aa", "check": "too-many-digits", "impact": "Informational", "confidence": "Medium"}] +[{"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1929, "filename_used": "contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "receive", "source_mapping": {"start": 826, "length": 110, "filename_used": "contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [33, 34, 35], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1929, "filename_used": "contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67], "starting_column": 1, "ending_column": 2}}, "signature": "receive()"}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1367, "length": 646, "filename_used": "contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1929, "filename_used": "contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-67) has payable functions:\n\t - DepositFeed.receive() (contracts/L1/DepositFeed.sol#33-35)\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#46-66)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L67) has payable functions:\n\t - [DepositFeed.receive()](contracts/L1/DepositFeed.sol#L33-L35)\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L46-L66)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L67", "id": "288a726f2c33db8578a9b3b43eaabd069d963e2dbe1fb2ae508c861783d169f5", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "depositTransaction", "source_mapping": {"start": 1102, "length": 648, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "depositTransaction(address,uint256,uint256,bool,bytes)"}}], "description": "Contract locking ether found:\n\tContract DepositFeed (contracts/L1/DepositFeed.sol#7-59) has payable functions:\n\t - DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes) (contracts/L1/DepositFeed.sol#38-58)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [DepositFeed](contracts/L1/DepositFeed.sol#L7-L59) has payable functions:\n\t - [DepositFeed.depositTransaction(address,uint256,uint256,bool,bytes)](contracts/L1/DepositFeed.sol#L38-L58)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "be013b000d4c176d4d893619bdca725d93e4761e4b2e22fa77a64144e53abb26", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}, {"type": "node", "name": "require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)", "source_mapping": {"start": 2010, "length": 88, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 97}, "type_specific_fields": {"parent": {"type": "function", "name": "appendL2Output", "source_mapping": {"start": 1769, "length": 422, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [45, 46, 47, 48, 49, 50, 51], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "MockL2OutputOracle", "source_mapping": {"start": 95, "length": 2773, "filename_used": "./contracts/L1/MockL2OutputOracle.sol", "filename_relative": "contracts/L1/MockL2OutputOracle.sol", "filename_absolute": "./contracts/L1/MockL2OutputOracle.sol", "filename_short": "contracts/L1/MockL2OutputOracle.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "starting_column": 1, "ending_column": 2}}, "signature": "appendL2Output(bytes32,uint256)"}}}}], "description": "MockL2OutputOracle.appendL2Output(bytes32,uint256) (contracts/L1/MockL2OutputOracle.sol#45-51) uses a dangerous strict equality:\n\t- require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp) (contracts/L1/MockL2OutputOracle.sol#48)\n", "markdown": "[MockL2OutputOracle.appendL2Output(bytes32,uint256)](contracts/L1/MockL2OutputOracle.sol#L45-L51) uses a dangerous strict equality:\n\t- [require(bool,string)(_timestamp == nextTimestamp(),Timestamp not equal to next expected timestamp)](contracts/L1/MockL2OutputOracle.sol#L48)\n", "first_markdown_element": "contracts/L1/MockL2OutputOracle.sol#L45-L51", "id": "74ee9955ede80e105221045625f8b4f963a0ca8422674891166ad65bdcdba57a", "check": "incorrect-equality", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}, {"type": "node", "name": "OFFSET = uint160(0x1111000000000000000000000000000000001111)", "source_mapping": {"start": 284, "length": 85, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [14], "starting_column": 5, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "slitherConstructorConstantVariables", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}, "type_specific_fields": {"parent": {"type": "contract", "name": "DepositFeed", "source_mapping": {"start": 86, "length": 1666, "filename_used": "./contracts/L1/DepositFeed.sol", "filename_relative": "contracts/L1/DepositFeed.sol", "filename_absolute": "./contracts/L1/DepositFeed.sol", "filename_short": "contracts/L1/DepositFeed.sol", "is_dependency": false, "lines": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 1, "ending_column": 2}}, "signature": "slitherConstructorConstantVariables()"}}}}], "description": "DepositFeed.slitherConstructorConstantVariables() (contracts/L1/DepositFeed.sol#7-59) uses literals with too many digits:\n\t- OFFSET = uint160(0x1111000000000000000000000000000000001111) (contracts/L1/DepositFeed.sol#14)\n", "markdown": "[DepositFeed.slitherConstructorConstantVariables()](contracts/L1/DepositFeed.sol#L7-L59) uses literals with too many digits:\n\t- [OFFSET = uint160(0x1111000000000000000000000000000000001111)](contracts/L1/DepositFeed.sol#L14)\n", "first_markdown_element": "contracts/L1/DepositFeed.sol#L7-L59", "id": "14adc89c437b961183112ca2328ae0e07b627d12995c5555d2c2fca5d4dbe1aa", "check": "too-many-digits", "impact": "Informational", "confidence": "Medium"}] From 1d882335affda722e486efa3a4fc8d0b2aff1e8e Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 21:40:02 -0400 Subject: [PATCH 376/585] Add solidity test on df.receive() function --- .../contracts/test/DepositFeed.t.sol | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol index 87e2272e56fa..215f5fddbf2a 100644 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -12,7 +12,7 @@ contract DepositFeedTest is DSTest { uint256 immutable NON_ZERO_VALUE = 100; uint256 immutable ZERO_VALUE = 0; uint256 immutable NON_ZERO_GASLIMIT = 50000; - bytes NON_ZERO_DATA = "0x1111"; + bytes NON_ZERO_DATA = hex"1111"; DepositFeed df; @@ -38,7 +38,7 @@ contract DepositFeedTest is DSTest { // Test: depositTransaction fails when contract creation has a non-zero destination address function test_depositTransaction_ContractCreationReverts() external { vm.expectRevert(abi.encodeWithSignature("NonZeroCreationTarget()")); - df.depositTransaction(NON_ZERO_ADDRESS, NON_ZERO_VALUE, NON_ZERO_GASLIMIT, true, "0x"); + df.depositTransaction(NON_ZERO_ADDRESS, NON_ZERO_VALUE, NON_ZERO_GASLIMIT, true, hex""); } // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value @@ -135,7 +135,7 @@ contract DepositFeedTest is DSTest { ZERO_VALUE, NON_ZERO_GASLIMIT, false, - "0x" + NON_ZERO_DATA ); df.depositTransaction{ value: NON_ZERO_VALUE }( @@ -143,8 +143,28 @@ contract DepositFeedTest is DSTest { ZERO_VALUE, NON_ZERO_GASLIMIT, false, - "0x" + NON_ZERO_DATA + ); + assertEq(address(df).balance, NON_ZERO_VALUE); + } + + // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH + function test_receive_withEthValueFromEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + address(this), + address(this), + NON_ZERO_VALUE, + NON_ZERO_VALUE, + 30_000, + false, + hex"" ); + address(df).call{ value: NON_ZERO_VALUE }(hex""); + assertEq(address(df).balance, NON_ZERO_VALUE); } @@ -183,7 +203,7 @@ contract DepositFeedTest is DSTest { ZERO_VALUE, NON_ZERO_GASLIMIT, true, - "0x" + hex"" ); df.depositTransaction{ value: NON_ZERO_VALUE }( @@ -191,7 +211,7 @@ contract DepositFeedTest is DSTest { ZERO_VALUE, NON_ZERO_GASLIMIT, true, - "0x" + hex"" ); assertEq(address(df).balance, NON_ZERO_VALUE); } From 5b585e3079f44b7e79448b4a5e7d27de96945dc5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 21:46:02 -0400 Subject: [PATCH 377/585] Add warning message on DepositFeed.receive() --- packages/contracts/contracts/L1/DepositFeed.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index 85e39b6eb8ee..fb567229f21a 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -27,8 +27,10 @@ contract DepositFeed { ); /** - * Accepts value deposits where users can send ETH directly to - * the smart contract address and have the funds be deposited + * Accepts value so that users can send ETH directly to this contract and + * have the funds be deposited to their address on L2. + * Note: this is intended as a convenience function for EOAs. Contracts should call the + * depositTransaction() function directly. */ receive() external payable { depositTransaction(msg.sender, msg.value, 30000, false, bytes("")); From 46878214e34c09d068e1598118c1846c9000eb1c Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 15 Mar 2022 12:10:46 -0400 Subject: [PATCH 378/585] specs: Add Withdrawals specification --- specs/glossary.md | 22 +++++ specs/withdrawals.md | 202 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 specs/withdrawals.md diff --git a/specs/glossary.md b/specs/glossary.md index 00691d450e19..d599d93a451c 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -28,6 +28,8 @@ - [Depositor](#depositor) - [Deposited Transaction Type](#deposited-transaction-type) - [Deposit Contract](#deposit-contract) +- [Withdrawals](#withdrawals) + - [Relayer](#relayer) - [Other L2 Chain Concepts](#other-l2-chain-concepts) - [Address Aliasing](#address-aliasing) - [L2 Chain Inception](#l2-chain-inception) @@ -286,6 +288,26 @@ cf. [Deposits Specification](deposits.md) ------------------------------------------------------------------------------------------------------------------------ +# Withdrawals + +[withdrawals]: glossary.md#withdrawals + +In general, a withdrawal is a transaction sent from L2 to L1 that may transfer of data and/or value. + +This term *withdrawal* is somewhat ambiguous as these "transactions" exist at multiple levels. In order to differentiate + between the L1 and L2 components of a withdrawal we introduce the following terms: + +- A *withdrawing* call or transaction occurs on L2 and initiates a withdrawal. +- A *withdrawn* call or transaction occurs on l1 as the result of an withdrawal being relayed on L1. + +## Relayer + +[relayer]: glossary.md#withdrawals + +An EOA on L1 which finalizes a withdrawal by providing submitting the data necessary to verify its inclusion on L2. + +------------------------------------------------------------------------------------------------------------------------ + # Other L2 Chain Concepts ## Address Aliasing diff --git a/specs/withdrawals.md b/specs/withdrawals.md new file mode 100644 index 000000000000..df88fcb05369 --- /dev/null +++ b/specs/withdrawals.md @@ -0,0 +1,202 @@ +# Withdrawals + + +[g-deposits]: glossary.md#deposits +[g-deposited]: glossary.md#deposited-transaction +[deposit-tx-type]: glossary.md#deposited-transaction-type + +[g-withdrawal]: glossary.md#withdrawal +[g-mpt]: glossary.md#merkle-patricia-trie +[g-relayer]: glossary.md#withdrawals +[g-execution-engine]: glossary.md#execution-engine +**Table of Contents** + +[Withdrawals][g-withdrawal] are cross domain transactions which are initiated on L2, and finalized by a transaction +executed on L1. They may be used to transfer data and/or ETH from L1 to L2. + +**Vocabulary note**: *withdrawal* can refer to the transaction at various stages of the process, but we introduce +more specific terms to differentiate between the transaction + +- *withdrawal initiating transaction* refers specifically to a transaction on L2 sent to the Withdrawals predeploy. +- *withdrawal finalizing transaction* refers specifically to an L1 transaction which finalizes and relays the + withdrawal. + +Withdrawals are initiated on L2 via a call to the Withdrawals predeploy contract, which records the important properties +of the message in its storage. Withdrawals are finalized on L1 via a call to the `L2WithdrawalVerifier` contract, which +proves the inclusion of this withdrawal message. + +In this way, withdrawals are different from [deposits][g-deposits] which make use of a special transaction type in the +[execution engine][g-execution-engine] client. Rather, withdrawals transaction must use smart contracts on L1 for +finalization. + + + +**Table of Contents** + +- [Withdrawal initialization on L2](#withdrawal-initialization-on-l2) +- [Withdrawal verification](#withdrawal-verification) +- [Withdrawal Flow](#withdrawal-flow) +- [The L2 Withdrawals Contract](#the-l2-withdrawals-contract) +- [Security Considerations](#security-considerations) + - [Key Properties of Withdrawal Verification](#key-properties-of-withdrawal-verification) + - [Handling Successfully Verified Messages That Fail When Relayed](#handling-successfully-verified-messages-that-fail-when-relayed) +- [Summary of Definitions](#summary-of-definitions) + - [Constants](#constants) + - [Data Structures and Type Aliases](#data-structures-and-type-aliases) + + + +## Withdrawal initialization on L2 + +> Todo: spec out the predeploy contract + +## Withdrawal verification + +In order to verify a `WithdrawalMessage`, the following inputs must be provided: + +| Type | Name | +| --------------------------------- | ------------------ | +| `WithdrawalMessage` | `message` | +| `L2OutputTimestamp` | `timestamp` | +| `WithdrawalsRootInclusionProof` | `storageRootProof` | +| `WithdrawalMessageInclusionProof` | `messageProof` | + +These inputs must satisfy the following conditions: + +1. The `timestamp` is at least `FINALIZATION_WINDOW` seconds old. +1. `OutputOracle.l2Outputs(timestamp)` returns a non-zero value `l2Output`. +1. The `storageRootProof` is valid for the `l2Output` returned in step 2, according to the SSZ encoding described in the + [L2 output commitment construction](./proposals.md#l2-output-commitment-construction). +1. The `messageProof` is valid for the provided `message` and `messageProof` + +## Withdrawal Flow + +**On L2:** + +1. An L2 account sends a withdrawal message (and possibly also ETH) to the `WithdrawalsWindow` predeploy contract. + This is a very simple contract that stores a mapping from the hash of the `WithdrawalMessage` as defined above to a + boolean value. (`mapping (bytes32 => bool) withdrawalMessages`) +2. If ETH is being withdrawn, it can eventually be burned by deploying a contract which immediately `SELFDESTRUCT`s. + This has the benefit of using an existing EVM mechanism for removing the ETH from the world state, without having to + add a diff to L2 Geth. + +**On L1:** + +1. A [relayer][g-relayer] submits the required inputs to the `DepositFeed` contract. The relayer may or may not be the + same entity which initiated the withdrawal on L2. +2. The `DepositFeed` contract retrieves the output root from the `OutputOracle`'s `l2Outputs()` function, and performs + the remainder of the verification process internally. +3. If verification is successful, the message is forwarded to the target. + 1. If the message call is successful, the hash is stored in a `successfulMessages` mapping. + 2. Otherwise it is stored in a `repeatableMessages` mapping. +4. If verification fails, the call reverts. + +## The L2 Withdrawals Contract + +The L2 Withdrawals predeploy is a simple contract at `0x4200000000000000000000000000000000000015` which stores messages +to be withdrawn. + +> **Backware** + +It contains a mapping which records withdrawals. + +```js +interface WithdrawalsWindow { + + event WithdrawalMessage( + uint256 indexed messageNonce, // this is a global nonce value for all withdrawal messages + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes message + ); + + function initiateWithdrawal( + address target, + bytes message, + uint256 gasLimit + ) external payable; + + function burn(); +} +``` + +## Security Considerations + +### Key Properties of Withdrawal Verification + +1. It should not be possible 'double spend' a withdrawal, ie. to relay a `WithdrawalMessage` on L1 which does not + correspond to a message initiated on L2. For reference, see [this writeup][polygon-dbl-spend] of a vulnerability + of this type found on Polygon. + + [polygon-dbl-spend]: https://gerhard-wagner.medium.com/double-spending-bug-in-polygons-plasma-bridge-2e0954ccadf1 + +1. For each `WithdrawalMessage` initiated on L2 (ie. with a unique `messageNonce`), the following properties must hold: + 1. There should be one (and only one) relayable message. + 1. It should not be possible to relay the message with any of its fields modified, ie. + 1. Modifying the `sender` field would enable a 'spoofing' attack. + 1. Modifying the `target`, `message`, or `value` fields would enable an attacker to dangerously change the + intended outcome of the withdrawal. + 1. Modifying the `gasLimit` could make the cost of relaying too high, or allow the relayer to cause execution + to fail (out of gas) in the `target`. + +### Handling Successfully Verified Messages That Fail When Relayed + +If the execution of the relayed call fails in the `target` contracts, it is unfortunately not possible to determine +whether or not it was 'supposed' to fail, and whether or not it should be 'replayable'. +Thus we provide the following mitigations: + +1. The minimum gas amount to be + +[Insufficient Gas Griefing]:(https://swcregistry.io/docs/SWC-126) + +## Summary of Definitions + +### Constants + +| Name | Value | Unit | +| --------------------- | --------- | ------- | +| `FINALIZATION_WINDOW` | `604_800` | seconds | + +This `FINALIZATION_WINDOW` value is equivalent to 7 days. + +### Data Structures and Type Aliases + +1. A `WithdrawalMessage` is encoded in a struct as follows: + + ```js + struct WithdrawalMessage { + uint256 nonce; + address sender; + uint256 value; + bytes message; + } + ``` + +1. The `L2OutputTimestamp` is an alias for `uint256`, and MUST be a multiple of the `SUBMISSION_INTERVAL` described + in the [L2 Output](./proposals.md#constants) document. + +1. The `WithdrawalsRoot` is an alias for a `bytes32` value, corresponding to the [MPT][g-mpt] + storage root of the Withdrawals predeploy contract at `0x4200000000000000000000000000000000000015` (described below). + +1. The `WithdrawalsRootInclusionProof` proof contains the data necessary to prove that the provided `WithdrawalsRoot` is + included in the + [SSZ merkleization](https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization) + of the `L2Output` as defined in the + [L2 output commitment construction](./proposals.md#l2-output-commitment-construction). + +1. A `WithdrawalMessageInclusionProof` is an MPT proof encoded in a struct as follows: + + ```js + struct WithdrawalMessageInclusionProof { + WithdrawalMessage message; + bytes32 l2withdrawalsRoot; + bytes memory _key; // storage key of the withdrawal message commitment + bytes memory _value; // Always bytes32(1) (boolean validity status of the message) + bytes memory _proof; // MPT inclusion proof for the key/value + } + ``` + +1. This document also refers to the `L2Output` type as defined in the + [L2 output commitment construction](./proposals.md#l2-output-commitment-construction). From 9858ab2202d3a8fba24820e0c0cb7c465296cba5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 30 Mar 2022 16:02:19 -0400 Subject: [PATCH 379/585] contracts: Add withdrawor and start of tests --- ops/rollup.json | 4 +- .../contracts/L1/WithdrawalVerifier.sol | 27 +++++++ .../contracts/contracts/L2/Withdrawor.sol | 37 +++++++++ .../contracts/test/WithdrawalVerifier.t.sol | 79 +++++++++++++++++++ packages/contracts/test/withdrawor.spec.ts | 63 +++++++++++++++ specs/withdrawals.md | 4 +- 6 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 packages/contracts/contracts/L1/WithdrawalVerifier.sol create mode 100644 packages/contracts/contracts/L2/Withdrawor.sol create mode 100644 packages/contracts/contracts/test/WithdrawalVerifier.t.sol create mode 100644 packages/contracts/test/withdrawor.spec.ts diff --git a/ops/rollup.json b/ops/rollup.json index 68d34ea846c3..4def12bd4bab 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -5,7 +5,7 @@ "number": 0 }, "l2": { - "hash": "0xb6eacd24a7fa15fa1a9b3ae550e217760f7d8a82a9c246975144b6ba6e3589f3", + "hash": "0x6175fc223ee77b1921bdd2601c80b8ce2dddc5459e9cae87d0e957f6f6469e25", "number": 0 }, "l2_time": 1647573629 @@ -18,4 +18,4 @@ "seq_window_size": 64, "l1_chain_id": 900 -} \ No newline at end of file +} diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol new file mode 100644 index 000000000000..79173b2bc1b8 --- /dev/null +++ b/packages/contracts/contracts/L1/WithdrawalVerifier.sol @@ -0,0 +1,27 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { L2OutputOracle } from "./L2OutputOracle.sol"; + +/** + * @title WithdrawalVerifier + */ +contract WithdrawalVerifier { + L2OutputOracle public immutable l2oracle; + address public immutable withdrawalsPredeploy; + + constructor(L2OutputOracle _l2Oracle, address _withdrawalsPredeploy) { + l2oracle = _l2Oracle; + withdrawalsPredeploy = _withdrawalsPredeploy; + } + + // function verifyWithdrawal(// WithdrawalMessage message, + // L2OutputTimestamp timestamp, + // WithdrawalsRootInclusionProof storageRootProof, + // WithdrawalMessageInclusionProof messageProof + // ) + // { + + // } + +} diff --git a/packages/contracts/contracts/L2/Withdrawor.sol b/packages/contracts/contracts/L2/Withdrawor.sol new file mode 100644 index 000000000000..5f2692ca047d --- /dev/null +++ b/packages/contracts/contracts/L2/Withdrawor.sol @@ -0,0 +1,37 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/** + * @title Withdrawor + */ +contract Withdrawor { + uint256 public nonce; + mapping(bytes32 => bool) public withdrawals; + + event WithdrawalInitiated( + uint256 indexed messageNonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes message + ); + + /** + * Passes a message to L1. + * @param _message Message to pass to L1. + */ + function initiateWithdrawal( + address _target, + uint256 _gasLimit, + bytes calldata _message + ) external payable { + bytes32 messageHash = keccak256( + abi.encode(nonce, msg.sender, _target, msg.value, _message) + ); + withdrawals[messageHash] = true; + nonce++; + + emit WithdrawalInitiated(nonce, msg.sender, _target, msg.value, _gasLimit, _message); + } +} diff --git a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol new file mode 100644 index 000000000000..6fedd5442958 --- /dev/null +++ b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol @@ -0,0 +1,79 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/* Testing utilities */ +import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; + + +/* Target contract dependencies */ +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; + +/* Target contract */ +import { WithdrawalVerifier } from "../L1/WithdrawalVerifier.sol"; + +contract WithdrawalVerifierTest is DSTest { + // Utilities + Vm vm = Vm(HEVM_ADDRESS); + bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); + + // Dependencies + L2OutputOracle oracle; + + // Oracle constructor arguments + address sequencer = 0x000000000000000000000000000000000000AbBa; + uint256 submissionInterval = 1800; + uint256 l2BlockTime = 2; + bytes32 genesisL2Output = keccak256(abi.encode(0)); + uint256 historicalTotalBlocks = 100; + + // Test target + WithdrawalVerifier wv; + + // Target constructor arguments + address withdrawalsPredeploy = 0x4200000000000000000000000000000000000016; // check this value + + // Cache of the initial L2 timestamp + uint256 startingBlockTimestamp; + + // By default the first block has timestamp zero, which will cause underflows in the tests + uint256 initTime = 1000; + + + constructor() { + // Move time forward so we have a non-zero starting timestamp + vm.warp(initTime); + // Deploy the L2OutputOracle and transfer owernship to the sequencer + oracle = new L2OutputOracle( + submissionInterval, + l2BlockTime, + genesisL2Output, + historicalTotalBlocks, + sequencer + ); + startingBlockTimestamp = block.timestamp; + + wv = new WithdrawalVerifier( + oracle, + withdrawalsPredeploy + ); + + // wdp = + } + + function _outputRoot() internal returns (bytes32) { + + // bytes32 root = + // returns + } + + function setup() external { + + } + + function test_verifyWithdrawal() public { + // what do we need? + + } +} diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawor.spec.ts new file mode 100644 index 000000000000..7ec67d3cac1a --- /dev/null +++ b/packages/contracts/test/withdrawor.spec.ts @@ -0,0 +1,63 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import { Signer, BigNumber, Wallet, providers, ethers } from 'ethers' +import { Withdrawor, Withdrawor__factory } from '../typechain' + +// not secret. Don't use for real shit. Don't submit bug reports if you find this in git. +// 0xf3c101f4e376e7994E78CFB13a3A7e4B40910983 +const l2GethProvider = new providers.JsonRpcProvider('http://localhost:9545') +const l1GethProvider = new providers.JsonRpcProvider('http://localhost:8545') +const withdraworAddress = '0x4200000000000000000000000000000000000015' +const ZERO_ADDRESS = '0x' + '00'.repeat(20) +const ZERO_BIGNUMBER = BigNumber.from(0) +const ZERO_BYTES32 = '0x' + '00'.repeat(32) +const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) +const NON_ZERO_GASLIMIT = BigNumber.from(50_000) +const NON_ZERO_VALUE = BigNumber.from(100) +const NON_ZERO_DATA = '0x' + '11'.repeat(42) + +if (!process.env.PRIVATE_KEY) { + throw new Error('You must define PRIVATE_KEY in your environment.') +} + +describe('Withdraw', () => { + let wallet: Wallet + let signer: Signer + let signerAddress: string + let withdrawor: Withdrawor + before(async () => { + wallet = new Wallet(process.env.PRIVATE_KEY!) + signer = wallet.connect(l2GethProvider) + signerAddress = await signer.getAddress() + + withdrawor = await new Withdrawor__factory(signer).attach(withdraworAddress) + }) + + it('Should create a withdrawal', async () => { + const nonceBefore = await withdrawor.nonce() + + const tx = await withdrawor.initiateWithdrawal( + NON_ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA + ) + await tx.wait() + + const messageHash = ethers.utils.keccak256( + ethers.utils.defaultAbiCoder.encode( + ['uint256', 'address', 'address', 'uint256', 'bytes'], + [ + nonceBefore, + signerAddress, + NON_ZERO_ADDRESS, + ZERO_BYTES32, + NON_ZERO_DATA, + ] + ) + ) + + const nonceAfter = await withdrawor.nonce() + expect(await withdrawor.withdrawals(messageHash)).to.be.true + expect(nonceAfter.sub(nonceBefore).toNumber()).to.eq(1) + }) +}) diff --git a/specs/withdrawals.md b/specs/withdrawals.md index df88fcb05369..50fd30fdec7f 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -73,7 +73,7 @@ These inputs must satisfy the following conditions: **On L2:** -1. An L2 account sends a withdrawal message (and possibly also ETH) to the `WithdrawalsWindow` predeploy contract. +1. An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdrawor` predeploy contract. This is a very simple contract that stores a mapping from the hash of the `WithdrawalMessage` as defined above to a boolean value. (`mapping (bytes32 => bool) withdrawalMessages`) 2. If ETH is being withdrawn, it can eventually be burned by deploying a contract which immediately `SELFDESTRUCT`s. @@ -101,7 +101,7 @@ to be withdrawn. It contains a mapping which records withdrawals. ```js -interface WithdrawalsWindow { +interface Withdrawor { event WithdrawalMessage( uint256 indexed messageNonce, // this is a global nonce value for all withdrawal messages From 13dfcb124aa8b75dbdc8f5aa7db6b1b280af4856 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 30 Mar 2022 16:25:35 -0400 Subject: [PATCH 380/585] ops: Add withdrawor predeploy to docker setup ops: Add contract code to Makefile and Dockerfile --- Makefile | 3 ++- ops/Dockerfile.l2 | 9 ++++++--- ops/docker-compose.yml | 1 + ops/genesis-l2.json | 8 ++++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c53e204bfa6c..f11d357907b9 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ clean: .PHONY: clean devnet-clean: devnet-down - cd ops && docker-compose rm + cd ./ops && docker-compose rm docker volume rm ops_l1_data docker volume rm ops_l2_data .PHONY: devnet-clean @@ -20,6 +20,7 @@ devnet-up: @(cd ./ops && \ DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ + WITHDRAWOR_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawor.sol/Withdrawor.json | jq .deployedBytecode) \ docker-compose up --build) .PHONY: devnet-up diff --git a/ops/Dockerfile.l2 b/ops/Dockerfile.l2 index 32b0b2a4c3bd..2a44a6653028 100644 --- a/ops/Dockerfile.l2 +++ b/ops/Dockerfile.l2 @@ -1,15 +1,18 @@ FROM mslipper/reference-optimistic-geth:latest ARG L1_BLOCK_INFO_BYTECODE="" +ARG WITHDRAWOR_BYTECODE="" RUN apk add --no-cache jq COPY entrypoint.sh /entrypoint.sh COPY genesis-l2.json /genesis.json -RUN cat /genesis.json | jq ". | .alloc.\"4242424242424242424242424242424242424242\".code = \"$L1_BLOCK_INFO_BYTECODE\"" | tee /genesis-with-bytecode.json && \ - mv /genesis-with-bytecode.json /genesis.json +RUN cat /genesis.json | jq ". | .alloc.\"4200000000000000000000000000000000000014\".code = \"$L1_BLOCK_INFO_BYTECODE\"" \ + | jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$WITHDRAWOR_BYTECODE\"" \ + | tee /genesis-with-bytecode.json && \ + mv /genesis-with-bytecode.json /genesis.json VOLUME ["/db"] -ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 36f48e9f8914..0cac506c0d9c 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -22,6 +22,7 @@ services: dockerfile: Dockerfile.l2 args: L1_BLOCK_INFO_BYTECODE: $L1_BLOCK_INFO_BYTECODE + WITHDRAWOR_BYTECODE: $WITHDRAWOR_BYTECODE ports: - "9545:8545" volumes: diff --git a/ops/genesis-l2.json b/ops/genesis-l2.json index 37335af1bb16..bb8f37176021 100644 --- a/ops/genesis-l2.json +++ b/ops/genesis-l2.json @@ -794,7 +794,11 @@ "de3829a23df1479438622a08a116e8eb3f620bb5": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, - "4242424242424242424242424242424242424242": { + "4200000000000000000000000000000000000014": { + "code": "", + "balance": "0x0" + }, + "4200000000000000000000000000000000000015": { "code": "", "balance": "0x0" } @@ -803,4 +807,4 @@ "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "baseFeePerGas": "0x7" -} \ No newline at end of file +} From 3f15a7a1f3912181abc073d11dae0849cd762dd7 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 30 Mar 2022 23:53:06 -0400 Subject: [PATCH 381/585] Add gaslimit to withdrawal encoding --- ops/rollup.json | 2 +- packages/contracts/contracts/L2/Withdrawor.sol | 18 ++++++++++-------- packages/contracts/test/withdrawor.spec.ts | 3 ++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ops/rollup.json b/ops/rollup.json index 4def12bd4bab..17b41e753bce 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -5,7 +5,7 @@ "number": 0 }, "l2": { - "hash": "0x6175fc223ee77b1921bdd2601c80b8ce2dddc5459e9cae87d0e957f6f6469e25", + "hash": "0x0add004793ed5167f96f639cfebc38c606544292903cac1022f36133a7699326", "number": 0 }, "l2_time": 1647573629 diff --git a/packages/contracts/contracts/L2/Withdrawor.sol b/packages/contracts/contracts/L2/Withdrawor.sol index 5f2692ca047d..b47252adfa95 100644 --- a/packages/contracts/contracts/L2/Withdrawor.sol +++ b/packages/contracts/contracts/L2/Withdrawor.sol @@ -14,24 +14,26 @@ contract Withdrawor { address indexed target, uint256 value, uint256 gasLimit, - bytes message + bytes data ); /** - * Passes a message to L1. - * @param _message Message to pass to L1. + * Initiates a withdrawal to execute on L1. + * @param _target Address to call on L1 execution. + * @param _gasLimit GasLimit to provide on L1. + * @param _data Data to forward to L1 target. */ function initiateWithdrawal( address _target, uint256 _gasLimit, - bytes calldata _message + bytes calldata _data ) external payable { - bytes32 messageHash = keccak256( - abi.encode(nonce, msg.sender, _target, msg.value, _message) + bytes32 withdrawalHash = keccak256( + abi.encode(nonce, msg.sender, _target, msg.value, _gasLimit, _data) ); - withdrawals[messageHash] = true; + withdrawals[withdrawalHash] = true; nonce++; - emit WithdrawalInitiated(nonce, msg.sender, _target, msg.value, _gasLimit, _message); + emit WithdrawalInitiated(nonce, msg.sender, _target, msg.value, _gasLimit, _data); } } diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawor.spec.ts index 7ec67d3cac1a..48ad6a0e29ad 100644 --- a/packages/contracts/test/withdrawor.spec.ts +++ b/packages/contracts/test/withdrawor.spec.ts @@ -45,12 +45,13 @@ describe('Withdraw', () => { const messageHash = ethers.utils.keccak256( ethers.utils.defaultAbiCoder.encode( - ['uint256', 'address', 'address', 'uint256', 'bytes'], + ['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes'], [ nonceBefore, signerAddress, NON_ZERO_ADDRESS, ZERO_BYTES32, + NON_ZERO_GASLIMIT, NON_ZERO_DATA, ] ) From 1723a308eb20ef35b4be02e84d6fb547cffde3e4 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 31 Mar 2022 10:45:56 -0400 Subject: [PATCH 382/585] test(contracts): Withdrawal creation and proof gen --- package.json | 7 +- packages/contracts/test/withdrawor.spec.ts | 99 +++- yarn.lock | 524 ++++++++++++++++++++- 3 files changed, 603 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 1777a77ae033..4a3c7f780241 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,10 @@ "license": "MIT", "private": true, "devDependencies": { + "doctoc": "2.1.0", "lint-staged": "11.0.0", "markdownlint": "^0.24.0", - "markdownlint-cli2": "^0.3.2", - "doctoc": "2.1.0" + "markdownlint-cli2": "^0.3.2" }, "scripts": { "setup": "yarn install && cargo install lychee", @@ -16,5 +16,8 @@ "lint:check": "markdownlint-cli2 \"./opnode/README.md\" \"./specs/**/*.md\" \"#**/node_modules\"", "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./opnode/README.md\" \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"", "lint:toc": "doctoc --title=\"**Table of Contents**\" ./specs ./meta" + }, + "dependencies": { + "@eth-optimism/core-utils": "^0.8.1" } } diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawor.spec.ts index 48ad6a0e29ad..1e9028a7a39b 100644 --- a/packages/contracts/test/withdrawor.spec.ts +++ b/packages/contracts/test/withdrawor.spec.ts @@ -1,7 +1,8 @@ import { expect } from 'chai' import hre from 'hardhat' -import { Signer, BigNumber, Wallet, providers, ethers } from 'ethers' +import { Signer, BigNumber, Wallet, providers, ethers, utils } from 'ethers' import { Withdrawor, Withdrawor__factory } from '../typechain' +import { toRpcHexString } from '@eth-optimism/core-utils' // not secret. Don't use for real shit. Don't submit bug reports if you find this in git. // 0xf3c101f4e376e7994E78CFB13a3A7e4B40910983 @@ -20,12 +21,33 @@ if (!process.env.PRIVATE_KEY) { throw new Error('You must define PRIVATE_KEY in your environment.') } +const encodeWithdrawal = (args: { + nonce: BigNumber | number + sender: string + target: string + value: BigNumber | number + gasLimit: BigNumber | number + data: string +}): string => { + return ethers.utils.defaultAbiCoder.encode( + ['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes'], + [ + utils.hexZeroPad(BigNumber.from(args.nonce).toHexString(), 32), + args.sender, + args.target, + utils.hexZeroPad(BigNumber.from(args.value).toHexString(), 32), + utils.hexZeroPad(BigNumber.from(args.gasLimit).toHexString(), 32), + args.data, + ] + ) +} + describe('Withdraw', () => { let wallet: Wallet let signer: Signer let signerAddress: string let withdrawor: Withdrawor - before(async () => { + before('Setup withdrawor contract', async () => { wallet = new Wallet(process.env.PRIVATE_KEY!) signer = wallet.connect(l2GethProvider) signerAddress = await signer.getAddress() @@ -33,32 +55,61 @@ describe('Withdraw', () => { withdrawor = await new Withdrawor__factory(signer).attach(withdraworAddress) }) - it('Should create a withdrawal', async () => { - const nonceBefore = await withdrawor.nonce() + describe('Creating a withdrawal', () => { + let withdrawalHash: string + let nonceBefore: BigNumber + let storageSlot: string + before(async () => { + nonceBefore = await withdrawor.nonce() - const tx = await withdrawor.initiateWithdrawal( - NON_ZERO_ADDRESS, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA - ) - await tx.wait() - - const messageHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( - ['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes'], - [ - nonceBefore, - signerAddress, + await ( + await withdrawor.initiateWithdrawal( NON_ZERO_ADDRESS, - ZERO_BYTES32, NON_ZERO_GASLIMIT, - NON_ZERO_DATA, - ] + NON_ZERO_DATA + ) + ).wait() + + // locally calculate the expected mapping key + withdrawalHash = ethers.utils.keccak256( + encodeWithdrawal({ + nonce: nonceBefore, + sender: signerAddress, + target: NON_ZERO_ADDRESS, + value: 0, + gasLimit: NON_ZERO_GASLIMIT, + data: NON_ZERO_DATA, + }) ) - ) - const nonceAfter = await withdrawor.nonce() - expect(await withdrawor.withdrawals(messageHash)).to.be.true - expect(nonceAfter.sub(nonceBefore).toNumber()).to.eq(1) + // locally calculate the expected storage slot in the contract + storageSlot = ethers.utils.keccak256( + withdrawalHash + '00'.repeat(31) + '01' + ) + }) + + it('Should add an entry to the withdrawals mapping', async () => { + const nonceAfter = await withdrawor.nonce() + expect(await withdrawor.withdrawals(withdrawalHash)).to.be.true + expect(nonceAfter.sub(nonceBefore).toNumber()).to.eq(1) + }) + + it('Should return bytes32(1) when querying the calculated storage slot', async () => { + // Test to ensure we're correctly calculating the slot, per the solidity docs: + // "The value corresponding to a mapping key k is located at keccak256(h(k) . p) where . is + // concatenation and h is a function that is applied to the key..." + expect( + await l2GethProvider.getStorageAt(withdraworAddress, storageSlot) + ).to.equal(utils.hexZeroPad('0x01', 32)) + }) + + it('should generate a proof', async () => { + const proof = await l2GethProvider.send('eth_getProof', [ + withdraworAddress, + [storageSlot], + toRpcHexString((await l2GethProvider.getBlock('latest')).number), + ]) + expect(proof.storageProof[0].key).to.eq(storageSlot) + }) }) }) diff --git a/yarn.lock b/yarn.lock index de6f8ceb9ac5..f008300e70b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,6 +23,360 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@eth-optimism/core-utils@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.8.1.tgz#ee7d8815f9ddb67ca3e2f3ec1d8515a46af5caf6" + integrity sha512-GJJvw9cBekvR1xH/f2jpgp6MnbWlMBaVm1h3BA0sEzmlaFufTG4ybGrHkL3nQT0Vqtjs3LYjaExkVmsUzpb7xg== + dependencies: + "@ethersproject/abstract-provider" "^5.5.1" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/providers" "^5.5.3" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.1" + bufio "^1.0.7" + chai "^4.3.4" + ethers "^5.5.4" + +"@ethersproject/abi@5.6.0", "@ethersproject/abi@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.0.tgz#ea07cbc1eec2374d32485679c12408005895e9f3" + integrity sha512-AhVByTwdXCc2YQ20v300w6KVHle9g2OFc28ZAFCPnJyEpkv1xKXjZcSTgWOlv1i+0dqlgF8RCF2Rn2KC1t+1Vg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/abstract-provider@5.6.0", "@ethersproject/abstract-provider@^5.5.1", "@ethersproject/abstract-provider@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz#0c4ac7054650dbd9c476cf5907f588bbb6ef3061" + integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + +"@ethersproject/abstract-signer@5.6.0", "@ethersproject/abstract-signer@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz#9cd7ae9211c2b123a3b29bf47aab17d4d016e3e7" + integrity sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/address@5.6.0", "@ethersproject/address@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" + integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + +"@ethersproject/base64@5.6.0", "@ethersproject/base64@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.0.tgz#a12c4da2a6fb86d88563216b0282308fc15907c9" + integrity sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + +"@ethersproject/basex@5.6.0", "@ethersproject/basex@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.0.tgz#9ea7209bf0a1c3ddc2a90f180c3a7f0d7d2e8a69" + integrity sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/bignumber@5.6.0", "@ethersproject/bignumber@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.0.tgz#116c81b075c57fa765a8f3822648cf718a8a0e26" + integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + bn.js "^4.11.9" + +"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@^5.6.0": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" + integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/constants@5.6.0", "@ethersproject/constants@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.0.tgz#55e3eb0918584d3acc0688e9958b0cedef297088" + integrity sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + +"@ethersproject/contracts@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.0.tgz#60f2cfc7addd99a865c6c8cfbbcec76297386067" + integrity sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw== + dependencies: + "@ethersproject/abi" "^5.6.0" + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + +"@ethersproject/hash@5.6.0", "@ethersproject/hash@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.0.tgz#d24446a5263e02492f9808baa99b6e2b4c3429a2" + integrity sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/hdnode@5.6.0", "@ethersproject/hdnode@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.0.tgz#9dcbe8d629bbbcf144f2cae476337fe92d320998" + integrity sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + +"@ethersproject/json-wallets@5.6.0", "@ethersproject/json-wallets@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz#4c2fc27f17e36c583e7a252fb938bc46f98891e5" + integrity sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.6.0", "@ethersproject/keccak256@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.0.tgz#fea4bb47dbf8f131c2e1774a1cecbfeb9d606459" + integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== + dependencies: + "@ethersproject/bytes" "^5.6.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.6.0", "@ethersproject/logger@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" + integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== + +"@ethersproject/networks@5.6.1", "@ethersproject/networks@^5.6.0": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.1.tgz#7a21ed1f83e86121737b16841961ec99ccf5c9c7" + integrity sha512-b2rrupf3kCTcc3jr9xOWBuHylSFtbpJf79Ga7QR98ienU2UqGimPGEsYMgbI29KHJfA5Us89XwGVmxrlxmSrMg== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/pbkdf2@5.6.0", "@ethersproject/pbkdf2@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz#04fcc2d7c6bff88393f5b4237d906a192426685a" + integrity sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + +"@ethersproject/properties@5.6.0", "@ethersproject/properties@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" + integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/providers@5.6.2", "@ethersproject/providers@^5.5.3": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.2.tgz#b9807b1c8c6f59fa2ee4b3cf6519724d07a9f422" + integrity sha512-6/EaFW/hNWz+224FXwl8+HdMRzVHt8DpPmu5MZaIQqx/K/ELnC9eY236SMV7mleCM3NnEArFwcAAxH5kUUgaRg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.6.0", "@ethersproject/random@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.0.tgz#1505d1ab6a250e0ee92f436850fa3314b2cb5ae6" + integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/rlp@5.6.0", "@ethersproject/rlp@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.0.tgz#55a7be01c6f5e64d6e6e7edb6061aa120962a717" + integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/sha2@5.6.0", "@ethersproject/sha2@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.0.tgz#364c4c11cc753bda36f31f001628706ebadb64d9" + integrity sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.6.0", "@ethersproject/signing-key@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.0.tgz#4f02e3fb09e22b71e2e1d6dc4bcb5dafa69ce042" + integrity sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.0.tgz#64657362a596bf7f5630bdc921c07dd78df06dc3" + integrity sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/strings@5.6.0", "@ethersproject/strings@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.0.tgz#9891b26709153d996bf1303d39a7f4bc047878fd" + integrity sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/transactions@5.6.0", "@ethersproject/transactions@^5.5.0", "@ethersproject/transactions@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.0.tgz#4b594d73a868ef6e1529a2f8f94a785e6791ae4e" + integrity sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + +"@ethersproject/units@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.0.tgz#e5cbb1906988f5740254a21b9ded6bd51e826d9c" + integrity sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/wallet@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.0.tgz#33d11a806d783864208f348709a5a3badac8e22a" + integrity sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/json-wallets" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + +"@ethersproject/web@5.6.0", "@ethersproject/web@^5.5.1", "@ethersproject/web@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.0.tgz#4bf8b3cbc17055027e1a5dd3c357e37474eaaeb8" + integrity sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg== + dependencies: + "@ethersproject/base64" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/wordlists@5.6.0", "@ethersproject/wordlists@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.0.tgz#79e62c5276e091d8575f6930ba01a29218ded032" + integrity sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -67,6 +421,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -123,6 +482,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -133,6 +497,16 @@ bail@^1.0.0: resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + boundary@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/boundary/-/boundary-1.0.1.tgz#4d67dc2602c0cc16dd9bce7ebf87e948290f5812" @@ -145,11 +519,34 @@ braces@^3.0.1: dependencies: fill-range "^7.0.1" +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +bufio@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.0.7.tgz#b7f63a1369a0829ed64cc14edf0573b3e382a33e" + integrity sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +chai@^4.3.4: + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -182,6 +579,11 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -285,6 +687,13 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -341,6 +750,19 @@ domutils@^2.0.0: domelementtype "^2.2.0" domhandler "^4.2.0" +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -380,6 +802,42 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +ethers@^5.5.4: + version "5.6.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.2.tgz#e75bac7f038c5e0fdde667dba62fc223924143a2" + integrity sha512-EzGCbns24/Yluu7+ToWnMca3SXJ1Jk1BvWB7CCmVNxyOeM4LLvw2OLuIHhlkhQk1dtOcj9UMsdkxUh8RiG1dxQ== + dependencies: + "@ethersproject/abi" "5.6.0" + "@ethersproject/abstract-provider" "5.6.0" + "@ethersproject/abstract-signer" "5.6.0" + "@ethersproject/address" "5.6.0" + "@ethersproject/base64" "5.6.0" + "@ethersproject/basex" "5.6.0" + "@ethersproject/bignumber" "5.6.0" + "@ethersproject/bytes" "5.6.1" + "@ethersproject/constants" "5.6.0" + "@ethersproject/contracts" "5.6.0" + "@ethersproject/hash" "5.6.0" + "@ethersproject/hdnode" "5.6.0" + "@ethersproject/json-wallets" "5.6.0" + "@ethersproject/keccak256" "5.6.0" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.1" + "@ethersproject/pbkdf2" "5.6.0" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.2" + "@ethersproject/random" "5.6.0" + "@ethersproject/rlp" "5.6.0" + "@ethersproject/sha2" "5.6.0" + "@ethersproject/signing-key" "5.6.0" + "@ethersproject/solidity" "5.6.0" + "@ethersproject/strings" "5.6.0" + "@ethersproject/transactions" "5.6.0" + "@ethersproject/units" "5.6.0" + "@ethersproject/wallet" "5.6.0" + "@ethersproject/web" "5.6.0" + "@ethersproject/wordlists" "5.6.0" + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -437,6 +895,11 @@ format@^0.2.0: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -476,6 +939,23 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + htmlparser2@~4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" @@ -509,7 +989,7 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -inherits@^2.0.0: +inherits@^2.0.0, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -609,6 +1089,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -684,6 +1169,13 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + markdown-escapes@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" @@ -758,6 +1250,16 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + minimist@~1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -833,6 +1335,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + picomatch@^2.2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" @@ -921,6 +1428,11 @@ rxjs@^7.4.0: dependencies: tslib "~2.1.0" +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -1069,6 +1581,11 @@ tslib@~2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -1187,6 +1704,11 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" From f67ad06bd5297d338793d12408835edb0e83751d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 31 Mar 2022 15:41:55 -0400 Subject: [PATCH 383/585] deps: install entire goddamn monorepo using forge. I needed the trie contracts over here, so now the whole monorepo is a submodule of the specs repo. Happy now @norswap? Why, you ask, did I do this rather than the alternatives available to me? 1. Copying and pasting is gross. 2. `yarn add` would have installed a smaller dep, but it's also gross. 3. git submodules, while also gross in their own right, is at least consistent with how we're currently handling other dependencies, so I went with that. --- .gitmodules | 3 +++ packages/contracts/lib/optimism | 1 + 2 files changed, 4 insertions(+) create mode 160000 packages/contracts/lib/optimism diff --git a/.gitmodules b/.gitmodules index 406056b3a734..f38688f818ba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "packages/contracts/lib/forge-std"] path = packages/contracts/lib/forge-std url = https://github.com/brockelmore/forge-std +[submodule "packages/contracts/lib/optimism"] + path = packages/contracts/lib/optimism + url = https://github.com/ethereum-optimism/optimism diff --git a/packages/contracts/lib/optimism b/packages/contracts/lib/optimism new file mode 160000 index 000000000000..70897fa47ea3 --- /dev/null +++ b/packages/contracts/lib/optimism @@ -0,0 +1 @@ +Subproject commit 70897fa47ea35f288fd6c1bb6c2eef6c45594761 From 4611489de0d52f3ff30e1c2d0028335158470c50 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 1 Apr 2022 08:46:59 -0400 Subject: [PATCH 384/585] Add output root inclusion proof Adds a check to ensure that withdrawal root is included in the l2 output root. --- ops/rollup.json | 2 +- .../contracts/L1/WithdrawalVerifier.sol | 58 ++++++++++-- .../contracts/test/WithdrawalVerifier.t.sol | 94 +++++++++++++++---- 3 files changed, 125 insertions(+), 29 deletions(-) diff --git a/ops/rollup.json b/ops/rollup.json index 17b41e753bce..0c5691f85562 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -5,7 +5,7 @@ "number": 0 }, "l2": { - "hash": "0x0add004793ed5167f96f639cfebc38c606544292903cac1022f36133a7699326", + "hash": "0x00574ae7ed85cf485dd148011ab78c138becdd65b3078bd46c94c55766c8fc7a", "number": 0 }, "l2_time": 1647573629 diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol index 79173b2bc1b8..efd2ad6c8260 100644 --- a/packages/contracts/contracts/L1/WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/WithdrawalVerifier.sol @@ -7,21 +7,59 @@ import { L2OutputOracle } from "./L2OutputOracle.sol"; * @title WithdrawalVerifier */ contract WithdrawalVerifier { - L2OutputOracle public immutable l2oracle; + L2OutputOracle public immutable l2Oracle; address public immutable withdrawalsPredeploy; + // todo: add an immutable finalization window var here + + struct OutputRootProof { + uint256 timestamp; + bytes32 version; + bytes32 stateRoot; + bytes32 withdrawerRoot; + bytes32 latestBlockhash; + } + + // struct WithdrawalProof { + // ; + // } constructor(L2OutputOracle _l2Oracle, address _withdrawalsPredeploy) { - l2oracle = _l2Oracle; + l2Oracle = _l2Oracle; withdrawalsPredeploy = _withdrawalsPredeploy; } - // function verifyWithdrawal(// WithdrawalMessage message, - // L2OutputTimestamp timestamp, - // WithdrawalsRootInclusionProof storageRootProof, - // WithdrawalMessageInclusionProof messageProof - // ) - // { - - // } + function verifyWithdrawal( + uint256 nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes calldata _data, + OutputRootProof calldata _outputRootProof + ) + external + returns ( + // WithdrawalProof _withdrawalProof + bool + ) + { + // check that the timestamp is 7 days old + // hash _outputRootProof and compare with the outputOracle's value + // how do I get the withdrawal root itself? + require(_outputRootProof.timestamp <= block.timestamp - 7 days, "Too soon"); + bytes32 outputRoot = l2Oracle.getL2Output(_outputRootProof.timestamp); + require( + outputRoot == + keccak256( + abi.encode( + _outputRootProof.version, + _outputRootProof.stateRoot, + _outputRootProof.withdrawerRoot, + _outputRootProof.latestBlockhash + ) + ), + "Calculated output root does not match expected value" + ); + } } diff --git a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol index 6fedd5442958..65015be632a2 100644 --- a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol +++ b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol @@ -6,7 +6,6 @@ import { DSTest } from "../../lib/ds-test/src/test.sol"; import { Vm } from "../../lib/forge-std/src/Vm.sol"; import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; - /* Target contract dependencies */ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; @@ -32,18 +31,29 @@ contract WithdrawalVerifierTest is DSTest { WithdrawalVerifier wv; // Target constructor arguments - address withdrawalsPredeploy = 0x4200000000000000000000000000000000000016; // check this value + address withdrawalsPredeploy = 0x4200000000000000000000000000000000000015; - // Cache of the initial L2 timestamp + // Cache of timestamps uint256 startingBlockTimestamp; + uint256 appendedTimestamp; - // By default the first block has timestamp zero, which will cause underflows in the tests - uint256 initTime = 1000; + // By default the first block has timestamp zero, which will cause underflows in the tests, + // so we jump ahead to the exact time that I wrote this line. + uint256 initTime = 1648757197; + // Generate an output that we can work with. We can use whatever values we want + // except for the withdrawerRoot. This one was generated by running the withdrawor.spec.ts + // test script against Geth. + bytes32 version = bytes32(hex"00"); + bytes32 stateRoot = keccak256(abi.encode(1)); + bytes32 withdrawerRoot = 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; + bytes32 latestBlockhash = keccak256(abi.encode(2)); + WithdrawalVerifier.OutputRootProof outputRootProof; constructor() { // Move time forward so we have a non-zero starting timestamp vm.warp(initTime); + // Deploy the L2OutputOracle and transfer owernship to the sequencer oracle = new L2OutputOracle( submissionInterval, @@ -54,26 +64,74 @@ contract WithdrawalVerifierTest is DSTest { ); startingBlockTimestamp = block.timestamp; - wv = new WithdrawalVerifier( - oracle, - withdrawalsPredeploy - ); - - // wdp = + wv = new WithdrawalVerifier(oracle, withdrawalsPredeploy); } - function _outputRoot() internal returns (bytes32) { + function setUp() external { + vm.warp(initTime); + bytes32 outputRoot = keccak256( + abi.encode(version, stateRoot, withdrawerRoot, latestBlockhash) + ); - // bytes32 root = - // returns + uint256 nextTimestamp = oracle.nextTimestamp(); + // Warp to 1 second after the timestamp we'll append + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); + oracle.appendL2Output(outputRoot, nextTimestamp, 0, 0); + + // cache the appendedTimestamp + appendedTimestamp = nextTimestamp; + outputRootProof = WithdrawalVerifier.OutputRootProof({ + timestamp: appendedTimestamp, + version: version, + stateRoot: stateRoot, + withdrawerRoot: withdrawerRoot, + latestBlockhash: latestBlockhash + }); } - function setup() external { - + function test_verifyWithdrawal() external { + // Warp to after the finality window + vm.warp(appendedTimestamp + 7 days); + wv.verifyWithdrawal( + 0, // nonce + 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5, // sender + 0x1111111111111111111111111111111111111111, // target + 0, // value + 50_000, // gasLimit + hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data + outputRootProof + ); } - function test_verifyWithdrawal() public { - // what do we need? + function test_cannotVerifyRecentWithdrawal() external { + // This call should fail because the output root we're using was appended 1 second ago. + vm.expectRevert("Too soon"); + wv.verifyWithdrawal( + 0, // nonce + 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5, // sender + 0x1111111111111111111111111111111111111111, // target + 0, // value + 50_000, // gasLimit + hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data + outputRootProof + ); + } + function test_cannotVerifyInvalidProof() external { + // This call should fail because the output root we're using was appended 1 second ago. + vm.warp(appendedTimestamp + 7 days); + vm.expectRevert("Calculated output root does not match expected value"); + WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; + invalidOutpuRootProof.latestBlockhash = 0; + wv.verifyWithdrawal( + 0, // nonce + 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5, // sender + 0x1111111111111111111111111111111111111111, // target + 0, // value + 50_000, // gasLimit + hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data + invalidOutpuRootProof + ); } } From 45e7abc7d1e1cf9ffc0fc2e1ed42cbd29a58b802 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 1 Apr 2022 13:04:16 -0400 Subject: [PATCH 385/585] Add storage inclusion proof Adds a check to ensure that the withdrawal message hash is included in the mapping of withdrawals in the withdrawer contract --- .../contracts/L1/WithdrawalVerifier.sol | 39 ++++++++++++------- .../contracts/test/WithdrawalVerifier.t.sol | 10 +++-- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol index efd2ad6c8260..817f2379ed80 100644 --- a/packages/contracts/contracts/L1/WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/WithdrawalVerifier.sol @@ -2,6 +2,9 @@ pragma solidity 0.8.10; import { L2OutputOracle } from "./L2OutputOracle.sol"; +import { + Lib_SecureMerkleTrie +} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; /** * @title WithdrawalVerifier @@ -19,30 +22,21 @@ contract WithdrawalVerifier { bytes32 latestBlockhash; } - // struct WithdrawalProof { - // ; - // } - constructor(L2OutputOracle _l2Oracle, address _withdrawalsPredeploy) { l2Oracle = _l2Oracle; withdrawalsPredeploy = _withdrawalsPredeploy; } function verifyWithdrawal( - uint256 nonce, + uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes calldata _data, - OutputRootProof calldata _outputRootProof - ) - external - returns ( - // WithdrawalProof _withdrawalProof - bool - ) - { + OutputRootProof calldata _outputRootProof, + bytes calldata _withdrawalProof + ) external returns (bool) { // check that the timestamp is 7 days old // hash _outputRootProof and compare with the outputOracle's value // how do I get the withdrawal root itself? @@ -61,5 +55,24 @@ contract WithdrawalVerifier { ), "Calculated output root does not match expected value" ); + + bytes32 withdrawalHash = keccak256( + abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) + ); + emit log_named_bytes32("withdrawalHash", withdrawalHash); + bytes32 storageKey = keccak256( + abi.encode( + withdrawalHash, + uint256(1) // second slot + ) + ); + + return + Lib_SecureMerkleTrie.verifyInclusionProof( + abi.encodePacked(storageKey), + hex"01", + _withdrawalProof, + _outputRootProof.withdrawerRoot + ); } } diff --git a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol index 65015be632a2..d66613f18af4 100644 --- a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol +++ b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol @@ -49,6 +49,7 @@ contract WithdrawalVerifierTest is DSTest { bytes32 withdrawerRoot = 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; bytes32 latestBlockhash = keccak256(abi.encode(2)); WithdrawalVerifier.OutputRootProof outputRootProof; + bytes withdrawalProof = hex"f879b853f8518080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28808080808080a0fc935bb380a99df15c4aae91dacba616986d33af599d458d5388fa5fec3ac80780808080808080a3e2a036125dacbefad1d42a65c3425f7b5c8b559dac475adb31578315e77ec70a3f9701"; constructor() { // Move time forward so we have a non-zero starting timestamp @@ -100,7 +101,8 @@ contract WithdrawalVerifierTest is DSTest { 0, // value 50_000, // gasLimit hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data - outputRootProof + outputRootProof, + withdrawalProof ); } @@ -114,7 +116,8 @@ contract WithdrawalVerifierTest is DSTest { 0, // value 50_000, // gasLimit hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data - outputRootProof + outputRootProof, + hex"ffff" ); } @@ -131,7 +134,8 @@ contract WithdrawalVerifierTest is DSTest { 0, // value 50_000, // gasLimit hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data - invalidOutpuRootProof + invalidOutpuRootProof, + hex"ffff" ); } } From 1f69eda8c84b84ed177bce0c09fdc2721ad0ff41 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Sun, 3 Apr 2022 21:11:31 -0400 Subject: [PATCH 386/585] Improve testing against L2 node --- .../contracts/L1/WithdrawalVerifier.sol | 11 ++-- .../test/TestLib_SecureMerkleTrie.sol | 46 ++++++++++++++ packages/contracts/package.json | 3 +- packages/contracts/test/withdrawor.spec.ts | 62 ++++++++++++------- packages/contracts/yarn.lock | 2 +- 5 files changed, 93 insertions(+), 31 deletions(-) create mode 100644 packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol index 817f2379ed80..17be1b811245 100644 --- a/packages/contracts/contracts/L1/WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/WithdrawalVerifier.sol @@ -6,6 +6,7 @@ import { Lib_SecureMerkleTrie } from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; + /** * @title WithdrawalVerifier */ @@ -18,7 +19,7 @@ contract WithdrawalVerifier { uint256 timestamp; bytes32 version; bytes32 stateRoot; - bytes32 withdrawerRoot; + bytes32 withdrawerStorageRoot; bytes32 latestBlockhash; } @@ -49,7 +50,7 @@ contract WithdrawalVerifier { abi.encode( _outputRootProof.version, _outputRootProof.stateRoot, - _outputRootProof.withdrawerRoot, + _outputRootProof.withdrawerStorageRoot, _outputRootProof.latestBlockhash ) ), @@ -59,11 +60,11 @@ contract WithdrawalVerifier { bytes32 withdrawalHash = keccak256( abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) ); - emit log_named_bytes32("withdrawalHash", withdrawalHash); + bytes32 storageKey = keccak256( abi.encode( withdrawalHash, - uint256(1) // second slot + uint256(1) // The withdrawals mapping is at the second slot in the layout ) ); @@ -72,7 +73,7 @@ contract WithdrawalVerifier { abi.encodePacked(storageKey), hex"01", _withdrawalProof, - _outputRootProof.withdrawerRoot + _outputRootProof.withdrawerStorageRoot ); } } diff --git a/packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol b/packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol new file mode 100644 index 000000000000..5205ff84c2bb --- /dev/null +++ b/packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Library Imports */ +import { + Lib_SecureMerkleTrie +} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; + +/** + * @title TestLib_SecureMerkleTrie + */ +contract TestLib_SecureMerkleTrie { + function verifyInclusionProof( + bytes memory _key, + bytes memory _value, + bytes memory _proof, + bytes32 _root + ) public pure returns (bool) { + return Lib_SecureMerkleTrie.verifyInclusionProof(_key, _value, _proof, _root); + } + + function update( + bytes memory _key, + bytes memory _value, + bytes memory _proof, + bytes32 _root + ) public pure returns (bytes32) { + return Lib_SecureMerkleTrie.update(_key, _value, _proof, _root); + } + + function get( + bytes memory _key, + bytes memory _proof, + bytes32 _root + ) public pure returns (bool, bytes memory) { + return Lib_SecureMerkleTrie.get(_key, _proof, _root); + } + + function getSingleNodeRootHash(bytes memory _key, bytes memory _value) + public + pure + returns (bytes32) + { + return Lib_SecureMerkleTrie.getSingleNodeRootHash(_key, _value); + } +} diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 582b5980d0cf..a74512a71bfb 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -5,7 +5,8 @@ "main": "index.js", "license": "MIT", "dependencies": { - "hardhat": "^2.7.1" + "hardhat": "^2.7.1", + "rlp": "^2.2.7" }, "scripts": { "build:forge": "forge build", diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawor.spec.ts index 1e9028a7a39b..05c8643725c4 100644 --- a/packages/contracts/test/withdrawor.spec.ts +++ b/packages/contracts/test/withdrawor.spec.ts @@ -1,20 +1,18 @@ import { expect } from 'chai' -import hre from 'hardhat' import { Signer, BigNumber, Wallet, providers, ethers, utils } from 'ethers' -import { Withdrawor, Withdrawor__factory } from '../typechain' -import { toRpcHexString } from '@eth-optimism/core-utils' +import { + Withdrawor, + Withdrawor__factory, + TestLibSecureMerkleTrie, + TestLibSecureMerkleTrie__factory, +} from '../typechain' +import { toRpcHexString, toHexString } from '@eth-optimism/core-utils' +import * as rlp from 'rlp' -// not secret. Don't use for real shit. Don't submit bug reports if you find this in git. -// 0xf3c101f4e376e7994E78CFB13a3A7e4B40910983 const l2GethProvider = new providers.JsonRpcProvider('http://localhost:9545') -const l1GethProvider = new providers.JsonRpcProvider('http://localhost:8545') const withdraworAddress = '0x4200000000000000000000000000000000000015' -const ZERO_ADDRESS = '0x' + '00'.repeat(20) -const ZERO_BIGNUMBER = BigNumber.from(0) -const ZERO_BYTES32 = '0x' + '00'.repeat(32) const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) const NON_ZERO_GASLIMIT = BigNumber.from(50_000) -const NON_ZERO_VALUE = BigNumber.from(100) const NON_ZERO_DATA = '0x' + '11'.repeat(42) if (!process.env.PRIVATE_KEY) { @@ -47,18 +45,22 @@ describe('Withdraw', () => { let signer: Signer let signerAddress: string let withdrawor: Withdrawor + let testLibSecureMerkleTrie: TestLibSecureMerkleTrie before('Setup withdrawor contract', async () => { wallet = new Wallet(process.env.PRIVATE_KEY!) signer = wallet.connect(l2GethProvider) signerAddress = await signer.getAddress() withdrawor = await new Withdrawor__factory(signer).attach(withdraworAddress) + testLibSecureMerkleTrie = await ( + await new TestLibSecureMerkleTrie__factory(signer) + ).deploy() }) describe('Creating a withdrawal', () => { let withdrawalHash: string let nonceBefore: BigNumber - let storageSlot: string + let storageKey: string before(async () => { nonceBefore = await withdrawor.nonce() @@ -81,11 +83,6 @@ describe('Withdraw', () => { data: NON_ZERO_DATA, }) ) - - // locally calculate the expected storage slot in the contract - storageSlot = ethers.utils.keccak256( - withdrawalHash + '00'.repeat(31) + '01' - ) }) it('Should add an entry to the withdrawals mapping', async () => { @@ -94,22 +91,39 @@ describe('Withdraw', () => { expect(nonceAfter.sub(nonceBefore).toNumber()).to.eq(1) }) - it('Should return bytes32(1) when querying the calculated storage slot', async () => { - // Test to ensure we're correctly calculating the slot, per the solidity docs: - // "The value corresponding to a mapping key k is located at keccak256(h(k) . p) where . is - // concatenation and h is a function that is applied to the key..." + // Test to ensure we're correctly calculating the storageKey. Per the solidity docs: + // "The value corresponding to a mapping key k is located at keccak256(h(k) . p) where . is + // concatenation and h is a function that is applied to the key..." + it('Should return bytes32(1) when querying the calculated storage key', async () => { + const storageSlot = '00'.repeat(31) + '01' // i.e the second variable declared in the contract + storageKey = ethers.utils.keccak256(withdrawalHash + storageSlot) + expect( - await l2GethProvider.getStorageAt(withdraworAddress, storageSlot) + await l2GethProvider.getStorageAt(withdraworAddress, storageKey) ).to.equal(utils.hexZeroPad('0x01', 32)) }) - it('should generate a proof', async () => { + it('should generate a valid proof', async () => { + // Get the proof const proof = await l2GethProvider.send('eth_getProof', [ withdraworAddress, - [storageSlot], + [storageKey], toRpcHexString((await l2GethProvider.getBlock('latest')).number), ]) - expect(proof.storageProof[0].key).to.eq(storageSlot) + + // Sanity check expected values of the proof + expect(proof.storageProof[0].key).to.eq(storageKey) + expect(proof.storageProof[0].value).to.eq('0x1') + + // Check the proof directly against the SecureMerkleTrie lib + expect( + await testLibSecureMerkleTrie.verifyInclusionProof( + proof.storageProof[0].key, + '0x01', + toHexString(rlp.encode(proof.storageProof[0].proof)), + proof.storageHash + ) + ).to.be.true }) }) }) diff --git a/packages/contracts/yarn.lock b/packages/contracts/yarn.lock index 667b4624186b..416ab6d28565 100644 --- a/packages/contracts/yarn.lock +++ b/packages/contracts/yarn.lock @@ -8031,7 +8031,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== From 34abb5878175784b0c912545dd5e681de895c1db Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 10:30:25 -0400 Subject: [PATCH 387/585] Add finalizationWindow var to WithdrawalVerifier --- .../contracts/L1/WithdrawalVerifier.sol | 41 ++++--- packages/contracts/test/withdrawor.spec.ts | 102 ++++++++++++++++-- 2 files changed, 115 insertions(+), 28 deletions(-) diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol index 17be1b811245..09ed042929ee 100644 --- a/packages/contracts/contracts/L1/WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/WithdrawalVerifier.sol @@ -13,7 +13,7 @@ import { contract WithdrawalVerifier { L2OutputOracle public immutable l2Oracle; address public immutable withdrawalsPredeploy; - // todo: add an immutable finalization window var here + uint256 public immutable finalizationWindow; struct OutputRootProof { uint256 timestamp; @@ -23,9 +23,14 @@ contract WithdrawalVerifier { bytes32 latestBlockhash; } - constructor(L2OutputOracle _l2Oracle, address _withdrawalsPredeploy) { + constructor( + L2OutputOracle _l2Oracle, + address _withdrawalsPredeploy, + uint256 _finalizationWindow + ) { l2Oracle = _l2Oracle; withdrawalsPredeploy = _withdrawalsPredeploy; + finalizationWindow = _finalizationWindow; } function verifyWithdrawal( @@ -41,22 +46,24 @@ contract WithdrawalVerifier { // check that the timestamp is 7 days old // hash _outputRootProof and compare with the outputOracle's value // how do I get the withdrawal root itself? - require(_outputRootProof.timestamp <= block.timestamp - 7 days, "Too soon"); - - bytes32 outputRoot = l2Oracle.getL2Output(_outputRootProof.timestamp); - require( - outputRoot == - keccak256( - abi.encode( - _outputRootProof.version, - _outputRootProof.stateRoot, - _outputRootProof.withdrawerStorageRoot, - _outputRootProof.latestBlockhash - ) - ), - "Calculated output root does not match expected value" - ); + require(_outputRootProof.timestamp <= block.timestamp - finalizationWindow, "Too soon"); + // Add a block scope to avoid stack-too-deep + { + bytes32 outputRoot = l2Oracle.getL2Output(_outputRootProof.timestamp); + require( + outputRoot == + keccak256( + abi.encode( + _outputRootProof.version, + _outputRootProof.stateRoot, + _outputRootProof.withdrawerStorageRoot, + _outputRootProof.latestBlockhash + ) + ), + "Calculated output root does not match expected value" + ); + } bytes32 withdrawalHash = keccak256( abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) ); diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawor.spec.ts index 05c8643725c4..040d0f24d2de 100644 --- a/packages/contracts/test/withdrawor.spec.ts +++ b/packages/contracts/test/withdrawor.spec.ts @@ -5,12 +5,19 @@ import { Withdrawor__factory, TestLibSecureMerkleTrie, TestLibSecureMerkleTrie__factory, + WithdrawalVerifier, + WithdrawalVerifier__factory, + L2OutputOracle, + L2OutputOracle__factory, } from '../typechain' -import { toRpcHexString, toHexString } from '@eth-optimism/core-utils' +import { toRpcHexString, toHexString, Address } from '@eth-optimism/core-utils' import * as rlp from 'rlp' const l2GethProvider = new providers.JsonRpcProvider('http://localhost:9545') +const l1GethProvider = new providers.JsonRpcProvider('http://localhost:8545') + const withdraworAddress = '0x4200000000000000000000000000000000000015' + const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) const NON_ZERO_GASLIMIT = BigNumber.from(50_000) const NON_ZERO_DATA = '0x' + '11'.repeat(42) @@ -42,24 +49,31 @@ const encodeWithdrawal = (args: { describe('Withdraw', () => { let wallet: Wallet - let signer: Signer let signerAddress: string + let l1Signer: Signer + let l2Signer: Signer let withdrawor: Withdrawor let testLibSecureMerkleTrie: TestLibSecureMerkleTrie - before('Setup withdrawor contract', async () => { + let proof: any + let nonceBefore: BigNumber + + before('Setup L2 withdrawor contract', async () => { wallet = new Wallet(process.env.PRIVATE_KEY!) - signer = wallet.connect(l2GethProvider) - signerAddress = await signer.getAddress() + signerAddress = await wallet.getAddress() + l1Signer = wallet.connect(l1GethProvider) + l2Signer = wallet.connect(l2GethProvider) + + withdrawor = await new Withdrawor__factory(l2Signer).attach( + withdraworAddress + ) - withdrawor = await new Withdrawor__factory(signer).attach(withdraworAddress) testLibSecureMerkleTrie = await ( - await new TestLibSecureMerkleTrie__factory(signer) + await new TestLibSecureMerkleTrie__factory(l2Signer) ).deploy() }) - describe('Creating a withdrawal', () => { + describe('Creating a withdrawal on L2', () => { let withdrawalHash: string - let nonceBefore: BigNumber let storageKey: string before(async () => { nonceBefore = await withdrawor.nonce() @@ -76,7 +90,7 @@ describe('Withdraw', () => { withdrawalHash = ethers.utils.keccak256( encodeWithdrawal({ nonce: nonceBefore, - sender: signerAddress, + sender: await l2Signer.getAddress(), target: NON_ZERO_ADDRESS, value: 0, gasLimit: NON_ZERO_GASLIMIT, @@ -105,7 +119,7 @@ describe('Withdraw', () => { it('should generate a valid proof', async () => { // Get the proof - const proof = await l2GethProvider.send('eth_getProof', [ + proof = await l2GethProvider.send('eth_getProof', [ withdraworAddress, [storageKey], toRpcHexString((await l2GethProvider.getBlock('latest')).number), @@ -126,4 +140,70 @@ describe('Withdraw', () => { ).to.be.true }) }) + + describe('Finalizing a withdrawal on L1', () => { + let withdrawalVerifier: WithdrawalVerifier + let l2OutputOracle: L2OutputOracle + let l2Timestamp: BigNumber + before('Setup L1 system contracts', async () => { + // Deploy the L2 Output Oracle with a 1 second submission interval so that we can immediately + // test the withdrawal. + l2OutputOracle = await ( + await new L2OutputOracle__factory(l1Signer) + ).deploy( + 1, // submissionInterval + 1, // l2BlockTime + ethers.utils.keccak256('0x00'), // genesisL2Output + 100, // historicalTotalBlocks + signerAddress + ) + + // Deploy the WithdrawalVerifier with a 0 second finalization delay. + withdrawalVerifier = await ( + await new WithdrawalVerifier__factory(l1Signer) + ).deploy(l2OutputOracle.address, withdraworAddress, 0) + + // create an output root that we can prove against only the storage root matters + // for our purposes. + const outputRoot = ethers.utils.keccak256( + ethers.utils.defaultAbiCoder.encode( + ['bytes32', 'bytes32', 'bytes32', 'bytes32'], + [ + ethers.constants.HashZero, + ethers.constants.HashZero, + proof.storageHash, + ethers.constants.HashZero, + ] + ) + ) + + l2Timestamp = await l2OutputOracle.nextTimestamp() + await l2OutputOracle.appendL2Output( + outputRoot, + l2Timestamp, + ethers.constants.HashZero, + 0 + ) + }) + it('should successfully verify the withdrawal on L1', async () => { + const tx = await withdrawalVerifier.verifyWithdrawal( + nonceBefore, + signerAddress, + NON_ZERO_ADDRESS, + 0, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA, + { + timestamp: l2Timestamp, + version: ethers.constants.HashZero, + stateRoot: ethers.constants.HashZero, + withdrawerStorageRoot: proof.storageHash, + latestBlockhash: ethers.constants.HashZero, + }, + toHexString(rlp.encode(proof.storageProof[0].proof)), + { + gasLimit: 1_000_000, + } + ) + }).timeout(30000) }) From 56fbd9ce6b68b4ed9cddc4558ec3f095e527501a Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 10:32:11 -0400 Subject: [PATCH 388/585] Add WithdrawalVerified event --- .../contracts/L1/WithdrawalVerifier.sol | 26 ++++++++++++++----- packages/contracts/test/withdrawor.spec.ts | 3 +++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol index 09ed042929ee..33b125e422fe 100644 --- a/packages/contracts/contracts/L1/WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/WithdrawalVerifier.sol @@ -23,6 +23,15 @@ contract WithdrawalVerifier { bytes32 latestBlockhash; } + event WithdrawalVerified( + uint256 indexed messageNonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data + ); + constructor( L2OutputOracle _l2Oracle, address _withdrawalsPredeploy, @@ -75,12 +84,15 @@ contract WithdrawalVerifier { ) ); - return - Lib_SecureMerkleTrie.verifyInclusionProof( - abi.encodePacked(storageKey), - hex"01", - _withdrawalProof, - _outputRootProof.withdrawerStorageRoot - ); + bool verified = Lib_SecureMerkleTrie.verifyInclusionProof( + abi.encodePacked(storageKey), + hex"01", + _withdrawalProof, + _outputRootProof.withdrawerStorageRoot + ); + + emit WithdrawalVerified(_nonce, _sender, _target, _value, _gasLimit, _data); + + return verified; } } diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawor.spec.ts index 040d0f24d2de..8b47cee3f86d 100644 --- a/packages/contracts/test/withdrawor.spec.ts +++ b/packages/contracts/test/withdrawor.spec.ts @@ -205,5 +205,8 @@ describe('Withdraw', () => { gasLimit: 1_000_000, } ) + const events: any = (await tx.wait()).events + expect(events[0].event).to.equal('WithdrawalVerified') + }) }).timeout(30000) }) From 3fd310400a7bdfef43ce67318b976af1c9469d2b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 10:38:52 -0400 Subject: [PATCH 389/585] Remove unused constructor argument --- .../contracts/L1/WithdrawalVerifier.sol | 21 +++++++------------ .../contracts/test/WithdrawalVerifier.t.sol | 2 +- packages/contracts/test/withdrawor.spec.ts | 3 ++- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol index 33b125e422fe..947db0194ec1 100644 --- a/packages/contracts/contracts/L1/WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/WithdrawalVerifier.sol @@ -6,14 +6,12 @@ import { Lib_SecureMerkleTrie } from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; - /** * @title WithdrawalVerifier */ contract WithdrawalVerifier { - L2OutputOracle public immutable l2Oracle; - address public immutable withdrawalsPredeploy; - uint256 public immutable finalizationWindow; + L2OutputOracle public immutable L2_ORACLE; + uint256 public immutable FINALIZATION_WINDOW; struct OutputRootProof { uint256 timestamp; @@ -32,14 +30,9 @@ contract WithdrawalVerifier { bytes data ); - constructor( - L2OutputOracle _l2Oracle, - address _withdrawalsPredeploy, - uint256 _finalizationWindow - ) { - l2Oracle = _l2Oracle; - withdrawalsPredeploy = _withdrawalsPredeploy; - finalizationWindow = _finalizationWindow; + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationWindow) { + L2_ORACLE = _l2Oracle; + FINALIZATION_WINDOW = _finalizationWindow; } function verifyWithdrawal( @@ -55,11 +48,11 @@ contract WithdrawalVerifier { // check that the timestamp is 7 days old // hash _outputRootProof and compare with the outputOracle's value // how do I get the withdrawal root itself? - require(_outputRootProof.timestamp <= block.timestamp - finalizationWindow, "Too soon"); + require(_outputRootProof.timestamp <= block.timestamp - FINALIZATION_WINDOW, "Too soon"); // Add a block scope to avoid stack-too-deep { - bytes32 outputRoot = l2Oracle.getL2Output(_outputRootProof.timestamp); + bytes32 outputRoot = L2_ORACLE.getL2Output(_outputRootProof.timestamp); require( outputRoot == keccak256( diff --git a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol index d66613f18af4..c8d6bc7c7360 100644 --- a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol +++ b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol @@ -65,7 +65,7 @@ contract WithdrawalVerifierTest is DSTest { ); startingBlockTimestamp = block.timestamp; - wv = new WithdrawalVerifier(oracle, withdrawalsPredeploy); + wv = new WithdrawalVerifier(oracle, 7 days); } function setUp() external { diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawor.spec.ts index 8b47cee3f86d..74f7a501d7a1 100644 --- a/packages/contracts/test/withdrawor.spec.ts +++ b/packages/contracts/test/withdrawor.spec.ts @@ -161,7 +161,7 @@ describe('Withdraw', () => { // Deploy the WithdrawalVerifier with a 0 second finalization delay. withdrawalVerifier = await ( await new WithdrawalVerifier__factory(l1Signer) - ).deploy(l2OutputOracle.address, withdraworAddress, 0) + ).deploy(l2OutputOracle.address, 0) // create an output root that we can prove against only the storage root matters // for our purposes. @@ -185,6 +185,7 @@ describe('Withdraw', () => { 0 ) }) + it('should successfully verify the withdrawal on L1', async () => { const tx = await withdrawalVerifier.verifyWithdrawal( nonceBefore, From 03d936ad39e82fb24554a414cfd75971fcfc4fec Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 10:42:47 -0400 Subject: [PATCH 390/585] Clean up Forge test of WithdrawalVerifier --- .../contracts/test/WithdrawalVerifier.t.sol | 66 ++++++++++++------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol index c8d6bc7c7360..cd28e85591d5 100644 --- a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol +++ b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol @@ -41,15 +41,33 @@ contract WithdrawalVerifierTest is DSTest { // so we jump ahead to the exact time that I wrote this line. uint256 initTime = 1648757197; + // Withdrawal call parameters + uint256 wdNonce = 0; + address wdSender = 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5; + address wdTarget = 0x1111111111111111111111111111111111111111; + uint256 wdValue = 0; + uint256 wdGasLimit = 50_000; + bytes wdData = + hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; + // Generate an output that we can work with. We can use whatever values we want - // except for the withdrawerRoot. This one was generated by running the withdrawor.spec.ts + // except for the withdrawerStorageRoot. This one was generated by running the withdrawor.spec.ts // test script against Geth. bytes32 version = bytes32(hex"00"); bytes32 stateRoot = keccak256(abi.encode(1)); - bytes32 withdrawerRoot = 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; + bytes32 withdrawerStorageRoot = 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; // eth_getProof (storageHash) bytes32 latestBlockhash = keccak256(abi.encode(2)); + + // This proof was generated by running + // make devnet-up + // Then in another terminal + // packages/contracts/test/withdrawor.spec.ts + // Invalid large internal hash + bytes withdrawalProof = + hex"f879b853f8518080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28808080808080a0fc935bb380a99df15c4aae91dacba616986d33af599d458d5388fa5fec3ac80780808080808080a3e2a036125dacbefad1d42a65c3425f7b5c8b559dac475adb31578315e77ec70a3f9701"; + + // we'll set this value in the `setUp` function and cache it here for reuse in each test WithdrawalVerifier.OutputRootProof outputRootProof; - bytes withdrawalProof = hex"f879b853f8518080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28808080808080a0fc935bb380a99df15c4aae91dacba616986d33af599d458d5388fa5fec3ac80780808080808080a3e2a036125dacbefad1d42a65c3425f7b5c8b559dac475adb31578315e77ec70a3f9701"; constructor() { // Move time forward so we have a non-zero starting timestamp @@ -71,7 +89,7 @@ contract WithdrawalVerifierTest is DSTest { function setUp() external { vm.warp(initTime); bytes32 outputRoot = keccak256( - abi.encode(version, stateRoot, withdrawerRoot, latestBlockhash) + abi.encode(version, stateRoot, withdrawerStorageRoot, latestBlockhash) ); uint256 nextTimestamp = oracle.nextTimestamp(); @@ -86,7 +104,7 @@ contract WithdrawalVerifierTest is DSTest { timestamp: appendedTimestamp, version: version, stateRoot: stateRoot, - withdrawerRoot: withdrawerRoot, + withdrawerStorageRoot: withdrawerStorageRoot, latestBlockhash: latestBlockhash }); } @@ -95,12 +113,12 @@ contract WithdrawalVerifierTest is DSTest { // Warp to after the finality window vm.warp(appendedTimestamp + 7 days); wv.verifyWithdrawal( - 0, // nonce - 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5, // sender - 0x1111111111111111111111111111111111111111, // target - 0, // value - 50_000, // gasLimit - hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data + wdNonce, + wdSender, + wdTarget, + wdValue, + wdGasLimit, + wdData, outputRootProof, withdrawalProof ); @@ -110,30 +128,30 @@ contract WithdrawalVerifierTest is DSTest { // This call should fail because the output root we're using was appended 1 second ago. vm.expectRevert("Too soon"); wv.verifyWithdrawal( - 0, // nonce - 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5, // sender - 0x1111111111111111111111111111111111111111, // target - 0, // value - 50_000, // gasLimit - hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data + wdNonce, + wdSender, + wdTarget, + wdValue, + wdGasLimit, + wdData, outputRootProof, hex"ffff" ); } function test_cannotVerifyInvalidProof() external { - // This call should fail because the output root we're using was appended 1 second ago. + // This call should fail because the output proof is modified vm.warp(appendedTimestamp + 7 days); vm.expectRevert("Calculated output root does not match expected value"); WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; invalidOutpuRootProof.latestBlockhash = 0; wv.verifyWithdrawal( - 0, // nonce - 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5, // sender - 0x1111111111111111111111111111111111111111, // target - 0, // value - 50_000, // gasLimit - hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111", //data + wdNonce, + wdSender, + wdTarget, + wdValue, + wdGasLimit, + wdData, invalidOutpuRootProof, hex"ffff" ); From 23c5bdc533ce10036f4ab626f14c329ddc44280e Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 13:09:13 -0400 Subject: [PATCH 391/585] ops: Docker get l2 genesis hash on startup Docker fixes --- Makefile | 2 +- ops/Dockerfile.opnode | 8 +++++++- ops/docker-compose.yml | 17 +---------------- ops/opnode-entrypoint.sh | 27 +++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 ops/opnode-entrypoint.sh diff --git a/Makefile b/Makefile index f11d357907b9..186409505f56 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ devnet-up: DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ WITHDRAWOR_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawor.sol/Withdrawor.json | jq .deployedBytecode) \ - docker-compose up --build) + docker-compose up --build) .PHONY: devnet-up devnet-down: diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode index 1031e0db478c..ac80494a9eac 100644 --- a/ops/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -7,10 +7,16 @@ COPY go.mod /app/go.mod COPY go.sum /app/go.sum WORKDIR /app +COPY ./ops/opnode-entrypoint.sh /app/opnode-entrypoint.sh +COPY ./ops/rollup.json /app/rollup.json + COPY ./opnode /app/opnode RUN make opnode FROM alpine:3.13 COPY --from=builder /app/bin/op /usr/local/bin -CMD ["op"] +COPY --from=builder /app/opnode-entrypoint.sh /opnode-entrypoint.sh +COPY --from=builder /app/rollup.json /rollup.json + +ENTRYPOINT ["/bin/sh", "/opnode-entrypoint.sh"] diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 0cac506c0d9c..a55f451018f2 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -41,19 +41,4 @@ services: - ${PWD}/bss-key.txt:/config/bss-key.txt - ${PWD}/rollup.json:/config/rollup.json command: - - "op" - - "--l1" - - "ws://l1:8546" - - "--l2" - - "ws://l2:8546" - - "--sequencing.enabled" - - "--rollup.config" - - "/config/rollup.json" - - "--batchsubmitter.key" - - "/config/bss-key.txt" - - "--l2.eth" - - "http://l2:8545" - - "--rpc.addr" - - "0.0.0.0" - - "--rpc.port" - - "8545" + - "opnode-entrypoint.sh" diff --git a/ops/opnode-entrypoint.sh b/ops/opnode-entrypoint.sh new file mode 100644 index 000000000000..745f88fff195 --- /dev/null +++ b/ops/opnode-entrypoint.sh @@ -0,0 +1,27 @@ +#!/bin/sh +set -exu + +curl \ + --retry 5 \ + --retry-delay 2 \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + http://localhost:9545 \ + | jq -r ".result.hash" \ + | tee l2_genesis_hash.txt + +cat /rollup.json \ + | jq ". | .genesis.l2.hash = \"${cat l2_genesis_hash.txt}\"" \ + | tee /rollup-with-l2-hash.json && \ + mv /rollup-with-l2-hash.json /rollup.json + +exec op \ + --l1 ws://l1:8546 \ + --l2 ws://l2:8546 \ + --sequencing.enabled \ + --rollup.config /config/rollup.json \ + --batchsubmitter.key /config/bss-key.txt \ + --l2.eth http://l2:8545 \ + --rpc.addr 0.0.0.0 \ + --rpc.port 8545 From ec73d8af855077117a998f4b803d829499ad8e66 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 14:46:53 -0400 Subject: [PATCH 392/585] contracts: ignore dirty submodules --- .gitmodules | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitmodules b/.gitmodules index f38688f818ba..7b93ec874984 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,16 @@ [submodule "packages/contracts/lib/ds-test"] path = packages/contracts/lib/ds-test url = https://github.com/dapphub/ds-test + ignore = dirty [submodule "packages/contracts/lib/openzeppelin-contracts"] path = packages/contracts/lib/openzeppelin-contracts url = https://github.com/openzeppelin/openzeppelin-contracts + ignore = dirty [submodule "packages/contracts/lib/forge-std"] path = packages/contracts/lib/forge-std url = https://github.com/brockelmore/forge-std + ignore = dirty [submodule "packages/contracts/lib/optimism"] path = packages/contracts/lib/optimism url = https://github.com/ethereum-optimism/optimism + ignore = dirty From a49177b319a7f1ce5678cd870212e447f8d500ef Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 14:51:30 -0400 Subject: [PATCH 393/585] Don't run hardhat tests in CI --- .github/workflows/solidity-ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/solidity-ci.yml b/.github/workflows/solidity-ci.yml index a8fa89ecbac6..094cbb09cc51 100644 --- a/.github/workflows/solidity-ci.yml +++ b/.github/workflows/solidity-ci.yml @@ -32,11 +32,12 @@ jobs: cache: 'yarn' - run: yarn install - - name: Build with HH - run: yarn build:hh + # We don't currently have any hardhat tests that should run in this context + # - name: Build with HH + # run: yarn build:hh - - name: Test - run: yarn test:hh + # # - name: Test + # # run: yarn test:hh - name: Lint run: yarn lint:check From ba17fdd967d259424c9a81d8d33a6e7e2c7e6bc9 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 22:13:51 -0400 Subject: [PATCH 394/585] Create Optimism Portal contract --- .../contracts/contracts/L1/OptimismPortal.sol | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 packages/contracts/contracts/L1/OptimismPortal.sol diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol new file mode 100644 index 000000000000..2e8a09ebd12c --- /dev/null +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -0,0 +1,15 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { DepositFeed } from "./DepositFeed.sol"; +import { WithdrawalVerifier } from "./WithdrawalVerifier.sol"; +import { L2OutputOracle } from "./L2OutputOracle.sol"; + + +contract OptimismPortal is DepositFeed, WithdrawalVerifier { + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationWindow) + WithdrawalVerifier(_l2Oracle, _finalizationWindow) + {} + + +} From a9385400edb8a010e4b296b1f4093ced6f29f12b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 22:15:01 -0400 Subject: [PATCH 395/585] Move receive function to OptimismPortal --- .../contracts/contracts/L1/DepositFeed.sol | 10 ------- .../contracts/contracts/L1/OptimismPortal.sol | 9 ++++++ .../contracts/test/DepositFeed.t.sol | 20 ------------- .../contracts/test/WithdrawalVerifier.t.sol | 30 +++++++++++++++++++ 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index fb567229f21a..c8f33ed9ea3b 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -26,16 +26,6 @@ contract DepositFeed { bytes data ); - /** - * Accepts value so that users can send ETH directly to this contract and - * have the funds be deposited to their address on L2. - * Note: this is intended as a convenience function for EOAs. Contracts should call the - * depositTransaction() function directly. - */ - receive() external payable { - depositTransaction(msg.sender, msg.value, 30000, false, bytes("")); - } - /** * Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving * deposit transactions. diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index 2e8a09ebd12c..c6cdfc95cf5f 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -12,4 +12,13 @@ contract OptimismPortal is DepositFeed, WithdrawalVerifier { {} + /** + * Accepts value so that users can send ETH directly to this contract and + * have the funds be deposited to their address on L2. + * Note: this is intended as a convenience function for EOAs. Contracts should call the + * depositTransaction() function directly. + */ + receive() external payable { + depositTransaction(msg.sender, msg.value, 30000, false, bytes("")); + } } diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol index 215f5fddbf2a..14f1ad3622b9 100644 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -148,26 +148,6 @@ contract DepositFeedTest is DSTest { assertEq(address(df).balance, NON_ZERO_VALUE); } - // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH - function test_receive_withEthValueFromEOA() external { - // EOA emulation - vm.prank(address(this), address(this)); - - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - address(this), - address(this), - NON_ZERO_VALUE, - NON_ZERO_VALUE, - 30_000, - false, - hex"" - ); - address(df).call{ value: NON_ZERO_VALUE }(hex""); - - assertEq(address(df).balance, NON_ZERO_VALUE); - } - // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH function test_depositTransaction_withEthValueFromContract() external { vm.expectEmit(true, true, false, true); diff --git a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol index cd28e85591d5..28f574536f60 100644 --- a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol +++ b/packages/contracts/contracts/test/WithdrawalVerifier.t.sol @@ -13,6 +13,17 @@ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { WithdrawalVerifier } from "../L1/WithdrawalVerifier.sol"; contract WithdrawalVerifierTest is DSTest { + + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 mint, + uint256 value, + uint256 gasLimit, + bool isCreation, + bytes data + ); + // Utilities Vm vm = Vm(HEVM_ADDRESS); bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); @@ -156,4 +167,23 @@ contract WithdrawalVerifierTest is DSTest { hex"ffff" ); } + + function test_receive_withEthValueFromEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + address(this), + address(this), + 100, + 100, + 30_000, + false, + hex"" + ); + address(op).call{ value: 100 }(hex""); + + assertEq(address(op).balance, 100); + } } From de7389de24eed66ad709acbbffa5c96e3aa244d6 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 5 Apr 2022 11:38:35 -0600 Subject: [PATCH 396/585] specs: Add overview page (#286) --- specs/assets/components.svg | 4 + specs/assets/derivation-1.svg | 4 + specs/assets/derivation-2.svg | 4 + specs/assets/derivation-3.svg | 4 + specs/assets/engine.svg | 4 + .../assets/network-participants-overview.svg | 4 + specs/assets/propagation.svg | 4 + specs/assets/sequencer-block-gen.svg | 4 + ...cer-handling-deposits-and-transactions.svg | 4 + specs/assets/user-withdrawing-to-l1.svg | 4 + .../assets/verifier-executing-fraud-proof.svg | 4 + specs/introduction.md | 159 ++++++++++++++ specs/overview.md | 198 ++++++++++++++++++ 13 files changed, 401 insertions(+) create mode 100644 specs/assets/components.svg create mode 100644 specs/assets/derivation-1.svg create mode 100644 specs/assets/derivation-2.svg create mode 100644 specs/assets/derivation-3.svg create mode 100644 specs/assets/engine.svg create mode 100644 specs/assets/network-participants-overview.svg create mode 100644 specs/assets/propagation.svg create mode 100644 specs/assets/sequencer-block-gen.svg create mode 100644 specs/assets/sequencer-handling-deposits-and-transactions.svg create mode 100644 specs/assets/user-withdrawing-to-l1.svg create mode 100644 specs/assets/verifier-executing-fraud-proof.svg create mode 100644 specs/introduction.md create mode 100644 specs/overview.md diff --git a/specs/assets/components.svg b/specs/assets/components.svg new file mode 100644 index 000000000000..e2526006c638 --- /dev/null +++ b/specs/assets/components.svg @@ -0,0 +1,4 @@ + + + +
DepositFeed
DepositFeed
L2OutputOracle
L2OutputOracle
Rollup
Node
Rollup...
Batch Submitter
Batch Submitter
L2 Execution Engine
(L2 Geth)
L2 Execution Engine...
BatchInbox
BatchInbox
L1
L1
L2
L2
Output Submitter
Output Submitter
Legend
Legend
Sequencer
Sequencer
Verifier
Verifier
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/derivation-1.svg b/specs/assets/derivation-1.svg new file mode 100644 index 000000000000..b22b32a1cebf --- /dev/null +++ b/specs/assets/derivation-1.svg @@ -0,0 +1,4 @@ + + + +
1
1
2
2
3
3
4
4
Sequencing Window (Epoch 1)
Sequencing Window (Epoch 1)
5
5
Sequencing Window (Epoch 2)
Sequencing Window (Epoch 2)
L1
L1
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/derivation-2.svg b/specs/assets/derivation-2.svg new file mode 100644 index 000000000000..32738befbe60 --- /dev/null +++ b/specs/assets/derivation-2.svg @@ -0,0 +1,4 @@ + + + +
1
1
2
2
3
3
4
4
Sequencing Window (Epoch 1)
Sequencing Window (Epoch 1)
5
5
Sequencing Window (Epoch 2)
Sequencing Window (Epoch 2)
L1
L1
Deposit
Deposit
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Rollup
Node
Data
Rollup...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/derivation-3.svg b/specs/assets/derivation-3.svg new file mode 100644 index 000000000000..4fd603be9529 --- /dev/null +++ b/specs/assets/derivation-3.svg @@ -0,0 +1,4 @@ + + + +
1
1
2
2
3
3
4
4
Sequencing Window (Epoch 1)
Sequencing Window (Epoch 1)
5
5
Sequencing Window (Epoch 2)
Sequencing Window (Epoch 2)
L1
L1
Deposit
Deposit
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Tx Batch
Rollup
Node
Data
Rollup...
2
2
3
3
4
4
L1 Info
L1 Info
5
5
L2
L2
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/engine.svg b/specs/assets/engine.svg new file mode 100644 index 000000000000..084684a4ba5b --- /dev/null +++ b/specs/assets/engine.svg @@ -0,0 +1,4 @@ + + + +
Rollup Driver
Rollup Driver
Engine API
Engine API
PayloadAttributes

- timestamp
- random
- suggestedFeeRecipient
- transactions
PayloadAttributes...
ForkChoiceState

- headBlockHash
- safeBlockHash
- finalizedBlockHash
ForkChoiceState...
FCS
FCS
PA
PA
payloadID
payloadID
Initiate block
production
Initiate block...
engine_forkChoiceUpdatedV1
engine_forkChoiceUpdatedV1
payload
payload
engine_getPayloadV1
(payloadID)
engine_getPayloadV1...
engine_executePayloadV1
(payload)
engine_executePayloadV1...
engine_forkChoiceUpdatedV1
engine_forkChoiceUpdatedV1
FCS
FCS
Current L2
block hash
Current L2...
payload.blockHash
payload.blockHash
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/network-participants-overview.svg b/specs/assets/network-participants-overview.svg new file mode 100644 index 000000000000..d70a983f7b9d --- /dev/null +++ b/specs/assets/network-participants-overview.svg @@ -0,0 +1,4 @@ + + + +
Ethereum L1 Chain
Ethereum L1 Chain

Network Participants Overview

Network Participants Overview
Query data
(eg. block explorers)
Query data...
Submit transactions
Submit transactions
Submit deposits
Submit deposits
Users
Users
Submit batches and assertions
Submit batches and assertions
P2P Realtime Updates
P2P Realtime Updates
Verifiers
Verifi...
Verify block hash assertions &
submit fraud proofs
Verify block hash assertions &...
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/specs/assets/propagation.svg b/specs/assets/propagation.svg new file mode 100644 index 000000000000..d95494eac5da --- /dev/null +++ b/specs/assets/propagation.svg @@ -0,0 +1,4 @@ + + + +
Engine API
Engine API
Rollup
Node
Rollup...
EE
EE
L1
L1
L2
L2
Batch Submitter
Batch Submitter
Output Submitter
Output Submitter
BatchInbox
BatchInbox
DepositFeed
DepositFeed
Rollup
Node
Rollup...
EE
EE
Unsafe
Block
Propagation
Unsafe...
TX Sync
TX Sync
State Sync
State Sync
Legend
Legend
Sequencer
Sequencer
Verifier
Verifier
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/sequencer-block-gen.svg b/specs/assets/sequencer-block-gen.svg new file mode 100644 index 000000000000..8b463b07b860 --- /dev/null +++ b/specs/assets/sequencer-block-gen.svg @@ -0,0 +1,4 @@ + + + +
Epoch 3
Epoch 3
Epoch 2
Epoch 2
Epoch 1
Epoch 1
L1
L1
D1
D1
B1
B1
L2
L2
D2
D2
B3
B3
B2
B2
D2
D2
B1
B1
D1
D1
B3
B3
B4
B4
B5
B5
B4
B4
B2
B2
B5
B5
D3
D3
B6
B6
B7
B7
B6
B6
B7
B7
D3
D3
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/sequencer-handling-deposits-and-transactions.svg b/specs/assets/sequencer-handling-deposits-and-transactions.svg new file mode 100644 index 000000000000..c6a8b8185125 --- /dev/null +++ b/specs/assets/sequencer-handling-deposits-and-transactions.svg @@ -0,0 +1,4 @@ + + + +
3. Insert deposit block
3. Insert deposit block
Rollup Node
Rollup Node
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to the batch inbox
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the batch inbox.
Queries for all...
Batch Inbox
Batch Inbox

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
L2 Output Submitter
L2 Output Submitter
Queries for the next
assertable block hash &
submits it to the
L2 Output Oracle.
Queries for the next...
L2 Output Oracle
L2 Output Oracle
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/user-withdrawing-to-l1.svg b/specs/assets/user-withdrawing-to-l1.svg new file mode 100644 index 000000000000..99fd8419063f --- /dev/null +++ b/specs/assets/user-withdrawing-to-l1.svg @@ -0,0 +1,4 @@ + + + +
Ethereum L1 Chain
Ethereum L1 Chain
Batch Inbox
Batch Inbox
L2 Output Oracle
L2 Output Oracle
3. Assert block hash
containing withdrawal
commitment
3. Assert block hash...
2. Post batch
with withdrawal
transaction data
2. Post batch...
1. Send
initiate
withdrawal

transaction
1. Send...
5. Send
execute
withdrawal

transaction
5. Send...
4. Wait for block
hash to finalize
4. Wait for block...
User
User
ERC20
ERC20
6. Verify
withdrawal
in finalized
block hash
6. Verify...
7.
Transfer
tokens
7....
Bridge
Bridge
Sequencers
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/assets/verifier-executing-fraud-proof.svg b/specs/assets/verifier-executing-fraud-proof.svg new file mode 100644 index 000000000000..29428313323c --- /dev/null +++ b/specs/assets/verifier-executing-fraud-proof.svg @@ -0,0 +1,4 @@ + + + +
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Node
Rollup Node
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 Output Oracle Contract
L2 Output Oracle Contract
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Text is not SVG - cannot display
\ No newline at end of file diff --git a/specs/introduction.md b/specs/introduction.md new file mode 100644 index 000000000000..133804888463 --- /dev/null +++ b/specs/introduction.md @@ -0,0 +1,159 @@ +# Optimistic Ethereum Introduction + + + +**Table of Contents** + +- [Foundations](#foundations) + - [What is Ethereum scalability?](#what-is-ethereum-scalability) + - [What is an Optimistic Rollup?](#what-is-an-optimistic-rollup) + - [What is EVM Equivalence?](#what-is-evm-equivalence) + - [🎶 All together now 🎶](#-all-together-now-) +- [Protocol Guarantees](#protocol-guarantees) +- [Network Participants](#network-participants) + - [Users](#users) + - [Sequencers](#sequencers) + - [Verifiers](#verifiers) +- [Key Interaction Diagrams](#key-interaction-diagrams) + - [Depositing and Sending Transactions](#depositing-and-sending-transactions) + - [Withdrawing](#withdrawing) +- [Next Steps](#next-steps) + + + +Optimism is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_ while remaining maximally +compatible with existing Ethereum infrastructure. This document provides an overview of the protocol to provide context +for the rest of the specification. + +## Foundations + +### What is Ethereum scalability? + +Scaling Ethereum means increasing the number of useful transactions the Ethereum network can process. Ethereum's +limited resources, specifically bandwidth, computation, and storage, constrain the number of transactions which can be +processed on the network. Of the three resources, computation and storage are currently the most significant +bottlenecks. These bottlenecks limit the supply of transactions, leading to extremely high fees. Scaling ethereum and +reducing fees can be achieved by better utilizing bandwidth, computation and storage. + +### What is an Optimistic Rollup? + +[Optimistic rollup](https://vitalik.ca/general/2021/01/05/rollup.html) is a layer 2 scalability technique which +increases the computation & storage capacity of Ethereum without sacrificing security or decentralization. Transaction +data is submitted on-chain but executed off-chain. If there is an error in the off-chain execution, a fraud proof can +be submitted on-chain to correct the error and protect user funds. In the same way you don't go to court unless there +is a dispute, you don't execute transactions on on-chain unless there is an error. + +### What is EVM Equivalence? + +[EVM Equivalence](https://medium.com/ethereum-optimism/introducing-evm-equivalence-5c2021deb306) is complete compliance +with the state transition function described in the Ethereum yellow paper, the formal definition of the protocol. By +conforming to the Ethereum standard across EVM equivalent rollups, smart contract developers can write once and deploy +anywhere. + +### 🎶 All together now 🎶 + +**Optimistic Ethereum is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_.** + +## Protocol Guarantees + +In order to scale Ethereum without sacrificing security, we must preserve 3 critical properties of Ethereum layer 1: +liveness, availability, and validity. + +1. **Liveness** - Anyone must be able to extend the rollup chain by sending transactions at any time. + - There are two ways transactions can be sent to the rollup chain: 1) via the sequencer, and 2) directly on layer +2. The sequencer provides low latency & low cost transactions, while sending transactions directly to layer 1 provides +censorship resistance. +3. **Availability** - Anyone must be able to download the rollup chain. + - All information required to derive the chain is embedded into layer 1 blocks. That way as long as the layer 1 +chain is available, so is the rollup. +4. **Validity** - All transactions must be correctly executed and all withdrawals correctly processed. + - The rollup state and withdrawals are managed on an L1 contract called the `L2 State Oracle`. This oracle is +guaranteed to _only_ finalize correct (ie. valid) rollup block hashes given a **single honest verifier** assumption. If +there is ever an invalid block hash asserted on layer 1, an honest verifier will prove it is invalid and win a bond. + +**Footnote**: There are two main ways to enforce validity of a rollup: fraud proofs (optimistic rollup) and validity +proofs (zkRollup). For the purposes of this spec we only focus on fraud proofs but it is worth noting that validity +proofs can also be plugged in once they have been made feasible. + +## Network Participants + +There are three actors in Optimistic Ethereum: users, sequencers, and verifiers. + +![Network Overview](./assets/network-participants-overview.svg) + +### Users + +At the heart of the network are users (us!). Users can: + +1. Deposit or withdraw arbitrary transactions on L2 by sending data to a contract on Ethereum mainnet. +2. Use EVM smart contracts on layer 2 by sending transactions to the sequencers. +3. View the status of transactions using block explorers provided by network verifiers. + +### Sequencers + +The sequencer is the primary block producer. There may be one sequencer **or** many using a consensus protocol. For +1.0.0, there is just one sequencer. In general, specifications may use "the sequencer" to be a stand-in term for the +consensus protocol operated by multiple sequencers. + +The sequencer: + +1. Accepts user off-chain transactions +2. Observes on-chain transactions (primarily, deposit events coming from L1) +3. Consolidates both kinds of transactions into L2 blocks with a specific ordering. +4. Propagates consolidated L2 blocks to L1, by submitting two things as calldata to L1: + - The pending off-chain transactions accepted in step 1. + - Sufficient information about the ordering of the on-chain transactions to successfully reconstruct the blocks +from step 3., purely by watching L1. + +The sequencer also provides access to block data as early as step 3., so that users may access real-time state in +advance of L1 confirmation if they so choose. + +### Verifiers + +Verifiers serve two purposes: + +1. Serving rollup data to users; and +2. Verifying rollup integrity and disputing invalid assertions. + +In order for the network to remain secure there must be **at least** one honest verifier who is able to verify the +integrity of the rollup chain & serve blockchain data to users. + +## Key Interaction Diagrams + +The following diagrams demonstrate how protocol components are utilized during key user interactions in order to +provide context when diving into any particular component specification. + +### Depositing and Sending Transactions + +Users will often begin their L2 journey by depositing ETH from L1. Once they have ETH to pay fees, they'll start +sending transactions on L2. The following diagram demonstrates this interaction and all key Optimistic Ethereum +components which are utilized: + +![Diagram of Depositing and Sending Transactions](./assets/sequencer-handling-deposits-and-transactions.svg) + +Links to components mentioned in this diagram: + +- Batch Inbox (WIP) +- [Rollup Node](./rollup-node.md) +- [Execution Engine](./exec-engine.md) +- Sequencer Batch Submitter (WIP) +- [L2 Output Oracle](./proposals.md#l2-output-oracle-smart-contract) +- [L2 Output Submitter](./proposals#proposing-l2-output-commitments) +- Fraud Proof VM (WIP) + +### Withdrawing + +Just as important as depositing, it is critical that users can withdraw from the rollup. Withdrawals are initiated by +normal transactions on L2, but then completed using a transaction on L1 after the dispute period has elapsed. + +![Diagram of Withdrawing](./assets/user-withdrawing-to-l1.svg) + +Links to components mentioned in this diagram: + +- [L2 Output Oracle](./proposals.md#l2-output-oracle-smart-contract) + +## Next Steps + +This is a choose your own adventure. Are you interested in how a verifier works under the hood? Maybe you want to dive +deep into the bit flippin' Fraud Proof VM? All key components have been linked at least once in this doc, so you should +now have the context you need to dive in deeper. [The world is yours](https://www.youtube.com/watch?v=e5PnuIRnJW8)! diff --git a/specs/overview.md b/specs/overview.md new file mode 100644 index 000000000000..a550c8c50190 --- /dev/null +++ b/specs/overview.md @@ -0,0 +1,198 @@ +# Optimism Overview + + + +**Table of Contents** + +- [Architecture Design Goals](#architecture-design-goals) +- [Components](#components) + - [L1 Components](#l1-components) + - [L2 Components](#l2-components) + - [Transaction/Block Propagation](#transactionblock-propagation) +- [Key Interactions In Depth](#key-interactions-in-depth) + - [Deposits](#deposits) + - [Block Derivation](#block-derivation) + - [Overview](#overview) + - [Epochs and the Sequencing Window](#epochs-and-the-sequencing-window) + - [Block Derivation Loop](#block-derivation-loop) + - [Engine API](#engine-api) + + + +This document is a high-level technical overview of the Optimism protocol. It aims to explain how the protocol works in +an informal manner, and direct readers to other parts of the specification so that they may learn more. + +This document assumes you've read the [introduction](./introduction.md). + +## Architecture Design Goals + +- **Execution-Level EVM Equivalence:** The developer experience should be identical to L2 except where L2 introduces a +fundamental difference. + - No special compiler. + - No unexpected gas costs. + - Transaction traces work out-of-the-box. + - All existing Ethereum tooling works - all you have to do is change the chain ID. +- **Maximal compatibility with ETH1 nodes:** The implementation should minimize any differences with a vanilla Geth +node, and leverage as many existing L1 standards as possible. + - The execution engine/rollup node use the ETH2 Engine API to build the canonical L2 chain. + - The execution engine leverages Geth's existing mempool and sync implementations, including snap sync. +- **Minimize state and complexity:** + - Whenever possible, services contributing to the rollup infrastructure are stateless. + - Stateful services can recover to full operation from a fresh DB using the peer-to-peer network and on-chain sync +mechanisms. + - Running a replica is as simple as running a Geth node. + +## Components + +![Components](./assets/components.svg) + +### L1 Components + +- **DepositFeed**: A feed of L2 transactions which originated as smart contract calls in the L1 state. + - The `DepositFeed` contract emits `TransactionDeposited` events, which the rollup driver reads in order to process +deposits. + - Deposits are guaranteed to be reflected in the L2 state within the _sequencing window_. + - Beware that _transactions_ are deposited, not tokens. However deposited transactions are a key part of implementing +token deposits (tokens are locked on L1, then minted on L2 via a deposited transaction). +- **BatchInbox**: An L1 address to which the Batch Submitter submits transaction batches. + - Transaction batches include L2 transaction calldata, timestamps, and ordering information. + - The BatchInbox is a regular EOA address. This lets us pass on gast cost savings by not executing any EVM code. + +- **L2OutputOracle**: A smart contract that stores [L2 output roots](./glossary.md#l2-output) for use with withdrawals +and fraud proofs. + +### L2 Components + +- **Rollup Node**: + - A standalone, stateless binary. + - Receives L2 transactions from users. + - Syncs and verifies rollup data on L1. + - Applies rollup-specific block production rules to synthesize blocks from L1. + - Appends blocks to the L2 chain using the Engine API. + - Handles L1 reorgs. + - Distributes unsubmitted blocks to other rollup nodes. +- **Execution Engine (EE)**: + - A vanilla Geth node with minor modifications to support Optimism. + - Maintains L2 state. + - Sync state to other L2 nodes for fast onboarding. + - Serves the Engine API to the rollup node. +- **Batch Submitter** + - A background process that submits [transaction batches](./glossary.md#sequencer-batch) to the `BatchInbox` address. +- **Output Submitter** + - A background process that submits L2 output commitments to the `L2OutputOracle`. + +### Transaction/Block Propagation + +**Spec links:** + +- [Execution Engine](specs/exec-engine.md) + +Since the EE uses Geth under the hood, Optimism uses Geth's built-in peer-to-peer network and transaction pool to +propagate transactions. The same network can also be used to propagate submitted blocks and support snap-sync. + +Unsubmitted blocks, however, are propagated using a separate peer-to-peer network of Rollup Nodes. This is optional, +however, and is provided as a convnience to lower latency for verifiers and their JSON-RPC clients. + +The below diagram illustrates how the sequencer and verifiers fit together: + +![Propagation](./assets/propagation.svg) + +## Key Interactions In Depth + +### Deposits + +**Spec links:** + +- [Deposits](./deposits.md) + +Optimism supports two types of deposits: user deposits, and L1 attributes deposits. To perform a user deposit, users +call the `depositTransaction` method on the `DepositFeed` contract. This in turn emits `TransactionDeposited` events, +which the rollup node reads during block derivation. + +L1 attributes deposits are used to register L1 block attributes (number, timestamp, etc.) on L2 via a call to the L1 +Attributes Predeploy. They cannot be initiated by users, and are instead added to L2 blocks automatically by the rollup +node. + +Both deposit types are represented by a single custom EIP-2718 transaction type on L2. + +### Block Derivation + +#### Overview + +The rollup chain can be deterministically derived given an L1 Ethereum chain. The fact that the entire rollup chain can +be derived based on L1 blocks is _what makes Optimism a rollup_. This process can be represented as: + +```text +derive_rollup_chain(l1_blockchain) -> rollup_blockchain +``` + +Optimism's block derivation function is designed such that it: + +- Requires no state other than what is easily accessible using L1 and L2 execution engine APIs. +- Supports sequencers and sequencer consensus. +- Is resilient to sequencer censorship. + +#### Epochs and the Sequencing Window + +The rollup chain is subdivided into epochs. There is a 1:1 correspondence between L1 block numbers and epoch numbers. +For L1 block number `n`, there is a corresponding rollup epoch `n` which can only be derived a "sequencing windows" has +passed, i.e. after L1 block number `n + SEQUENCING_WINDOW_SIZE` is added to the L1 chain. + +Each epoch contains at least one block. Every block in the epoch contains an L1 info transaction which contains +contextual information about L1 such as the block hash and timestamp. The first block in the epoch also contains all +deposits initiated via the `DepositFeed` contract on L1. All L2 blocks can also contain _sequenced transactions_, i.e. +transactions submitted directly to the sequencer. + +Whenever the sequencer creates a new L2 block for a given epoch, it must submit it to L1 as part of a _batch_, within +the epoch's sequencing window (i.e. the batch must land before L1 block `n + SEQUENCING_WINDOW_SIZE`). These batches are +(along with the `TransactionDeposited` L1 events) what allows the derivation of the L2 chain from the L1 chain. + +The sequencer does not need for a L2 block to be batch-submitted to L1 in order to build on top of it. In fact, batches +typically contain multiple L2 blocks worth of sequenced transaction. This is what enables +_fast transaction confirmations_ on the sequencer. + +Since transaction batches for a given epoch can be submitted anywhere within the sequencing window, verifiers must +search all blocks within the window for transaction batches. This protects against the uncertainty of transaction +inclusion of L1. This uncertainty is also why we need the sequencing window in the first place: otherwise the sequencer +could retroactively add blocks to an old epoch, and validators wouldn't know when they can finalize an epoch. + +The sequencing window also prevents censorship by the sequencer: deposits made on a given L1 block will be included in +the L2 chain at worst after `SEQUENCING_WINDOW_SIZE` L1 blocks have passed. + +The following diagram describes this relationship, and how L2 blocks are derived from L1 blocks (L1 info transactions +have been elided): + +![Epochs and Sequencing Windows](./assets/sequencer-block-gen.svg) + +#### Block Derivation Loop + +A sub-component of the rollup node called the _rollup driver_ is actually responsible for performing block derivation. +The rollup driver is essentially an infinite loop that runs the block derivation function. For each epoch, the block +derivation function performs the following steps: + +1. Downloads deposit and transaction batch data for each block in the sequencing window. +2. Converts the deposit and transaction batch data into payload attributes for the Engine API. +3. Submits the payload attributes to the Engine API, where they are converted into blocks and added to the canonical +chain. + +This process is then repeated with incrementing epohcs until the tip of L1 is reached. + +### Engine API + +The rollup driver doesn't actually create blocks. Instead, it directs the execution engine to do so via the Engine API. +For each iteration of the block derivation loop described above, the rollup driver will craft a _payload attributes_ +object and send it to the execution engine. The execution engine will then convert the payload attributes object into a +block, and add it to the chain. The basic sequence the rollup driver is as follows: + +1. Call `engine_forkChoiceUpdatedV1` with the payload attributes object. We'll skip over the details of the fork choice +state parameter for now - just know that one of its fields is the L2 chain's `headBlockHash`, and that it is set to the +block hash of the tip of the L2 chain. The Engine API returns a payload ID. +2. Call `engine_getPayloadV1` with the payload ID returned in step 1. The engine API returns a payload object that +includes a block hash as one of its fields. +3. Call `engine_executePayloadV1` with the payload returned in step 2. +4. Call `engine_forkChoiceUpdatedV1` with the fork choice parameter's `headBlockHash` set to the block hash returned in +step 2. The tip of the L2 chain is now the block created in step 1. + +The swimlane diagram below visualizes the process: + +![Engine API](./assets/engine.svg) From 44b861b14a0ffc390fd5bc80a18c7529e5c18407 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 4 Apr 2022 23:52:35 -0400 Subject: [PATCH 397/585] Convert WithdrawalVerifier to a library This changes the WithdrawalVerifier to be stateless, and moves all checks into the OptimismPortal --- .../contracts/L1/Lib_WithdrawalVerifier.sol | 57 ++++++++++++ .../contracts/contracts/L1/OptimismPortal.sol | 79 +++++++++++++++- .../contracts/L1/WithdrawalVerifier.sol | 91 ------------------- ...walVerifier.t.sol => OptimismPortal.t.sol} | 15 +-- 4 files changed, 139 insertions(+), 103 deletions(-) create mode 100644 packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol delete mode 100644 packages/contracts/contracts/L1/WithdrawalVerifier.sol rename packages/contracts/contracts/test/{WithdrawalVerifier.t.sol => OptimismPortal.t.sol} (93%) diff --git a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol new file mode 100644 index 000000000000..2db34801bdc0 --- /dev/null +++ b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol @@ -0,0 +1,57 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { L2OutputOracle } from "./L2OutputOracle.sol"; +import { + Lib_SecureMerkleTrie +} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; + +/** + * @title WithdrawalVerifier + */ +library WithdrawalVerifier { + struct OutputRootProof { + uint256 timestamp; + bytes32 version; + bytes32 stateRoot; + bytes32 withdrawerStorageRoot; + bytes32 latestBlockhash; + } + + function _verifyWithdrawerStorageRoot( + bytes32 _outputRoot, + OutputRootProof calldata _outputRootProof + ) internal pure returns (bool) { + return + _outputRoot == + keccak256( + abi.encode( + _outputRootProof.version, + _outputRootProof.stateRoot, + _outputRootProof.withdrawerStorageRoot, + _outputRootProof.latestBlockhash + ) + ); + } + + function _verifyWithdrawalInclusion( + bytes32 _withdrawalHash, + bytes32 _withdrawerStorageRoot, + bytes calldata _withdrawalProof + ) internal pure returns (bool) { + bytes32 storageKey = keccak256( + abi.encode( + _withdrawalHash, + uint256(1) // The withdrawals mapping is at the second slot in the layout + ) + ); + + return + Lib_SecureMerkleTrie.verifyInclusionProof( + abi.encodePacked(storageKey), + hex"01", + _withdrawalProof, + _withdrawerStorageRoot + ); + } +} diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index c6cdfc95cf5f..ba3cf7ca72d2 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -2,15 +2,25 @@ pragma solidity 0.8.10; import { DepositFeed } from "./DepositFeed.sol"; -import { WithdrawalVerifier } from "./WithdrawalVerifier.sol"; +import { WithdrawalVerifier } from "./Lib_WithdrawalVerifier.sol"; import { L2OutputOracle } from "./L2OutputOracle.sol"; +contract OptimismPortal is DepositFeed { + event WithdrawalFinalized(bytes32 indexed); -contract OptimismPortal is DepositFeed, WithdrawalVerifier { - constructor(L2OutputOracle _l2Oracle, uint256 _finalizationWindow) - WithdrawalVerifier(_l2Oracle, _finalizationWindow) - {} + // Value used to reset the l2Sender. This is more gas efficient that setting it to zero. + address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; + uint256 public immutable FINALIZATION_WINDOW; + L2OutputOracle public immutable L2_ORACLE; + + address public l2Sender = DEFAULT_L2_SENDER; + mapping(bytes32 => bool) public finalizedWithdrawals; + + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationWindow) { + L2_ORACLE = _l2Oracle; + FINALIZATION_WINDOW = _finalizationWindow; + } /** * Accepts value so that users can send ETH directly to this contract and @@ -21,4 +31,63 @@ contract OptimismPortal is DepositFeed, WithdrawalVerifier { receive() external payable { depositTransaction(msg.sender, msg.value, 30000, false, bytes("")); } + + /** + * Finalizes a withdrawal transaction. + * @param _nonce Nonce for the provided message. + * @param _sender Message sender address on L2. + * @param _target Target address on L1. + * @param _data Data to send to the target. + * @param _gasLimit Gas to be forwarded to the target. + * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. + * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. + */ + function finalizeWithdrawalTransaction( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes calldata _data, + WithdrawalVerifier.OutputRootProof calldata _outputRootProof, + bytes calldata _withdrawalProof + ) external { + // Check that the timestamp is 7 days old. + require(_outputRootProof.timestamp <= block.timestamp - FINALIZATION_WINDOW, "Too soon"); + + // Get the output root and verify that the withdrawer contract's storage root is contained + // in it. + bytes32 outputRoot = L2_ORACLE.getL2Output(_outputRootProof.timestamp); + require( + WithdrawalVerifier._verifyWithdrawerStorageRoot(outputRoot, _outputRootProof) == true, + "Calculated output root does not match expected value" + ); + + // Verify that the hash of the withdrawal transaction's arguments are included in the + // storage hash of the withdrawer contract. + bytes32 withdrawalHash = keccak256( + abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) + ); + require( + WithdrawalVerifier._verifyWithdrawalInclusion( + withdrawalHash, + _outputRootProof.withdrawerStorageRoot, + _withdrawalProof + ) == true, + "Withdrawal transaction not found in storage" + ); + + // Check that this withdrawal has not already been finalized. + require(finalizedWithdrawals[withdrawalHash] == false, "Withdrawal already finalized"); + + // Make the call. + l2Sender = _sender; + _target.call{ value: _value, gas: _gasLimit }(_data); + l2Sender = DEFAULT_L2_SENDER; + + // All withdrawals are immediately finalized. If the ability to replay a transaction is + // required, that support can be provided in external contracts. + finalizedWithdrawals[withdrawalHash] = true; + emit WithdrawalFinalized(withdrawalHash); + } } diff --git a/packages/contracts/contracts/L1/WithdrawalVerifier.sol b/packages/contracts/contracts/L1/WithdrawalVerifier.sol deleted file mode 100644 index 947db0194ec1..000000000000 --- a/packages/contracts/contracts/L1/WithdrawalVerifier.sol +++ /dev/null @@ -1,91 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.10; - -import { L2OutputOracle } from "./L2OutputOracle.sol"; -import { - Lib_SecureMerkleTrie -} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; - -/** - * @title WithdrawalVerifier - */ -contract WithdrawalVerifier { - L2OutputOracle public immutable L2_ORACLE; - uint256 public immutable FINALIZATION_WINDOW; - - struct OutputRootProof { - uint256 timestamp; - bytes32 version; - bytes32 stateRoot; - bytes32 withdrawerStorageRoot; - bytes32 latestBlockhash; - } - - event WithdrawalVerified( - uint256 indexed messageNonce, - address indexed sender, - address indexed target, - uint256 value, - uint256 gasLimit, - bytes data - ); - - constructor(L2OutputOracle _l2Oracle, uint256 _finalizationWindow) { - L2_ORACLE = _l2Oracle; - FINALIZATION_WINDOW = _finalizationWindow; - } - - function verifyWithdrawal( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes calldata _data, - OutputRootProof calldata _outputRootProof, - bytes calldata _withdrawalProof - ) external returns (bool) { - // check that the timestamp is 7 days old - // hash _outputRootProof and compare with the outputOracle's value - // how do I get the withdrawal root itself? - require(_outputRootProof.timestamp <= block.timestamp - FINALIZATION_WINDOW, "Too soon"); - - // Add a block scope to avoid stack-too-deep - { - bytes32 outputRoot = L2_ORACLE.getL2Output(_outputRootProof.timestamp); - require( - outputRoot == - keccak256( - abi.encode( - _outputRootProof.version, - _outputRootProof.stateRoot, - _outputRootProof.withdrawerStorageRoot, - _outputRootProof.latestBlockhash - ) - ), - "Calculated output root does not match expected value" - ); - } - bytes32 withdrawalHash = keccak256( - abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) - ); - - bytes32 storageKey = keccak256( - abi.encode( - withdrawalHash, - uint256(1) // The withdrawals mapping is at the second slot in the layout - ) - ); - - bool verified = Lib_SecureMerkleTrie.verifyInclusionProof( - abi.encodePacked(storageKey), - hex"01", - _withdrawalProof, - _outputRootProof.withdrawerStorageRoot - ); - - emit WithdrawalVerified(_nonce, _sender, _target, _value, _gasLimit, _data); - - return verified; - } -} diff --git a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol similarity index 93% rename from packages/contracts/contracts/test/WithdrawalVerifier.t.sol rename to packages/contracts/contracts/test/OptimismPortal.t.sol index 28f574536f60..09658de7184d 100644 --- a/packages/contracts/contracts/test/WithdrawalVerifier.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -8,11 +8,12 @@ import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; /* Target contract dependencies */ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { WithdrawalVerifier } from "../L1/Lib_WithdrawalVerifier.sol"; /* Target contract */ -import { WithdrawalVerifier } from "../L1/WithdrawalVerifier.sol"; +import { OptimismPortal } from "../L1/OptimismPortal.sol"; -contract WithdrawalVerifierTest is DSTest { +contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { event TransactionDeposited( address indexed from, @@ -39,7 +40,7 @@ contract WithdrawalVerifierTest is DSTest { uint256 historicalTotalBlocks = 100; // Test target - WithdrawalVerifier wv; + OptimismPortal op; // Target constructor arguments address withdrawalsPredeploy = 0x4200000000000000000000000000000000000015; @@ -94,7 +95,7 @@ contract WithdrawalVerifierTest is DSTest { ); startingBlockTimestamp = block.timestamp; - wv = new WithdrawalVerifier(oracle, 7 days); + op = new OptimismPortal(oracle, 7 days); } function setUp() external { @@ -123,7 +124,7 @@ contract WithdrawalVerifierTest is DSTest { function test_verifyWithdrawal() external { // Warp to after the finality window vm.warp(appendedTimestamp + 7 days); - wv.verifyWithdrawal( + op.finalizeWithdrawalTransaction( wdNonce, wdSender, wdTarget, @@ -138,7 +139,7 @@ contract WithdrawalVerifierTest is DSTest { function test_cannotVerifyRecentWithdrawal() external { // This call should fail because the output root we're using was appended 1 second ago. vm.expectRevert("Too soon"); - wv.verifyWithdrawal( + op.finalizeWithdrawalTransaction( wdNonce, wdSender, wdTarget, @@ -156,7 +157,7 @@ contract WithdrawalVerifierTest is DSTest { vm.expectRevert("Calculated output root does not match expected value"); WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; invalidOutpuRootProof.latestBlockhash = 0; - wv.verifyWithdrawal( + op.finalizeWithdrawalTransaction( wdNonce, wdSender, wdTarget, From cad0a0f561afd50f479f1d6fdec8e15514c2b240 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 00:13:38 -0400 Subject: [PATCH 398/585] contracts: Rename Withdrawor to Withdrawer --- Makefile | 2 +- ops/Dockerfile.l2 | 4 +-- ops/docker-compose.yml | 2 +- .../L2/{Withdrawor.sol => Withdrawer.sol} | 4 +-- .../contracts/test/OptimismPortal.t.sol | 4 +-- ...{withdrawor.spec.ts => withdrawer.spec.ts} | 26 +++++++++---------- specs/withdrawals.md | 10 ++++--- 7 files changed, 27 insertions(+), 25 deletions(-) rename packages/contracts/contracts/L2/{Withdrawor.sol => Withdrawer.sol} (95%) rename packages/contracts/test/{withdrawor.spec.ts => withdrawer.spec.ts} (91%) diff --git a/Makefile b/Makefile index 186409505f56..1d2d4a76cc14 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ devnet-up: @(cd ./ops && \ DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ - WITHDRAWOR_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawor.sol/Withdrawor.json | jq .deployedBytecode) \ + WITHDRAWER_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json | jq .deployedBytecode) \ docker-compose up --build) .PHONY: devnet-up diff --git a/ops/Dockerfile.l2 b/ops/Dockerfile.l2 index 2a44a6653028..7777d68949a6 100644 --- a/ops/Dockerfile.l2 +++ b/ops/Dockerfile.l2 @@ -1,7 +1,7 @@ FROM mslipper/reference-optimistic-geth:latest ARG L1_BLOCK_INFO_BYTECODE="" -ARG WITHDRAWOR_BYTECODE="" +ARG WITHDRAWER_BYTECODE="" RUN apk add --no-cache jq @@ -9,7 +9,7 @@ COPY entrypoint.sh /entrypoint.sh COPY genesis-l2.json /genesis.json RUN cat /genesis.json | jq ". | .alloc.\"4200000000000000000000000000000000000014\".code = \"$L1_BLOCK_INFO_BYTECODE\"" \ - | jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$WITHDRAWOR_BYTECODE\"" \ + | jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$WITHDRAWER_BYTECODE\"" \ | tee /genesis-with-bytecode.json && \ mv /genesis-with-bytecode.json /genesis.json diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index a55f451018f2..db652e1a8f76 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -22,7 +22,7 @@ services: dockerfile: Dockerfile.l2 args: L1_BLOCK_INFO_BYTECODE: $L1_BLOCK_INFO_BYTECODE - WITHDRAWOR_BYTECODE: $WITHDRAWOR_BYTECODE + WITHDRAWER_BYTECODE: $WITHDRAWER_BYTECODE ports: - "9545:8545" volumes: diff --git a/packages/contracts/contracts/L2/Withdrawor.sol b/packages/contracts/contracts/L2/Withdrawer.sol similarity index 95% rename from packages/contracts/contracts/L2/Withdrawor.sol rename to packages/contracts/contracts/L2/Withdrawer.sol index b47252adfa95..024d1873db79 100644 --- a/packages/contracts/contracts/L2/Withdrawor.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -2,9 +2,9 @@ pragma solidity 0.8.10; /** - * @title Withdrawor + * @title Withdrawer */ -contract Withdrawor { +contract Withdrawer { uint256 public nonce; mapping(bytes32 => bool) public withdrawals; diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index 09658de7184d..368f48f1d62d 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -63,7 +63,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; // Generate an output that we can work with. We can use whatever values we want - // except for the withdrawerStorageRoot. This one was generated by running the withdrawor.spec.ts + // except for the withdrawerStorageRoot. This one was generated by running the withdrawer.spec.ts // test script against Geth. bytes32 version = bytes32(hex"00"); bytes32 stateRoot = keccak256(abi.encode(1)); @@ -73,7 +73,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { // This proof was generated by running // make devnet-up // Then in another terminal - // packages/contracts/test/withdrawor.spec.ts + // packages/contracts/test/withdrawer.spec.ts // Invalid large internal hash bytes withdrawalProof = hex"f879b853f8518080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28808080808080a0fc935bb380a99df15c4aae91dacba616986d33af599d458d5388fa5fec3ac80780808080808080a3e2a036125dacbefad1d42a65c3425f7b5c8b559dac475adb31578315e77ec70a3f9701"; diff --git a/packages/contracts/test/withdrawor.spec.ts b/packages/contracts/test/withdrawer.spec.ts similarity index 91% rename from packages/contracts/test/withdrawor.spec.ts rename to packages/contracts/test/withdrawer.spec.ts index 74f7a501d7a1..60e346d50ad0 100644 --- a/packages/contracts/test/withdrawor.spec.ts +++ b/packages/contracts/test/withdrawer.spec.ts @@ -1,8 +1,8 @@ import { expect } from 'chai' import { Signer, BigNumber, Wallet, providers, ethers, utils } from 'ethers' import { - Withdrawor, - Withdrawor__factory, + Withdrawer, + Withdrawer__factory, TestLibSecureMerkleTrie, TestLibSecureMerkleTrie__factory, WithdrawalVerifier, @@ -16,7 +16,7 @@ import * as rlp from 'rlp' const l2GethProvider = new providers.JsonRpcProvider('http://localhost:9545') const l1GethProvider = new providers.JsonRpcProvider('http://localhost:8545') -const withdraworAddress = '0x4200000000000000000000000000000000000015' +const withdrawerAddress = '0x4200000000000000000000000000000000000015' const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) const NON_ZERO_GASLIMIT = BigNumber.from(50_000) @@ -52,19 +52,19 @@ describe('Withdraw', () => { let signerAddress: string let l1Signer: Signer let l2Signer: Signer - let withdrawor: Withdrawor + let withdrawer: Withdrawer let testLibSecureMerkleTrie: TestLibSecureMerkleTrie let proof: any let nonceBefore: BigNumber - before('Setup L2 withdrawor contract', async () => { + before('Setup L2 withdrawer contract', async () => { wallet = new Wallet(process.env.PRIVATE_KEY!) signerAddress = await wallet.getAddress() l1Signer = wallet.connect(l1GethProvider) l2Signer = wallet.connect(l2GethProvider) - withdrawor = await new Withdrawor__factory(l2Signer).attach( - withdraworAddress + withdrawer = await new Withdrawer__factory(l2Signer).attach( + withdrawerAddress ) testLibSecureMerkleTrie = await ( @@ -76,10 +76,10 @@ describe('Withdraw', () => { let withdrawalHash: string let storageKey: string before(async () => { - nonceBefore = await withdrawor.nonce() + nonceBefore = await withdrawer.nonce() await ( - await withdrawor.initiateWithdrawal( + await withdrawer.initiateWithdrawal( NON_ZERO_ADDRESS, NON_ZERO_GASLIMIT, NON_ZERO_DATA @@ -100,8 +100,8 @@ describe('Withdraw', () => { }) it('Should add an entry to the withdrawals mapping', async () => { - const nonceAfter = await withdrawor.nonce() - expect(await withdrawor.withdrawals(withdrawalHash)).to.be.true + const nonceAfter = await withdrawer.nonce() + expect(await withdrawer.withdrawals(withdrawalHash)).to.be.true expect(nonceAfter.sub(nonceBefore).toNumber()).to.eq(1) }) @@ -113,14 +113,14 @@ describe('Withdraw', () => { storageKey = ethers.utils.keccak256(withdrawalHash + storageSlot) expect( - await l2GethProvider.getStorageAt(withdraworAddress, storageKey) + await l2GethProvider.getStorageAt(withdrawerAddress, storageKey) ).to.equal(utils.hexZeroPad('0x01', 32)) }) it('should generate a valid proof', async () => { // Get the proof proof = await l2GethProvider.send('eth_getProof', [ - withdraworAddress, + withdrawerAddress, [storageKey], toRpcHexString((await l2GethProvider.getBlock('latest')).number), ]) diff --git a/specs/withdrawals.md b/specs/withdrawals.md index 50fd30fdec7f..2b5525382de2 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -73,7 +73,7 @@ These inputs must satisfy the following conditions: **On L2:** -1. An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdrawor` predeploy contract. +1. An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdrawer` predeploy contract. This is a very simple contract that stores a mapping from the hash of the `WithdrawalMessage` as defined above to a boolean value. (`mapping (bytes32 => bool) withdrawalMessages`) 2. If ETH is being withdrawn, it can eventually be burned by deploying a contract which immediately `SELFDESTRUCT`s. @@ -96,12 +96,10 @@ These inputs must satisfy the following conditions: The L2 Withdrawals predeploy is a simple contract at `0x4200000000000000000000000000000000000015` which stores messages to be withdrawn. -> **Backware** - It contains a mapping which records withdrawals. ```js -interface Withdrawor { +interface Withdrawer { event WithdrawalMessage( uint256 indexed messageNonce, // this is a global nonce value for all withdrawal messages @@ -147,6 +145,8 @@ If the execution of the relayed call fails in the `target` contracts, it is unfo whether or not it was 'supposed' to fail, and whether or not it should be 'replayable'. Thus we provide the following mitigations: +// TODO: finish this sentence... + 1. The minimum gas amount to be [Insufficient Gas Griefing]:(https://swcregistry.io/docs/SWC-126) @@ -163,6 +163,8 @@ This `FINALIZATION_WINDOW` value is equivalent to 7 days. ### Data Structures and Type Aliases +> TODO: update this section is quite outdated with current impl + 1. A `WithdrawalMessage` is encoded in a struct as follows: ```js From d41fcc9a85a5f785eb095ce878f86a4e4e940787 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 5 Apr 2022 01:32:55 +0200 Subject: [PATCH 399/585] specs: define timestamp bounds of derivation process, clear up block derivation, define missing noTxPool field --- specs/exec-engine.md | 11 +++++-- specs/rollup-node.md | 73 +++++++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/specs/exec-engine.md b/specs/exec-engine.md index f2faa59b96df..2f7cc6b3e250 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -72,11 +72,12 @@ to [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1]: the extended `Pay the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: ```js -PayloadAttributesOPV1: { +PayloadAttributesV1: { timestamp: QUANTITY random: DATA (32 bytes) suggestedFeeRecipient: DATA (20 bytes) transactions: array of DATA + noTxPool: bool } ``` @@ -91,10 +92,14 @@ The `transactions` field is optional: - If empty or missing: no changes to engine behavior. The sequencers will (if enabled) build a block by consuming transactions from the transaction pool. -- If present and non-empty: the payload MUST only be produced with this exact list of transactions. +- If present and non-empty: the payload MUST be produced starting with this exact list of transactions. The [rollup driver][rollup-driver] determines the transaction list based on deterministic L1 inputs. -> **TODO**: derivation function spec in rollup node doc or separate driver doc +The `noTxPool` is optional as well, and extends the `transactions` meaning: + +- If `false`, the execution engine is free to pack additional transactions from external sources like the tx pool + into the payload, after any of the `transactions`. This is the default behavior a L1 node implements. +- If `true`, the execution engine must not change anything about the given list of `transactions`. [rollup-driver]: rollup-node.md diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 4b68c0083943..f582e9453767 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -45,12 +45,12 @@ currently only concerned with the specification of the rollup driver. **Table of Contents** - [L2 Chain Derivation](#l2-chain-derivation) - - [From L1 chain to Sequencing Window](#from-l1-chain-to-sequencing-window) - - [From L1 Blocks to Payload Attributes](#from-l1-blocks-to-payload-attributes) + - [From L1 Sequencing window to L2 Payload Attributes](#from-l1-sequencing-window-to-l2-payload-attributes) - [Reading L1 inputs](#reading-l1-inputs) - [Encoding the L1 Attributes Deposited Transaction](#encoding-the-l1-attributes-deposited-transaction) - [Encoding User-Deposited Transactions](#encoding-user-deposited-transactions) - - [Building the Payload Attributes](#building-the-payload-attributes) + - [Deriving all Payload Attributes of a sequencing window](#deriving-all-payload-attributes-of-a-sequencing-window) + - [Building individual Payload Attributes](#building-individual-payload-attributes) - [From Payload Attributes to L2 Block](#from-payload-attributes-to-l2-block) - [Inductive Derivation Step](#inductive-derivation-step) - [Engine API Error Handling](#engine-api-error-handling) @@ -78,7 +78,7 @@ Every L2 block carries transactions of two categories: ------------------------------------------------------------------------------------------------------------------------ -## From L1 chain to Sequencing Window +## From L1 Sequencing window to L2 Payload Attributes A [sequencing window][g-sequencing-window] is a fixed number consecutive L1 blocks that a derivation step takes as input. The window is identified by an `epoch`, equal to the block number of the first block in the window. @@ -86,25 +86,7 @@ input. The window is identified by an `epoch`, equal to the block number of the As the full derivation of the L2 chain by the driver progresses each derivation step shifts the window forward by a single L1 block: the windows overlap. -Each sequencing window is derived into a variable number of L2 blocks, depending on the timestamps of L1 and L2. - -The L2 has a fixed block time and no more than one batch per block, -meaning that gaps between the batches (ordered by timestamp) are interpreted as batches with empty transaction-lists, -thus construing L2 blocks that only contain deposit transaction(s). - -The L2 blocks produced by a sequencing window are bounded by timestamp: - -- `min_l2_timestamp = prev_l2_timestamp + l2_block_time` -- `max_l2_timestamp = l1_timestamp + l2_block_time`, where `l1_timestamp` is the timestamp of the - first L1 block of the sequencing window. (maximum bound, may not be aligned with block time) - -If there are no batches present in the sequencing window then the L2 chain is extended up to `max_l2_timestamp` (incl.) -with empty batches, but otherwise regular block derivation. - -Note that with short block times on L1 the L2 time may increment beyond the L1 time, -but the longer target block time of L1 will correct back and allow the timestamps to align again. - -## From L1 Blocks to Payload Attributes +Each sequencing window is derived into a variable number of L2 blocks, following the below derivation steps. ### Reading L1 inputs @@ -126,9 +108,16 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi - Batches not matching filter criteria are ignored: - `batch.epoch == sequencing_window.epoch`, i.e. for this sequencing window - `(batch.timestamp - genesis_l2_timestamp) % block_time == 0`, i.e. timestamp is aligned - - `min_l2_timestamp < batch.timestamp < max_l2_timestamp`, i.e. timestamp is within range + - `min_l2_timestamp <= batch.timestamp < max_l2_timestamp`, i.e. timestamp is within range + - `min_l2_timestamp = prev_l2_timestamp + l2_block_time` + - `prev_l2_timestamp` is the timestamp of the previous L2 block: the last block of the previous epoch, + or the L2 genesis block timestamp if there is no previous epoch. + - `l2_block_time` is a configurable parameter of the time between L2 blocks + - `max_l2_timestamp = max(l1_timestamp + max_sequencer_drift, min_l2_timestamp + l2_block_time)` + - `l1_timestamp` is the timestamp of the L1 block associated with the L2 block's epoch + - `max_sequencer_drift` is the most a sequencer is allowed to get ahead of L1 - The batch is the first batch with `batch.timestamp` in this sequencing window, - i.e. one batch per L2 block number + i.e. one batch per L2 block number - The batch only contains sequenced transactions, i.e. it must NOT contain any Deposit-type transactions. [random]: https://eips.ethereum.org/EIPS/eip-4399 @@ -192,21 +181,37 @@ To encode user-deposited transactions, refer to the following sections of the de - [The Deposited Transaction Type](deposits.md#the-deposited-transaction-type) - [User-Deposited Transactions](deposits.md#user-deposited-transactions) -### Building the Payload Attributes +### Deriving all Payload Attributes of a sequencing window + +A sequencing window is derived into a variable number of L2 blocks, defined by a range of timestamps: + +- Starting at `min_l2_timestamp`, as defined in the batch filtering. +- Up to and including + `new_head_l2_timestamp = max(highest_valid_batch_timestamp, next_l1_timestamp - l2_block_time, min_l2_timestamp)` + - `highest_valid_batch_timestamp = max(batch.timestamp for batch in filtered_batches)`, + or `0` if no there are no `filtered_batches`. + - `next_l1_timestamp` is the timestamp of the next L1 block. + +The L2 chain is extended to `new_head_l2_timestamp`, has a fixed block time, and no more than one batch per block. +This means that every `l2_block_time` that has no batch is interpreted as one with an empty sequenced transaction-list, +thus construing a L2 block that only contains deposit transaction(s). + +#### Building individual Payload Attributes -[payload attributes]: #building-the-payload-attributes +[payload attributes]: #building-individual-payload-attributes -From the data read from L1 and the encoded transactions, the rollup node constructs the [payload +From timestamped transaction lists derived from the sequencing window, the rollup node constructs [payload attributes][g-payload-attr] as an [expanded version][expanded-payload] of the [`PayloadAttributesV1`] object, which -includes an additional `transactions` field. +includes additional `transactions` and `noTxPool` fields. -The object's properties must be set as follows: +Each of the timestamped transaction lists translates to a `PayloadAttributesV1` as follows: -- `timestamp` is set to the timestamp of the L1 block. -- `random` is set to the *random* L1 block attribute +- `timestamp` is set to the timestamp of the L2 block. +- `random` is set to the *random* `execution_payload.prev_randao` L1 block attribute - `suggestedFeeRecipient` is set to an address determined by the system -- `transactions` is an array of the derived transactions: deposited transactions and sequenced transactions. - All encoded with [EIP-2718]. Sequenced transactions must exclude any Deposit-type transactions. +- `transactions` is the array of the derived transactions: deposited transactions and sequenced transactions. + All encoded with [EIP-2718]. +- `noTxPool` is set to `true`, to use the exact above `transactions` list when constructing the block. [expanded-payload]: exec-engine.md#extended-payloadattributesv1 [`PayloadAttributesV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 From 3e74be6ac0f949b08bd5485d4d8c081ff5841ab0 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 5 Apr 2022 04:05:57 +0200 Subject: [PATCH 400/585] opnode/rollup: implement new timestamp bounds on block derivation batch filtering and filling --- opnode/rollup/derive/payload_attributes.go | 15 +++++++++++++-- opnode/rollup/driver/step.go | 17 ++++++++++++----- opnode/rollup/types.go | 4 ++-- opnode/rollup/types_test.go | 14 +++++++------- opnode/test/system_test.go | 16 ++++++++-------- 5 files changed, 42 insertions(+), 24 deletions(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 1c284cd4134c..a43d3c6da940 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -252,13 +252,24 @@ type L2Info interface { } // FillMissingBatches turns a collection of batches to the input batches for a series of blocks -func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, maxL2Time uint64) []*BatchData { +func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, nextL1Time uint64) []*BatchData { m := make(map[uint64]*BatchData) + // The number of L2 blocks per sequencing window is variable, we do not immediately fill to maxL2Time: + // - ensure at least 1 block + // - fill up to the next L1 block time stamp, if higher, to keep up with L1 time + // - fill up to the last valid batch, to keep up with L2 time + newHeadL2Timestamp := minL2Time + if nextL1Time > newHeadL2Timestamp+blockTime { + newHeadL2Timestamp = nextL1Time - blockTime + } for _, b := range batches { m[b.BatchV1.Timestamp] = b + if b.Timestamp > newHeadL2Timestamp { + newHeadL2Timestamp = b.Timestamp + } } var out []*BatchData - for t := minL2Time; t < maxL2Time; t += blockTime { + for t := minL2Time; t <= newHeadL2Timestamp; t += blockTime { b, ok := m[t] if ok { out = append(out, b) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 0d7cb0126ef3..458e27d52d70 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -103,11 +103,11 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, // It returns the new L2 head and L2 Safe head and if there was a reorg. This function must return if there was a reorg otherwise the L2 chain must be traversed. func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) { // Sanity Checks - if len(l1Input) == 0 { - return l2Head, l2SafeHead, false, fmt.Errorf("empty L1 sequencing window on L2 %s", l2SafeHead) + if len(l1Input) <= 1 { + return l2Head, l2SafeHead, false, fmt.Errorf("too small L1 sequencing window for L2 derivation on %s: %v", l2SafeHead, l1Input) } if len(l1Input) != int(d.Config.SeqWindowSize) { - return l2Head, l2SafeHead, false, errors.New("Invalid sequencing window size") + return l2Head, l2SafeHead, false, errors.New("invalid sequencing window size") } logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], "input_l2_parent", l2SafeHead, "finalized_l2", l2Finalized) @@ -128,6 +128,10 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S if l2SafeHead.L1Origin.Hash != l1Info.ParentHash() { return l2Head, l2SafeHead, false, fmt.Errorf("l1Info %v does not extend L1 Origin (%v) of L2 Safe Head (%v)", l1Info.Hash(), l2SafeHead.L1Origin, l2SafeHead) } + nextL1Block, err := d.dl.InfoByHash(ctx, l1Input[1].Hash) + if err != nil { + return l2Head, l2SafeHead, false, fmt.Errorf("failed to get L1 timestamp of next L1 block: %v", err) + } deposits, err := derive.DeriveDeposits(l2SafeHead.Number+1, receipts) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to derive deposits: %w", err) @@ -143,9 +147,12 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S } // Make batches contiguous minL2Time := l2Info.Time() + d.Config.BlockTime - maxL2Time := l1Info.Time() + maxL2Time := l1Info.Time() + d.Config.MaxSequencerDrift + if minL2Time+d.Config.BlockTime > maxL2Time { + maxL2Time = minL2Time + d.Config.BlockTime + } batches = derive.FilterBatches(&d.Config, epoch, minL2Time, maxL2Time, batches) - batches = derive.FillMissingBatches(batches, uint64(epoch), d.Config.BlockTime, minL2Time, maxL2Time) + batches = derive.FillMissingBatches(batches, uint64(epoch), d.Config.BlockTime, minL2Time, nextL1Block.Time()) fc := l2.ForkchoiceState{ HeadBlockHash: l2Head.Hash, diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go index bb9ed7e9b0e9..6551e58716b5 100644 --- a/opnode/rollup/types.go +++ b/opnode/rollup/types.go @@ -24,12 +24,12 @@ type Config struct { Genesis Genesis `json:"genesis"` // Seconds per L2 block BlockTime uint64 `json:"block_time"` - // Sequencer batches may not be more than MaxSequencerTimeDiff seconds after + // Sequencer batches may not be more than MaxSequencerDrift seconds after // the L1 timestamp of the sequencing window end. // // Note: When L1 has many 1 second consecutive blocks, and L2 grows at fixed 2 seconds, // the L2 time may still grow beyond this difference. - MaxSequencerTimeDiff uint64 `json:"max_sequencer_time_diff"` + MaxSequencerDrift uint64 `json:"max_sequencer_drift"` // Number of epochs (L1 blocks) per sequencing window SeqWindowSize uint64 `json:"seq_window_size"` // Required to verify L1 signatures diff --git a/opnode/rollup/types_test.go b/opnode/rollup/types_test.go index 628cba8285cb..23fb24b1c5df 100644 --- a/opnode/rollup/types_test.go +++ b/opnode/rollup/types_test.go @@ -27,13 +27,13 @@ func randConfig() *Config { L2: eth.BlockID{Hash: randHash(), Number: 1337}, L2Time: uint64(time.Now().Unix()), }, - BlockTime: 2, - MaxSequencerTimeDiff: 100, - SeqWindowSize: 2, - L1ChainID: big.NewInt(900), - FeeRecipientAddress: randAddr(), - BatchInboxAddress: randAddr(), - BatchSenderAddress: randAddr(), + BlockTime: 2, + MaxSequencerDrift: 100, + SeqWindowSize: 2, + L1ChainID: big.NewInt(900), + FeeRecipientAddress: randAddr(), + BatchInboxAddress: randAddr(), + BatchSenderAddress: randAddr(), } } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 470c39cdb6f9..5077eb489dd0 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -170,10 +170,10 @@ func TestSystemE2E(t *testing.T) { L2: l2GenesisID, L2Time: l2GenesisTime, }, - BlockTime: 1, - MaxSequencerTimeDiff: 10, - SeqWindowSize: 2, - L1ChainID: big.NewInt(900), + BlockTime: 1, + MaxSequencerDrift: 10, + SeqWindowSize: 2, + L1ChainID: big.NewInt(900), // TODO pick defaults FeeRecipientAddress: common.Address{0xff, 0x01}, BatchInboxAddress: common.Address{0xff, 0x02}, @@ -199,10 +199,10 @@ func TestSystemE2E(t *testing.T) { L2: l2GenesisID, L2Time: l2GenesisTime, }, - BlockTime: 1, - MaxSequencerTimeDiff: 10, - SeqWindowSize: 2, - L1ChainID: big.NewInt(900), + BlockTime: 1, + MaxSequencerDrift: 10, + SeqWindowSize: 2, + L1ChainID: big.NewInt(900), // TODO pick defaults FeeRecipientAddress: common.Address{0xff, 0x01}, BatchInboxAddress: common.Address{0xff, 0x02}, From de03e80d463ea1b1a2faf909cde4a0dc7a12ff2f Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 5 Apr 2022 20:55:36 +0200 Subject: [PATCH 401/585] opnode: fix sequencer L1 origin advancing, and fix e2e genesis time --- opnode/rollup/driver/state.go | 56 ++++++++++++++++++++++++++--------- opnode/rollup/driver/step.go | 4 +-- opnode/test/setup.go | 4 +-- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 94124f93015f..be508f3008d7 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -6,6 +6,8 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" @@ -173,19 +175,33 @@ func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { } // Somehow reorg'd. Will let the state loop take care of it. if curr.Hash != s.l2Head.L1Origin.Hash { - return eth.L1BlockRef{}, errors.New("Unknown L1Origin") + return eth.L1BlockRef{}, errors.New("unknown L1Origin") + } + + nextOrigin, err := s.l1.L1BlockRefByNumber(ctx, curr.Number+1) + if errors.Is(err, ethereum.NotFound) { + // no new L1 origin found, keep the current one + s.log.Info("No new L1 origin, staying with current one", "l2Head", s.l2Head, "l1Origin", curr) + return nextOrigin, nil + } + + nextL2Time := s.l2Head.Time + s.Config.BlockTime + + // If we can, start building on the next L1 origin + if nextL2Time >= nextOrigin.Time { // TODO: this is where we can add confirmation distance, instead of eagerly building on the very latest L1 block + s.log.Info("Advancing L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) + return nextOrigin, nil } - // TODO: There is an interaction with not using the L1 Genesis as an L1 Origin and - // the fact that the L2 Genesis time needs to be set around the L1 Genesis such - // that this check will return true. - if s.l2Head.Time+s.Config.BlockTime >= curr.Time { - // TODO: Need to walk more? - ref, err := s.l1.L1BlockRefByNumber(ctx, curr.Number+1) - s.log.Debug("Advancing L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", ref, "err", err) - return ref, err + // If there is no more slack left (including the sequencer drift), then we will have to start building on the next L1 origin + maxL2Time := curr.Time + s.Config.MaxSequencerDrift + if nextL2Time > maxL2Time { + s.log.Warn("Forced to advance to new L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) + return nextOrigin, nil } - s.log.Debug("Next L1 Origin is the same as the previous", "l2Head", s.l2Head, "l1Origin", curr) + + // If we have a next + s.log.Info("Next L1 Origin is the same as the previous", "l2Head", s.l2Head, "l1Origin", curr) return curr, nil } @@ -196,13 +212,25 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { s.log.Error("Error finding next L1 Origin", "err", err) return eth.L1BlockRef{}, err } - if nextOrigin.Time <= s.Config.BlockTime+s.l2Head.Time { - s.log.Trace("Skipping block production because the next block time is behind the next L1 Origin", "l2Head", s.l2Head, "l1Origin", nextOrigin) + nextL2Time := s.l2Head.Time + s.Config.BlockTime + // If we are behind the next L1 origin, then we should be deriving empty blocks (regular verifier work) until the L2 time catches up with L1 again. + if nextL2Time < nextOrigin.Time { + s.log.Warn("Skipping block production because the next block time is behind the next L1 Origin", + "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) + return eth.L1BlockRef{}, nil + } + + // TODO: we can give ourselves less slack here, and prefer to adopt the next L1 block more eagerly, + // to ensure we have more time to submit the next block we produce, at the cost of sequencing less eagerly. + maxL2Time := nextOrigin.Time + s.Config.MaxSequencerDrift + if nextL2Time > maxL2Time { + s.log.Warn("Skipping block production because we have no slack left to sequence more blocks on the L1 origin", + "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) return eth.L1BlockRef{}, nil } // Don't produce blocks until past the L1 genesis if nextOrigin.Number <= s.Config.Genesis.L1.Number { - s.log.Trace("Skipping block production because the next L1 Origin is behind the L1 genesis") + s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis") return eth.L1BlockRef{}, nil } // Actually create the new block @@ -213,7 +241,7 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { } // State update s.l2Head = newUnsafeL2Head - s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) + s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin, "txs", len(batch.Transactions), "time", s.l2Head.Time) //Submit batch go func() { _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 458e27d52d70..0ede38ef5007 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -52,8 +52,8 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, } timestamp := l2Info.Time() + d.Config.BlockTime - if timestamp >= l1Info.Time() { - return l2Head, nil, errors.New("L2 Timestamp is too large") + if timestamp > l1Info.Time()+d.Config.MaxSequencerDrift { + return l2Head, nil, errors.New("no slack left, L2 Timestamp is too large") } l1InfoTx, err := derive.L1InfoDepositBytes(l2Head.Number+1, l1Info) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index f4975da4913e..b2efdf2760ea 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -151,8 +151,8 @@ func initializeGenesis(cfg *systemConfig) { Difficulty: common.Big1, GasLimit: 5000000, Nonce: 4660, - // Set the L2 timestamps to be before the timestamp of the rollup genesis's L1 Block Timestamp. This is to match the current implementation of timestamps. - Timestamp: genesisTimestamp - 1, + // must be equal (or higher, while within bounds) as the L1 anchor point of the rollup + Timestamp: genesisTimestamp, BaseFee: big.NewInt(7), } From 784b390730cac98b8550dcbc6373272b52e670d1 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 13:42:07 -0400 Subject: [PATCH 402/585] contracts: Add burn function to the Withdrawer contract --- .../contracts/contracts/L2/Withdrawer.sol | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 024d1873db79..e0bcd317980d 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -36,4 +36,29 @@ contract Withdrawer { emit WithdrawalInitiated(nonce, msg.sender, _target, msg.value, _gasLimit, _data); } + + /** + * @notice Removes all ETH held in this contract from the state, by deploying a contract which + * immediately self destructs. + * For simplicity, this call is not incentivized as it costs very little to run. + * Inspired by https://etherscan.io/address/0xb69fba56b2e67e7dda61c8aa057886a8d1468575#code + */ + function burn() external { + assembly { + // Put this code into memory at the scratch space (first word). + // 30 - address(this) + // ff - selfdestruct + mstore(0, 0x30ff) + + // Transfer all funds to a new contract that will selfdestruct + // and destroy all the ether it holds in the process. + pop( + create( + balance(address()), // Fund the new contract with the balance of this one. + 30, // offset + 2 // size + ) + ) + } + } } From 2b735f838049b026ff9190e847c48ec068626ebc Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 13:21:50 -0400 Subject: [PATCH 403/585] contracts: Add natspec comments --- .../contracts/contracts/L1/DepositFeed.sol | 10 +++-- .../contracts/contracts/L1/L2OutputOracle.sol | 38 ++++++++++--------- .../contracts/L1/Lib_WithdrawalVerifier.sol | 22 ++++++++++- .../contracts/contracts/L1/OptimismPortal.sol | 32 +++++++++++++--- .../contracts/contracts/L2/Withdrawer.sol | 18 ++++++++- specs/withdrawals.md | 2 +- 6 files changed, 91 insertions(+), 31 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index c8f33ed9ea3b..d799d53310b9 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -3,10 +3,11 @@ pragma solidity 0.8.10; /** * @title DepositFeed + * @notice Implements the logic for depositing from L1 to L2. */ contract DepositFeed { /** - * Deposits which create a new contract must set the recipient to address(0). + * @notice Error emitted on deposits which create a new contract with a non-zero target. */ error NonZeroCreationTarget(); @@ -14,7 +15,8 @@ contract DepositFeed { uint160 private constant OFFSET = uint160(0x1111000000000000000000000000000000001111); /** - * Event with the parameters required to derive transactions on L2. + * @notice Emitted when a Transaction is deposited from L1 to L2. The parameters of this + * event are read by the rollup node and used to derive deposit transactions on L2. */ event TransactionDeposited( address indexed from, @@ -27,8 +29,8 @@ contract DepositFeed { ); /** - * Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving - * deposit transactions. + * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in + * deriving deposit transactions. * @param _to The L2 destination address. * @param _value The ETH value to send in the deposit transaction. * @param _gasLimit The L2 gasLimit. diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index a9b8e6133f56..d47d6b2cad10 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -1,37 +1,39 @@ //SPDX-License-Identifier: MIT pragma solidity >=0.8.10; +/* Library Imports */ import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; /** * @title L2OutputOracle + * @notice */ // The payable keyword is used on appendL2Output to save gas on the msg.value check. // slither-disable-next-line locked-ether contract L2OutputOracle is Ownable { - // The interval in seconds at which checkpoints must be submitted. + /// @notice The interval in seconds at which checkpoints must be submitted. uint256 public immutable submissionInterval; - // The time between blocks on L2. + /// @notice The time between blocks on L2. uint256 public immutable l2BlockTime; - // The number of blocks in the chain before the first block in this contract. + /// @notice The number of blocks in the chain before the first block in this contract. uint256 public immutable historicalTotalBlocks; - // The timestamp of the first L2 block recorded in this contract. + /// @notice The timestamp of the first L2 block recorded in this contract. uint256 public immutable startingBlockTimestamp; - // The timestamp of the most recent L2 block recorded in this contract. + /// @notice The timestamp of the most recent L2 block recorded in this contract. uint256 public latestBlockTimestamp; - // A mapping from L2 timestamps to the output root for the block with that timestamp + /// @notice A mapping from L2 timestamps to the output root for the block with that timestamp. mapping(uint256 => bytes32) internal l2Outputs; - // Emitted when an output is appended + /// @notice Emitted when an output is appended. event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); /** - * Initialize the L2OutputOracle contract. + * @notice Initialize the L2OutputOracle contract. * @param _submissionInterval The desired interval in seconds at which * checkpoints must be submitted. * @param _l2BlockTime The desired L2 inter-block time in seconds. @@ -57,9 +59,9 @@ contract L2OutputOracle is Ownable { } /** - * Accepts an L2 output checkpoint and the timestamp of the corresponding L2 - * block. The timestamp must be equal to the current value returned by - * `nextTimestamp()` in order to be accepted. + * @notice Accepts an L2 outputRoot and the timestamp of the corresponding L2 block. The + * timestamp must be equal to the current value returned by `nextTimestamp()` in order to be + * accepted. * This function may only be called by the Sequencer. * @param _l2Output The L2 output of the checkpoint block. * @param _l2timestamp The L2 block timestamp that resulted in _l2Output. @@ -98,15 +100,15 @@ contract L2OutputOracle is Ownable { } /** - * Computes the timestamp of the next L2 block that needs to be - * checkpointed. + * @notice Computes the timestamp of the next L2 block that needs to be checkpointed. */ function nextTimestamp() public view returns (uint256) { return latestBlockTimestamp + submissionInterval; } /** - * Returns the L2 output root given a target L2 block timestamp. Returns 0 if none is found. + * @notice Returns the L2 output root given a target L2 block timestamp. Returns 0 if none is + * found. * @param _l2Timestamp The L2 block timestamp of the target block. */ function getL2Output(uint256 _l2Timestamp) external view returns (bytes32) { @@ -114,7 +116,7 @@ contract L2OutputOracle is Ownable { } /** - * Computes the L2 block number given a target L2 block timestamp. + * @notice Computes the L2 block number given a target L2 block timestamp. * @param _l2timestamp The L2 block timestamp of the target block. */ function computeL2BlockNumber(uint256 _l2timestamp) external view returns (uint256) { @@ -122,8 +124,8 @@ contract L2OutputOracle is Ownable { _l2timestamp >= startingBlockTimestamp, "Timestamp prior to startingBlockTimestamp" ); - // If _l2timestamp == startingBlockTimestamp, then the L2BlockNumber should be - // historicalTotalBlocks + 1 - return historicalTotalBlocks + 1 + (_l2timestamp - startingBlockTimestamp) / l2BlockTime; + // For the first block recorded (ie. _l2timestamp = startingBlockTimestamp), the + // L2BlockNumber should be historicalTotalBlocks + 1. + return historicalTotalBlocks + 1 + ((_l2timestamp - startingBlockTimestamp) / l2BlockTime); } } diff --git a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol index 2db34801bdc0..5c1ab0bbdff8 100644 --- a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol @@ -1,15 +1,20 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +/* Interactions Imports */ import { L2OutputOracle } from "./L2OutputOracle.sol"; + +/* Library Imports */ import { Lib_SecureMerkleTrie } from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; /** * @title WithdrawalVerifier + * @notice A library with helper functions for verifying a withdrawal on L1. */ library WithdrawalVerifier { + /// @notice A struct containing the elements hashed together to generate the output root. struct OutputRootProof { uint256 timestamp; bytes32 version; @@ -18,6 +23,13 @@ library WithdrawalVerifier { bytes32 latestBlockhash; } + /** + * @notice Checks that the elements provided in the proof hash together to generate the provided + * output root. + * @param _outputRoot A hash retrieved from the L2OutputOracle contract. + * @param _outputRootProof The elements which were hashed together to generate the output root. + * @return Whether or not the output root matches the hashed output of the proof. + */ function _verifyWithdrawerStorageRoot( bytes32 _outputRoot, OutputRootProof calldata _outputRootProof @@ -34,6 +46,14 @@ library WithdrawalVerifier { ); } + /** + * @notice Verifies a proof that a given withdrawal hash is present in the Withdrawer contract's + * withdrawals mapping. + * @param _withdrawalHash Keccak256 hash of the withdrawal transaction data. + * @param _withdrawerStorageRoot Storage root of the withdrawer predeploy contract. + * @param _withdrawalProof Merkle trie inclusion proof for the desired node. + * @return Whether or not the inclusion proof was successful. + */ function _verifyWithdrawalInclusion( bytes32 _withdrawalHash, bytes32 _withdrawerStorageRoot, @@ -42,7 +62,7 @@ library WithdrawalVerifier { bytes32 storageKey = keccak256( abi.encode( _withdrawalHash, - uint256(1) // The withdrawals mapping is at the second slot in the layout + uint256(1) // The withdrawals mapping is at the second slot in the layout. ) ); diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index ba3cf7ca72d2..c158dc99fdd8 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -1,20 +1,42 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +/* Inherited Imports */ import { DepositFeed } from "./DepositFeed.sol"; -import { WithdrawalVerifier } from "./Lib_WithdrawalVerifier.sol"; +/* Interactions Imports */ import { L2OutputOracle } from "./L2OutputOracle.sol"; +/* Library Imports */ +import { WithdrawalVerifier } from "./Lib_WithdrawalVerifier.sol"; + +/** + * @title OptimismPortal + * @notice The OptimismPortal is a contract on L1 used to deposit and withdraw between L2 and L1. + */ contract OptimismPortal is DepositFeed { + /// @notice Emitted when a withdrawal is finalized event WithdrawalFinalized(bytes32 indexed); - // Value used to reset the l2Sender. This is more gas efficient that setting it to zero. + /// @notice Value used to reset the l2Sender, this is more efficient than setting it to zero. address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; + /// @notice Minimum time that must elapse before a withdrawal can be finalized. uint256 public immutable FINALIZATION_WINDOW; + + /// @notice Address of the L2OutputOracle. L2OutputOracle public immutable L2_ORACLE; + /** + * @notice Public variable which can be used to read the address of the L2 account which + * initated the withdrawal. Can also be used to determine whether or not execution is occuring + * downstream of a call to finalizeWithdrawalTransaction(). + */ address public l2Sender = DEFAULT_L2_SENDER; + + /** + * @notice A list of withdrawal hashes which have been successfully finalized. + * Used for replay protection. + */ mapping(bytes32 => bool) public finalizedWithdrawals; constructor(L2OutputOracle _l2Oracle, uint256 _finalizationWindow) { @@ -23,9 +45,9 @@ contract OptimismPortal is DepositFeed { } /** - * Accepts value so that users can send ETH directly to this contract and + * @notice Accepts value so that users can send ETH directly to this contract and * have the funds be deposited to their address on L2. - * Note: this is intended as a convenience function for EOAs. Contracts should call the + * @dev This is intended as a convenience function for EOAs. Contracts should call the * depositTransaction() function directly. */ receive() external payable { @@ -33,7 +55,7 @@ contract OptimismPortal is DepositFeed { } /** - * Finalizes a withdrawal transaction. + * @notice Finalizes a withdrawal transaction. * @param _nonce Nonce for the provided message. * @param _sender Message sender address on L2. * @param _target Target address on L1. diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index e0bcd317980d..1702892dbd2a 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -3,13 +3,27 @@ pragma solidity 0.8.10; /** * @title Withdrawer + * @notice The Withdrawer contract facilitates sending both ETH value and data from L2 to L1. + * It is predeployed in the L2 state at address 0x4200000000000000000000000000000000000015. */ contract Withdrawer { + /// @notice A unique value hashed with each withdrawal. uint256 public nonce; + + /// @notice A mapping listing withdrawals which have been initiated herein. mapping(bytes32 => bool) public withdrawals; + /** + * @notice Emitted any time a withdrawal is initiated. + * @param nonce Unique value corresponding to each withdrawal. + * @param sender The L2 account address which initiated the withdrawal. + * @param target The L1 account address the call will be send to. + * @param value The ETH value submitted for withdrawal, to be forwarded to the target. + * @param gasLimit The minimum amount of gas that must be provided when withdrawing on L1. + * @param data The data to be forwarded to the target on L1. + */ event WithdrawalInitiated( - uint256 indexed messageNonce, + uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, @@ -18,7 +32,7 @@ contract Withdrawer { ); /** - * Initiates a withdrawal to execute on L1. + * @notice Initiates a withdrawal to execute on L1. * @param _target Address to call on L1 execution. * @param _gasLimit GasLimit to provide on L1. * @param _data Data to forward to L1 target. diff --git a/specs/withdrawals.md b/specs/withdrawals.md index 2b5525382de2..1374447fa757 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -102,7 +102,7 @@ It contains a mapping which records withdrawals. interface Withdrawer { event WithdrawalMessage( - uint256 indexed messageNonce, // this is a global nonce value for all withdrawal messages + uint256 indexed nonce, // this is a global nonce value for all withdrawal messages address indexed sender, address indexed target, uint256 value, From 2ec1f74243deb6761e9b8d48623f5b17710beee1 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 14:53:59 -0400 Subject: [PATCH 404/585] contracts: Remove timestamp from OutputRootProof --- .../contracts/contracts/L1/Lib_WithdrawalVerifier.sol | 1 - packages/contracts/contracts/L1/OptimismPortal.sol | 8 ++++++-- packages/contracts/contracts/test/OptimismPortal.t.sol | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol index 5c1ab0bbdff8..dbd26667b156 100644 --- a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol @@ -16,7 +16,6 @@ import { library WithdrawalVerifier { /// @notice A struct containing the elements hashed together to generate the output root. struct OutputRootProof { - uint256 timestamp; bytes32 version; bytes32 stateRoot; bytes32 withdrawerStorageRoot; diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index c158dc99fdd8..f99d47544734 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -71,15 +71,19 @@ contract OptimismPortal is DepositFeed { uint256 _value, uint256 _gasLimit, bytes calldata _data, + uint256 _timestamp, WithdrawalVerifier.OutputRootProof calldata _outputRootProof, bytes calldata _withdrawalProof ) external { // Check that the timestamp is 7 days old. - require(_outputRootProof.timestamp <= block.timestamp - FINALIZATION_WINDOW, "Too soon"); + require( + _timestamp <= block.timestamp - FINALIZATION_WINDOW, + "Finalization window has not yet passed." + ); // Get the output root and verify that the withdrawer contract's storage root is contained // in it. - bytes32 outputRoot = L2_ORACLE.getL2Output(_outputRootProof.timestamp); + bytes32 outputRoot = L2_ORACLE.getL2Output(_timestamp); require( WithdrawalVerifier._verifyWithdrawerStorageRoot(outputRoot, _outputRootProof) == true, "Calculated output root does not match expected value" diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index 368f48f1d62d..30a497ef92d8 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -113,7 +113,6 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { // cache the appendedTimestamp appendedTimestamp = nextTimestamp; outputRootProof = WithdrawalVerifier.OutputRootProof({ - timestamp: appendedTimestamp, version: version, stateRoot: stateRoot, withdrawerStorageRoot: withdrawerStorageRoot, @@ -131,6 +130,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { wdValue, wdGasLimit, wdData, + appendedTimestamp, outputRootProof, withdrawalProof ); @@ -138,7 +138,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { function test_cannotVerifyRecentWithdrawal() external { // This call should fail because the output root we're using was appended 1 second ago. - vm.expectRevert("Too soon"); + vm.expectRevert("Finalization window has not yet passed."); op.finalizeWithdrawalTransaction( wdNonce, wdSender, @@ -146,6 +146,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { wdValue, wdGasLimit, wdData, + appendedTimestamp, outputRootProof, hex"ffff" ); @@ -164,6 +165,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { wdValue, wdGasLimit, wdData, + appendedTimestamp, invalidOutpuRootProof, hex"ffff" ); From 1f6e3834a9772a1b6a7e11e5610fbb444c33c883 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 15:09:08 -0400 Subject: [PATCH 405/585] contracts: undoL1ToL2Alias on withdrawals from a contract Also uses AddressAliasHelper lib for aliasing instead of reimplementing it. --- packages/contracts/contracts/L1/DepositFeed.sol | 12 ++++++------ .../contracts/contracts/L1/OptimismPortal.sol | 3 ++- packages/contracts/contracts/L2/Withdrawer.sol | 14 +++++++++++++- .../contracts/contracts/test/DepositFeed.t.sol | 17 ++++++++--------- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index d799d53310b9..d26ad89c96f0 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -1,6 +1,11 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +/* Library Imports */ +import { + AddressAliasHelper +} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; + /** * @title DepositFeed * @notice Implements the logic for depositing from L1 to L2. @@ -11,9 +16,6 @@ contract DepositFeed { */ error NonZeroCreationTarget(); - // Constant for address aliasing - uint160 private constant OFFSET = uint160(0x1111000000000000000000000000000000001111); - /** * @notice Emitted when a Transaction is deposited from L1 to L2. The parameters of this * event are read by the rollup node and used to derive deposit transactions on L2. @@ -51,9 +53,7 @@ contract DepositFeed { address from = msg.sender; // Transform the from-address to its alias if the caller is a contract. if (msg.sender != tx.origin) { - unchecked { - from = address(uint160(msg.sender) + OFFSET); - } + from = AddressAliasHelper.applyL1ToL2Alias(msg.sender); } emit TransactionDeposited(from, _to, msg.value, _value, _gasLimit, _isCreation, _data); diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index f99d47544734..940002b0068e 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.10; /* Inherited Imports */ import { DepositFeed } from "./DepositFeed.sol"; + /* Interactions Imports */ import { L2OutputOracle } from "./L2OutputOracle.sol"; @@ -106,8 +107,8 @@ contract OptimismPortal is DepositFeed { // Check that this withdrawal has not already been finalized. require(finalizedWithdrawals[withdrawalHash] == false, "Withdrawal already finalized"); - // Make the call. l2Sender = _sender; + // Make the call. _target.call{ value: _value, gas: _gasLimit }(_data); l2Sender = DEFAULT_L2_SENDER; diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 1702892dbd2a..3ddbdf0ed869 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -1,6 +1,12 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +/* Library Imports */ +import { + AddressAliasHelper +} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; + + /** * @title Withdrawer * @notice The Withdrawer contract facilitates sending both ETH value and data from L2 to L1. @@ -42,6 +48,12 @@ contract Withdrawer { uint256 _gasLimit, bytes calldata _data ) external payable { + + address from = msg.sender; + // Transform the from-address to its L1 alias if the caller is a contract. + if (msg.sender != tx.origin) { + from = AddressAliasHelper.undoL1ToL2Alias(msg.sender); + } bytes32 withdrawalHash = keccak256( abi.encode(nonce, msg.sender, _target, msg.value, _gasLimit, _data) ); @@ -69,7 +81,7 @@ contract Withdrawer { pop( create( balance(address()), // Fund the new contract with the balance of this one. - 30, // offset + 0, // offset 2 // size ) ) diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol index 14f1ad3622b9..5b699cbeed95 100644 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -5,6 +5,10 @@ import { DSTest } from "../../lib/ds-test/src/test.sol"; import { Vm } from "../../lib/forge-std/src/Vm.sol"; import { DepositFeed } from "../L1/DepositFeed.sol"; +import { + AddressAliasHelper +} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; + contract DepositFeedTest is DSTest { Vm vm = Vm(HEVM_ADDRESS); address immutable ZERO_ADDRESS = address(0); @@ -30,11 +34,6 @@ contract DepositFeedTest is DSTest { df = new DepositFeed(); } - function addressAlias() internal view returns (address) { - return - address(uint160(address(this)) + uint160(0x1111000000000000000000000000000000001111)); - } - // Test: depositTransaction fails when contract creation has a non-zero destination address function test_depositTransaction_ContractCreationReverts() external { vm.expectRevert(abi.encodeWithSignature("NonZeroCreationTarget()")); @@ -69,7 +68,7 @@ contract DepositFeedTest is DSTest { function test_depositTransaction_NoValueContract() external { vm.expectEmit(true, true, false, true); emit TransactionDeposited( - addressAlias(), + AddressAliasHelper.applyL1ToL2Alias(address(this)), NON_ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, @@ -110,7 +109,7 @@ contract DepositFeedTest is DSTest { function test_depositTransaction_createWithZeroValueForContract() external { vm.expectEmit(true, true, false, true); emit TransactionDeposited( - addressAlias(), + AddressAliasHelper.applyL1ToL2Alias(address(this)), ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, @@ -152,7 +151,7 @@ contract DepositFeedTest is DSTest { function test_depositTransaction_withEthValueFromContract() external { vm.expectEmit(true, true, false, true); emit TransactionDeposited( - addressAlias(), + AddressAliasHelper.applyL1ToL2Alias(address(this)), NON_ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, @@ -200,7 +199,7 @@ contract DepositFeedTest is DSTest { function test_depositTransaction_withEthValueAndContractContractCreation() external { vm.expectEmit(true, true, false, true); emit TransactionDeposited( - addressAlias(), + AddressAliasHelper.applyL1ToL2Alias(address(this)), ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, From 28e6d0c7815ff543a713da6a8f9fc27237d7796f Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 6 Apr 2022 00:11:42 +0200 Subject: [PATCH 406/585] specs/rollup-node: improve spec based on review suggestions from @norswap --- specs/rollup-node.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index f582e9453767..913c0ae34684 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -45,7 +45,7 @@ currently only concerned with the specification of the rollup driver. **Table of Contents** - [L2 Chain Derivation](#l2-chain-derivation) - - [From L1 Sequencing window to L2 Payload Attributes](#from-l1-sequencing-window-to-l2-payload-attributes) + - [From L1 Sequencing Window to L2 Payload Attributes](#from-l1-sequencing-window-to-l2-payload-attributes) - [Reading L1 inputs](#reading-l1-inputs) - [Encoding the L1 Attributes Deposited Transaction](#encoding-the-l1-attributes-deposited-transaction) - [Encoding User-Deposited Transactions](#encoding-user-deposited-transactions) @@ -78,15 +78,15 @@ Every L2 block carries transactions of two categories: ------------------------------------------------------------------------------------------------------------------------ -## From L1 Sequencing window to L2 Payload Attributes +## From L1 Sequencing Window to L2 Payload Attributes A [sequencing window][g-sequencing-window] is a fixed number consecutive L1 blocks that a derivation step takes as input. The window is identified by an `epoch`, equal to the block number of the first block in the window. -As the full derivation of the L2 chain by the driver progresses each derivation step shifts the window forward by a -single L1 block: the windows overlap. - -Each sequencing window is derived into a variable number of L2 blocks, following the below derivation steps. +The derivation of the L2 chain from the L1 chain happens in steps. +Each step adds a variable number of L2 blocks to the L2 chain, derived from the sequencing window for the given epoch. +For epoch `N`, the sequencing window comprises L1 blocks `[N, N + SEQUENCING_WINDOW_SIZE)`. +Note that the sequencing windows overlap. ### Reading L1 inputs @@ -117,7 +117,7 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi - `l1_timestamp` is the timestamp of the L1 block associated with the L2 block's epoch - `max_sequencer_drift` is the most a sequencer is allowed to get ahead of L1 - The batch is the first batch with `batch.timestamp` in this sequencing window, - i.e. one batch per L2 block number + i.e. one batch per L2 block number. - The batch only contains sequenced transactions, i.e. it must NOT contain any Deposit-type transactions. [random]: https://eips.ethereum.org/EIPS/eip-4399 @@ -146,17 +146,10 @@ Batch contents: The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts][g-receipts]. Refer to the [**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log -entries. +entries. The deposited and sequenced transactions are combined when the Payload Attributes are constructed. [deposit-contract-spec]: deposits.md#deposit-contract -Each of the derived `PayloadAttributes` starts with a L1 Attributes transaction. -Like other derived deposits, this does not have to be batch-submitted, and exposes the required L1 information for the -process of finding the sync starting point of the L2 chain, without requiring L2 state access. - -The [User-deposited] transactions are all put in the first of the derived `PayloadAttributes`, -inserted after the L1 Attributes transaction, before any [sequenced][g-sequencing] transactions. - ### Encoding the L1 Attributes Deposited Transaction The [L1 attributes deposited transaction][g-l1-attr-deposit] is a call that submits the L1 block attributes (listed @@ -190,23 +183,30 @@ A sequencing window is derived into a variable number of L2 blocks, defined by a `new_head_l2_timestamp = max(highest_valid_batch_timestamp, next_l1_timestamp - l2_block_time, min_l2_timestamp)` - `highest_valid_batch_timestamp = max(batch.timestamp for batch in filtered_batches)`, or `0` if no there are no `filtered_batches`. + `batch.timestamp` refers to the L2 block timestamp encoded in the batch. - `next_l1_timestamp` is the timestamp of the next L1 block. -The L2 chain is extended to `new_head_l2_timestamp`, has a fixed block time, and no more than one batch per block. -This means that every `l2_block_time` that has no batch is interpreted as one with an empty sequenced transaction-list, -thus construing a L2 block that only contains deposit transaction(s). +The L2 chain is extended to `new_head_l2_timestamp` with blocks at a fixed block time (`l2_block_time`). +This means that every `l2_block_time` that has no batch is interpreted as one with no sequenced transactions. + +Each of the derived `PayloadAttributes` starts with a L1 Attributes transaction. +Like other derived deposits, this does not have to be batch-submitted, and exposes the required L1 information for the +process of finding the sync starting point of the L2 chain, without requiring L2 state access. + +The [User-deposited] transactions are all put in the first of the derived `PayloadAttributes`, +inserted after the L1 Attributes transaction, before any [sequenced][g-sequencing] transactions. #### Building individual Payload Attributes [payload attributes]: #building-individual-payload-attributes -From timestamped transaction lists derived from the sequencing window, the rollup node constructs [payload +From the timestamped transaction lists derived from the sequencing window, the rollup node constructs [payload attributes][g-payload-attr] as an [expanded version][expanded-payload] of the [`PayloadAttributesV1`] object, which -includes additional `transactions` and `noTxPool` fields. +includes the additional `transactions` and `noTxPool` fields. Each of the timestamped transaction lists translates to a `PayloadAttributesV1` as follows: -- `timestamp` is set to the timestamp of the L2 block. +- `timestamp` is set to the timestamp of the transaction list. - `random` is set to the *random* `execution_payload.prev_randao` L1 block attribute - `suggestedFeeRecipient` is set to an address determined by the system - `transactions` is the array of the derived transactions: deposited transactions and sequenced transactions. From d4ed0c0fa86b197176b2a8ec13311063809a322f Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 6 Apr 2022 00:38:02 +0200 Subject: [PATCH 407/585] opnode/rollup: implement review suggestions from @trianglesphere --- opnode/rollup/derive/payload_attributes.go | 2 +- opnode/rollup/driver/driver.go | 2 +- opnode/rollup/driver/state.go | 27 +++++++++++----------- opnode/rollup/driver/state_test.go | 2 +- opnode/rollup/driver/step.go | 24 +++++++------------ 5 files changed, 25 insertions(+), 32 deletions(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index a43d3c6da940..5d442e5d9481 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -256,7 +256,7 @@ func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, nextL m := make(map[uint64]*BatchData) // The number of L2 blocks per sequencing window is variable, we do not immediately fill to maxL2Time: // - ensure at least 1 block - // - fill up to the next L1 block time stamp, if higher, to keep up with L1 time + // - fill up to the next L1 block timestamp, if higher, to keep up with L1 time // - fill up to the last valid batch, to keep up with L2 time newHeadL2Timestamp := minL2Time if nextL1Time > newHeadL2Timestamp+blockTime { diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 227d79264801..b9161fac3a25 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -55,7 +55,7 @@ type outputInterface interface { insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) // createNewBlock builds a new block based on the L2 Head, L1 Origin, and the current mempool. - createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) + createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) } func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index be508f3008d7..d73b867e5f8a 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -169,20 +169,16 @@ func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { } // Grab the block ref - curr, err := s.l1.L1BlockRefByHash(ctx, s.l2Head.L1Origin.Hash) + currentOrigin, err := s.l1.L1BlockRefByHash(ctx, s.l2Head.L1Origin.Hash) if err != nil { return eth.L1BlockRef{}, err } - // Somehow reorg'd. Will let the state loop take care of it. - if curr.Hash != s.l2Head.L1Origin.Hash { - return eth.L1BlockRef{}, errors.New("unknown L1Origin") - } - nextOrigin, err := s.l1.L1BlockRefByNumber(ctx, curr.Number+1) + nextOrigin, err := s.l1.L1BlockRefByNumber(ctx, currentOrigin.Number+1) if errors.Is(err, ethereum.NotFound) { // no new L1 origin found, keep the current one - s.log.Info("No new L1 origin, staying with current one", "l2Head", s.l2Head, "l1Origin", curr) - return nextOrigin, nil + s.log.Info("No new L1 origin, staying with current one", "l2Head", s.l2Head, "l1Origin", currentOrigin) + return currentOrigin, nil } nextL2Time := s.l2Head.Time + s.Config.BlockTime @@ -194,15 +190,15 @@ func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { } // If there is no more slack left (including the sequencer drift), then we will have to start building on the next L1 origin - maxL2Time := curr.Time + s.Config.MaxSequencerDrift + maxL2Time := currentOrigin.Time + s.Config.MaxSequencerDrift if nextL2Time > maxL2Time { s.log.Warn("Forced to advance to new L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) return nextOrigin, nil } // If we have a next - s.log.Info("Next L1 Origin is the same as the previous", "l2Head", s.l2Head, "l1Origin", curr) - return curr, nil + s.log.Info("Next L1 Origin is the same as the previous", "l2Head", s.l2Head, "l1Origin", currentOrigin) + return currentOrigin, nil } // createNewL2Block builds a L2 block on top of the L2 Head (unsafe) @@ -220,10 +216,15 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { return eth.L1BlockRef{}, nil } + // If the L1 origin changed this block, then we are in the first block of the epoch + isFirstEpochBlock := s.l2Head.L1Origin.Number != nextOrigin.Number + + // We create at least 1 block per epoch. After that we have to enforce the max timestamp. + // // TODO: we can give ourselves less slack here, and prefer to adopt the next L1 block more eagerly, // to ensure we have more time to submit the next block we produce, at the cost of sequencing less eagerly. maxL2Time := nextOrigin.Time + s.Config.MaxSequencerDrift - if nextL2Time > maxL2Time { + if !isFirstEpochBlock && nextL2Time > maxL2Time { s.log.Warn("Skipping block production because we have no slack left to sequence more blocks on the L1 origin", "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) return eth.L1BlockRef{}, nil @@ -234,7 +235,7 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { return eth.L1BlockRef{}, nil } // Actually create the new block - newUnsafeL2Head, batch, err := s.output.createNewBlock(context.Background(), s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, nextOrigin.ID()) + newUnsafeL2Head, batch, err := s.output.createNewBlock(context.Background(), s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, nextOrigin) if err != nil { s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", nextOrigin) return eth.L1BlockRef{}, err diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index ded4c5b98807..f8d8b1ba2314 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -44,7 +44,7 @@ func (fn outputHandlerFn) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef return fn(ctx, l2Head, l2SafeHead, l2Finalized, l1Input) } -func (fn outputHandlerFn) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { +func (fn outputHandlerFn) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) { panic("Unimplemented") } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 0ede38ef5007..4c5db0633760 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -25,23 +25,20 @@ type outputImpl struct { Config rollup.Config } -func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.BlockID) (eth.L2BlockRef, *derive.BatchData, error) { +func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) { d.log.Info("creating new block", "l2Head", l2Head) + + // If the L1 origin changed this block, then we are in the first block of the epoch + firstEpochBlock := l2Head.L1Origin.Number != l1Origin.Number + fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - l2Info, err := d.l2.BlockByHash(fetchCtx, l2Head.Hash) - if err != nil { - return l2Head, nil, fmt.Errorf("failed to fetch L2 block info of %s: %v", l2Head, err) - } - l2BLockRef, err := derive.BlockReferences(l2Info, &d.Config.Genesis) - if err != nil { - return l2Head, nil, fmt.Errorf("failed to derive L2BlockRef from l2Block: %w", err) - } var l1Info derive.L1Info var receipts types.Receipts + var err error // Include deposits if this is the first block of an epoch - if l2BLockRef.L1Origin.Number != l1Origin.Number { + if firstEpochBlock { l1Info, _, receipts, err = d.dl.Fetch(fetchCtx, l1Origin.Hash) } else { l1Info, err = d.dl.InfoByHash(fetchCtx, l1Origin.Hash) @@ -51,11 +48,6 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, return l2Head, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) } - timestamp := l2Info.Time() + d.Config.BlockTime - if timestamp > l1Info.Time()+d.Config.MaxSequencerDrift { - return l2Head, nil, errors.New("no slack left, L2 Timestamp is too large") - } - l1InfoTx, err := derive.L1InfoDepositBytes(l2Head.Number+1, l1Info) if err != nil { return l2Head, nil, err @@ -72,7 +64,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, depositStart := len(txns) attrs := &l2.PayloadAttributes{ - Timestamp: hexutil.Uint64(timestamp), + Timestamp: hexutil.Uint64(l2Head.Time + d.Config.BlockTime), Random: l2.Bytes32(l1Info.MixDigest()), SuggestedFeeRecipient: d.Config.FeeRecipientAddress, Transactions: txns, From d6465784cf1345e9804d984ad634c4bd27832601 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 6 Apr 2022 01:01:07 +0200 Subject: [PATCH 408/585] specs/rollup-node: document timestamp invariant between L2 and L1 origin --- specs/rollup-node.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 913c0ae34684..2ab1bb4c4282 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -120,6 +120,9 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi i.e. one batch per L2 block number. - The batch only contains sequenced transactions, i.e. it must NOT contain any Deposit-type transactions. +Note that after the above filtering `min_l2_timestamp >= l1_timestamp` always holds, +i.e. a L2 block timestamp is always equal or ahead of the timestamp of the corresponding L1 origin block. + [random]: https://eips.ethereum.org/EIPS/eip-4399 A bundle of batches is versioned by prefixing with a bundle version byte: `bundle = bundle_version ++ bundle_data`. From 2cb04a6946c6b7a05f38d61302ac3d8c6a1be8c8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 6 Apr 2022 01:47:36 +0200 Subject: [PATCH 409/585] opnode/rollup/driver: continue sequencing on current epoch if next L1 origin timestamp is not reached yet --- opnode/rollup/driver/state.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index d73b867e5f8a..15fb76c834de 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -3,6 +3,7 @@ package driver import ( "context" "errors" + "fmt" "sync/atomic" "time" @@ -192,6 +193,14 @@ func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { // If there is no more slack left (including the sequencer drift), then we will have to start building on the next L1 origin maxL2Time := currentOrigin.Time + s.Config.MaxSequencerDrift if nextL2Time > maxL2Time { + // If we are not matching the L1 origin (due to a large gap between L1 blocks), then we stay with the current origin. + // This matches the `next_l1_timestamp - l2_block_time` part of the `new_head_l2_timestamp`, the batches will still be valid. + if nextL2Time < nextOrigin.Time { + s.log.Warn("Ran out of slack with current epoch, but the next L1 block is still ahead in time, thus we continue the epoch", + "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) + return currentOrigin, nil + } + // The L1 chain continues, and eventually the sequencer will be forced onto the chain with deposits from L1 s.log.Warn("Forced to advance to new L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) return nextOrigin, nil } @@ -209,11 +218,12 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { return eth.L1BlockRef{}, err } nextL2Time := s.l2Head.Time + s.Config.BlockTime - // If we are behind the next L1 origin, then we should be deriving empty blocks (regular verifier work) until the L2 time catches up with L1 again. + // If we are behind the L1 origin that we should be using then we broke the invariant if nextL2Time < nextOrigin.Time { - s.log.Warn("Skipping block production because the next block time is behind the next L1 Origin", + s.log.Error("Cannot build L2 block for time before L1 origin", "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) - return eth.L1BlockRef{}, nil + return eth.L1BlockRef{}, fmt.Errorf("cannot build L2 block on top %s for time %d before L1 origin %s at time %d", + s.l2Head, nextL2Time, nextOrigin, nextOrigin.Time) } // If the L1 origin changed this block, then we are in the first block of the epoch From 8393ced722e5f15f65f964e6fecad9be2b45d43c Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 6 Apr 2022 02:48:18 +0200 Subject: [PATCH 410/585] opnode/rollup: fix maxL2Time excl bound, and return adjusted maxL2time in long L1 gap case --- opnode/rollup/driver/state.go | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 15fb76c834de..c228d5e7906e 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -162,24 +162,25 @@ func (s *state) handleNewL1Block(ctx context.Context, newL1Head eth.L1BlockRef) // findNextL1Origin determines what the next L1 Origin should be. // The L1 Origin is either the L2 Head's Origin, or the following L1 block // if the next L2 block's time is greater than or equal to the L2 Head's Origin. -func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { +// Also return the max timestamp (incl.) that we can build a L2 block at using the returned origin. +func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, uint64, error) { // If we are at the head block, don't do a lookup. // Don't do a timestamp check either as we are unable to get the next block even if we wanted to. if s.l2Head.L1Origin.Hash == s.l1Head.Hash { - return s.l1Head, nil + return s.l1Head, s.l1Head.Time + s.Config.MaxSequencerDrift, nil } // Grab the block ref currentOrigin, err := s.l1.L1BlockRefByHash(ctx, s.l2Head.L1Origin.Hash) if err != nil { - return eth.L1BlockRef{}, err + return eth.L1BlockRef{}, 0, err } nextOrigin, err := s.l1.L1BlockRefByNumber(ctx, currentOrigin.Number+1) if errors.Is(err, ethereum.NotFound) { // no new L1 origin found, keep the current one s.log.Info("No new L1 origin, staying with current one", "l2Head", s.l2Head, "l1Origin", currentOrigin) - return currentOrigin, nil + return currentOrigin, currentOrigin.Time + s.Config.MaxSequencerDrift, nil } nextL2Time := s.l2Head.Time + s.Config.BlockTime @@ -187,32 +188,32 @@ func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, error) { // If we can, start building on the next L1 origin if nextL2Time >= nextOrigin.Time { // TODO: this is where we can add confirmation distance, instead of eagerly building on the very latest L1 block s.log.Info("Advancing L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) - return nextOrigin, nil + return nextOrigin, nextOrigin.Time + s.Config.MaxSequencerDrift, nil } // If there is no more slack left (including the sequencer drift), then we will have to start building on the next L1 origin maxL2Time := currentOrigin.Time + s.Config.MaxSequencerDrift - if nextL2Time > maxL2Time { + if nextL2Time >= maxL2Time { // the maxL2Time is an excl. bound on the current epoch. // If we are not matching the L1 origin (due to a large gap between L1 blocks), then we stay with the current origin. // This matches the `next_l1_timestamp - l2_block_time` part of the `new_head_l2_timestamp`, the batches will still be valid. if nextL2Time < nextOrigin.Time { s.log.Warn("Ran out of slack with current epoch, but the next L1 block is still ahead in time, thus we continue the epoch", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) - return currentOrigin, nil + return currentOrigin, nextOrigin.Time, nil } // The L1 chain continues, and eventually the sequencer will be forced onto the chain with deposits from L1 s.log.Warn("Forced to advance to new L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) - return nextOrigin, nil + return nextOrigin, nextOrigin.Time + s.Config.MaxSequencerDrift, nil } // If we have a next s.log.Info("Next L1 Origin is the same as the previous", "l2Head", s.l2Head, "l1Origin", currentOrigin) - return currentOrigin, nil + return currentOrigin, currentOrigin.Time + s.Config.MaxSequencerDrift, nil } // createNewL2Block builds a L2 block on top of the L2 Head (unsafe) func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { - nextOrigin, err := s.findNextL1Origin(context.Background()) + nextOrigin, maxL2Time, err := s.findNextL1Origin(context.Background()) if err != nil { s.log.Error("Error finding next L1 Origin", "err", err) return eth.L1BlockRef{}, err @@ -230,11 +231,7 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { isFirstEpochBlock := s.l2Head.L1Origin.Number != nextOrigin.Number // We create at least 1 block per epoch. After that we have to enforce the max timestamp. - // - // TODO: we can give ourselves less slack here, and prefer to adopt the next L1 block more eagerly, - // to ensure we have more time to submit the next block we produce, at the cost of sequencing less eagerly. - maxL2Time := nextOrigin.Time + s.Config.MaxSequencerDrift - if !isFirstEpochBlock && nextL2Time > maxL2Time { + if !isFirstEpochBlock && nextL2Time >= maxL2Time { s.log.Warn("Skipping block production because we have no slack left to sequence more blocks on the L1 origin", "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) return eth.L1BlockRef{}, nil From 0b25240171537fd22186d5114842526e717b22d4 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 16:23:35 -0400 Subject: [PATCH 411/585] contracts: Add withdrawer tests fixup! contracts: Add burn function to the Withdrawer contract --- .../contracts/contracts/L2/Withdrawer.sol | 13 +- .../contracts/contracts/test/Withdrawer.t.sol | 124 ++++++++++++++++++ 2 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 packages/contracts/contracts/test/Withdrawer.t.sol diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 3ddbdf0ed869..b96112161907 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -6,7 +6,6 @@ import { AddressAliasHelper } from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; - /** * @title Withdrawer * @notice The Withdrawer contract facilitates sending both ETH value and data from L2 to L1. @@ -37,6 +36,9 @@ contract Withdrawer { bytes data ); + /// @notice Emitted when the balance of this contract is burned. + event WithdrawerBalanceBurnt(uint256 indexed amount); + /** * @notice Initiates a withdrawal to execute on L1. * @param _target Address to call on L1 execution. @@ -48,7 +50,6 @@ contract Withdrawer { uint256 _gasLimit, bytes calldata _data ) external payable { - address from = msg.sender; // Transform the from-address to its L1 alias if the caller is a contract. if (msg.sender != tx.origin) { @@ -58,9 +59,9 @@ contract Withdrawer { abi.encode(nonce, msg.sender, _target, msg.value, _gasLimit, _data) ); withdrawals[withdrawalHash] = true; - nonce++; - emit WithdrawalInitiated(nonce, msg.sender, _target, msg.value, _gasLimit, _data); + emit WithdrawalInitiated(nonce, from, _target, msg.value, _gasLimit, _data); + nonce++; } /** @@ -70,6 +71,7 @@ contract Withdrawer { * Inspired by https://etherscan.io/address/0xb69fba56b2e67e7dda61c8aa057886a8d1468575#code */ function burn() external { + uint256 balance = address(this).balance; assembly { // Put this code into memory at the scratch space (first word). // 30 - address(this) @@ -81,10 +83,11 @@ contract Withdrawer { pop( create( balance(address()), // Fund the new contract with the balance of this one. - 0, // offset + 30, // offset 2 // size ) ) } + emit WithdrawerBalanceBurnt(balance); } } diff --git a/packages/contracts/contracts/test/Withdrawer.t.sol b/packages/contracts/contracts/test/Withdrawer.t.sol new file mode 100644 index 000000000000..bd7ece45eb81 --- /dev/null +++ b/packages/contracts/contracts/test/Withdrawer.t.sol @@ -0,0 +1,124 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { Withdrawer } from "../L2/Withdrawer.sol"; + +import { + AddressAliasHelper +} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +import { + Lib_RLPWriter +} from "../../lib/optimism/packages/contracts/contracts/libraries/rlp/Lib_RLPWriter.sol"; +import { + Lib_Bytes32Utils +} from "../../lib/optimism/packages/contracts/contracts/libraries/utils/Lib_Bytes32Utils.sol"; + + +contract WithdrawerTestCommon is DSTest { + Vm vm = Vm(HEVM_ADDRESS); + address immutable ZERO_ADDRESS = address(0); + address immutable NON_ZERO_ADDRESS = address(1); + uint256 immutable NON_ZERO_VALUE = 100; + uint256 immutable ZERO_VALUE = 0; + uint256 immutable NON_ZERO_GASLIMIT = 50000; + bytes NON_ZERO_DATA = hex"1111"; + + event WithdrawalInitiated( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data + ); + + Withdrawer wd; + + function setUp() public virtual { + wd = new Withdrawer(); + } +} + +contract WithdrawerTestInitiateWithdrawal is WithdrawerTestCommon { + + // Test: initiateWithdrawal should emit the correct log when called by a contract + function test_initiateWithdrawal_fromContract() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated( + 0, + AddressAliasHelper.undoL1ToL2Alias(address(this)), + NON_ZERO_ADDRESS, + NON_ZERO_VALUE, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA + ); + + wd.initiateWithdrawal{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA + ); + } + + // Test: initiateWithdrawal should emit the correct log when called by an EOA + function test_initiateWithdrawal_fromEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated( + 0, + address(this), + NON_ZERO_ADDRESS, + NON_ZERO_VALUE, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA + ); + + wd.initiateWithdrawal{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA + ); + } +} + +contract WithdawerBurnTest is WithdrawerTestCommon { + + event WithdrawerBalanceBurnt(uint256 indexed amount); + + function setUp() public override { + // fund a new withdrawer + super.setUp(); + wd.initiateWithdrawal{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA + ); + } + + // Test: burn should destroy the ETH held in the contract + function test_burn() external { + // Sanity check that setUp worked as expected. + assertEq(address(wd).balance, NON_ZERO_VALUE); + vm.expectEmit(true, false, false, false); + emit WithdrawerBalanceBurnt(NON_ZERO_VALUE); + wd.burn(); + // Calculate the address of the contract that will selfdestruct at the end of this tx. + // Based on https://github.com/ethereum-optimism/contracts/blob/532b9a743cf34d66e812cbf1d9f28c452b52e1bd/contracts/optimistic-ethereum/libraries/utils/Lib_EthUtils.sol#L145 + bytes[] memory encoded = new bytes[](2); + encoded[0] = Lib_RLPWriter.writeAddress(address(wd)); // creator + encoded[1] = Lib_RLPWriter.writeUint(0); // nonce + bytes memory encodedList = Lib_RLPWriter.writeList(encoded); + address created = Lib_Bytes32Utils.toAddress(keccak256(encodedList)); + + // The Withdrawer should have no balance + assertEq(address(wd).balance, 0); + + // The created contract should have its balance + assertEq(created.balance, NON_ZERO_VALUE); + + } + +} From 1325e42e4828a068d39746a90e6f768ac2ae5ead Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 20:27:57 -0400 Subject: [PATCH 412/585] Rename Finalization Window to Finalization Period --- packages/contracts/contracts/L1/OptimismPortal.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index 940002b0068e..05d9a7ddefd8 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -22,7 +22,7 @@ contract OptimismPortal is DepositFeed { address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; /// @notice Minimum time that must elapse before a withdrawal can be finalized. - uint256 public immutable FINALIZATION_WINDOW; + uint256 public immutable FINALIZATION_PERIOD; /// @notice Address of the L2OutputOracle. L2OutputOracle public immutable L2_ORACLE; @@ -40,9 +40,9 @@ contract OptimismPortal is DepositFeed { */ mapping(bytes32 => bool) public finalizedWithdrawals; - constructor(L2OutputOracle _l2Oracle, uint256 _finalizationWindow) { + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) { L2_ORACLE = _l2Oracle; - FINALIZATION_WINDOW = _finalizationWindow; + FINALIZATION_PERIOD = _finalizationPeriod; } /** @@ -78,7 +78,7 @@ contract OptimismPortal is DepositFeed { ) external { // Check that the timestamp is 7 days old. require( - _timestamp <= block.timestamp - FINALIZATION_WINDOW, + _timestamp <= block.timestamp - FINALIZATION_PERIOD, "Finalization window has not yet passed." ); From 9cf5af8cfeda7fd45a5b9ceba2f4c9495b0343ee Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 20:31:05 -0400 Subject: [PATCH 413/585] contracts: Validate output root proof in portal Moves the comparison into the Portal contract, and changes the WithdrawalVerifier function from _verifyWithdrawerStorageRoot to _deriveOutputRoot. --- .../contracts/L1/Lib_WithdrawalVerifier.sol | 14 ++++++-------- packages/contracts/contracts/L1/OptimismPortal.sol | 7 ++++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol index dbd26667b156..13cc90be96a0 100644 --- a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol @@ -23,18 +23,16 @@ library WithdrawalVerifier { } /** - * @notice Checks that the elements provided in the proof hash together to generate the provided - * output root. - * @param _outputRoot A hash retrieved from the L2OutputOracle contract. + * @notice Derives the output root corresponding to the elements provided in the proof. * @param _outputRootProof The elements which were hashed together to generate the output root. * @return Whether or not the output root matches the hashed output of the proof. */ - function _verifyWithdrawerStorageRoot( - bytes32 _outputRoot, - OutputRootProof calldata _outputRootProof - ) internal pure returns (bool) { + function _deriveOutputRoot(OutputRootProof calldata _outputRootProof) + internal + pure + returns (bytes32) + { return - _outputRoot == keccak256( abi.encode( _outputRootProof.version, diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index 05d9a7ddefd8..fde91de25078 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -82,11 +82,12 @@ contract OptimismPortal is DepositFeed { "Finalization window has not yet passed." ); - // Get the output root and verify that the withdrawer contract's storage root is contained - // in it. + // Get the output root. bytes32 outputRoot = L2_ORACLE.getL2Output(_timestamp); + + // Verify that the output root can be generated with the elements in the proof. require( - WithdrawalVerifier._verifyWithdrawerStorageRoot(outputRoot, _outputRootProof) == true, + outputRoot == WithdrawalVerifier._deriveOutputRoot(_outputRootProof), "Calculated output root does not match expected value" ); From 548be0f61a9109e1fd951baebccd768fd69f1d0d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 21:10:51 -0400 Subject: [PATCH 414/585] contracts: Use solidity custom errors --- .../contracts/contracts/L1/OptimismPortal.sol | 39 ++++++++++++------- .../contracts/test/OptimismPortal.t.sol | 18 +++------ 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index fde91de25078..b0c4ef0c2959 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -15,6 +15,18 @@ import { WithdrawalVerifier } from "./Lib_WithdrawalVerifier.sol"; * @notice The OptimismPortal is a contract on L1 used to deposit and withdraw between L2 and L1. */ contract OptimismPortal is DepositFeed { + /// @notice Error emitted when attempting to finalize a withdrawal too early. + error NotYetFinal(); + + /// @notice Error emitted when the output root proof is invalid. + error InvalidOutputRootProof(); + + /// @notice Error emitted when the withdrawal inclusion proof is invalid. + error InvalidWithdrawalInclusionProof(); + + /// @notice Error emitted when a withdrawal has already been finalized. + error WithdrawalAlreadyFinalized(); + /// @notice Emitted when a withdrawal is finalized event WithdrawalFinalized(bytes32 indexed); @@ -77,36 +89,37 @@ contract OptimismPortal is DepositFeed { bytes calldata _withdrawalProof ) external { // Check that the timestamp is 7 days old. - require( - _timestamp <= block.timestamp - FINALIZATION_PERIOD, - "Finalization window has not yet passed." - ); + if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { + revert NotYetFinal(); + } // Get the output root. bytes32 outputRoot = L2_ORACLE.getL2Output(_timestamp); // Verify that the output root can be generated with the elements in the proof. - require( - outputRoot == WithdrawalVerifier._deriveOutputRoot(_outputRootProof), - "Calculated output root does not match expected value" - ); + if (outputRoot != WithdrawalVerifier._deriveOutputRoot(_outputRootProof)) { + revert InvalidOutputRootProof(); + } // Verify that the hash of the withdrawal transaction's arguments are included in the // storage hash of the withdrawer contract. bytes32 withdrawalHash = keccak256( abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) ); - require( + if ( WithdrawalVerifier._verifyWithdrawalInclusion( withdrawalHash, _outputRootProof.withdrawerStorageRoot, _withdrawalProof - ) == true, - "Withdrawal transaction not found in storage" - ); + ) == false + ) { + revert InvalidWithdrawalInclusionProof(); + } // Check that this withdrawal has not already been finalized. - require(finalizedWithdrawals[withdrawalHash] == false, "Withdrawal already finalized"); + if (finalizedWithdrawals[withdrawalHash] == true) { + revert WithdrawalAlreadyFinalized(); + } l2Sender = _sender; // Make the call. diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index 30a497ef92d8..564bedf0b3af 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -14,7 +14,6 @@ import { WithdrawalVerifier } from "../L1/Lib_WithdrawalVerifier.sol"; import { OptimismPortal } from "../L1/OptimismPortal.sol"; contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { - event TransactionDeposited( address indexed from, address indexed to, @@ -67,7 +66,8 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { // test script against Geth. bytes32 version = bytes32(hex"00"); bytes32 stateRoot = keccak256(abi.encode(1)); - bytes32 withdrawerStorageRoot = 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; // eth_getProof (storageHash) + bytes32 withdrawerStorageRoot = + 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; // eth_getProof (storageHash) bytes32 latestBlockhash = keccak256(abi.encode(2)); // This proof was generated by running @@ -138,7 +138,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { function test_cannotVerifyRecentWithdrawal() external { // This call should fail because the output root we're using was appended 1 second ago. - vm.expectRevert("Finalization window has not yet passed."); + vm.expectRevert(abi.encodeWithSignature("NotYetFinal()")); op.finalizeWithdrawalTransaction( wdNonce, wdSender, @@ -155,7 +155,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { function test_cannotVerifyInvalidProof() external { // This call should fail because the output proof is modified vm.warp(appendedTimestamp + 7 days); - vm.expectRevert("Calculated output root does not match expected value"); + vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; invalidOutpuRootProof.latestBlockhash = 0; op.finalizeWithdrawalTransaction( @@ -176,15 +176,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { vm.prank(address(this), address(this)); vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - address(this), - address(this), - 100, - 100, - 30_000, - false, - hex"" - ); + emit TransactionDeposited(address(this), address(this), 100, 100, 30_000, false, hex""); address(op).call{ value: 100 }(hex""); assertEq(address(op).balance, 100); From 1df52922c9ad11425cb2e26c65338410e47a4238 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 21:32:19 -0400 Subject: [PATCH 415/585] contracts: Use unchecked math when safe --- packages/contracts/contracts/L1/L2OutputOracle.sol | 5 ++++- packages/contracts/contracts/L1/OptimismPortal.sol | 6 ++++-- packages/contracts/contracts/L2/Withdrawer.sol | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index d47d6b2cad10..1db96d93f867 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -126,6 +126,9 @@ contract L2OutputOracle is Ownable { ); // For the first block recorded (ie. _l2timestamp = startingBlockTimestamp), the // L2BlockNumber should be historicalTotalBlocks + 1. - return historicalTotalBlocks + 1 + ((_l2timestamp - startingBlockTimestamp) / l2BlockTime); + unchecked { + return + historicalTotalBlocks + 1 + ((_l2timestamp - startingBlockTimestamp) / l2BlockTime); + } } } diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index b0c4ef0c2959..18154b3fd009 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -89,8 +89,10 @@ contract OptimismPortal is DepositFeed { bytes calldata _withdrawalProof ) external { // Check that the timestamp is 7 days old. - if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { - revert NotYetFinal(); + unchecked { + if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { + revert NotYetFinal(); + } } // Get the output root. diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index b96112161907..1f9b1194d6aa 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -61,7 +61,9 @@ contract Withdrawer { withdrawals[withdrawalHash] = true; emit WithdrawalInitiated(nonce, from, _target, msg.value, _gasLimit, _data); - nonce++; + unchecked { + nonce++; + } } /** From b31acafe5e365c26b6a9282f256c98d279c3474d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 21:49:49 -0400 Subject: [PATCH 416/585] contracts: Add section dividers to contract layout --- .../contracts/contracts/L1/DepositFeed.sol | 14 ++++++++++++ .../contracts/contracts/L1/L2OutputOracle.sol | 20 +++++++++++++++-- .../contracts/contracts/L1/OptimismPortal.sol | 20 +++++++++++++++++ .../contracts/contracts/L2/Withdrawer.sol | 22 ++++++++++++++----- 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index d26ad89c96f0..5be293bffea5 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -11,11 +11,21 @@ import { * @notice Implements the logic for depositing from L1 to L2. */ contract DepositFeed { + + /********** + * Errors * + **********/ + /** * @notice Error emitted on deposits which create a new contract with a non-zero target. */ error NonZeroCreationTarget(); + + /********** + * Events * + **********/ + /** * @notice Emitted when a Transaction is deposited from L1 to L2. The parameters of this * event are read by the rollup node and used to derive deposit transactions on L2. @@ -30,6 +40,10 @@ contract DepositFeed { bytes data ); + /********************** + * External Functions * + **********************/ + /** * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in * deriving deposit transactions. diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 1db96d93f867..bf827872c566 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -11,6 +11,17 @@ import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownab // The payable keyword is used on appendL2Output to save gas on the msg.value check. // slither-disable-next-line locked-ether contract L2OutputOracle is Ownable { + /********** + * Events * + **********/ + + /// @notice Emitted when an output is appended. + event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + + /********************** + * Contract Variables * + **********************/ + /// @notice The interval in seconds at which checkpoints must be submitted. uint256 public immutable submissionInterval; @@ -29,8 +40,9 @@ contract L2OutputOracle is Ownable { /// @notice A mapping from L2 timestamps to the output root for the block with that timestamp. mapping(uint256 => bytes32) internal l2Outputs; - /// @notice Emitted when an output is appended. - event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + /*************** + * Constructor * + ***************/ /** * @notice Initialize the L2OutputOracle contract. @@ -58,6 +70,10 @@ contract L2OutputOracle is Ownable { _transferOwnership(sequencer); } + /********************************* + * External and Public Functions * + *********************************/ + /** * @notice Accepts an L2 outputRoot and the timestamp of the corresponding L2 block. The * timestamp must be equal to the current value returned by `nextTimestamp()` in order to be diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index 18154b3fd009..e8ca2929e986 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -15,6 +15,10 @@ import { WithdrawalVerifier } from "./Lib_WithdrawalVerifier.sol"; * @notice The OptimismPortal is a contract on L1 used to deposit and withdraw between L2 and L1. */ contract OptimismPortal is DepositFeed { + /********** + * Errors * + **********/ + /// @notice Error emitted when attempting to finalize a withdrawal too early. error NotYetFinal(); @@ -27,12 +31,20 @@ contract OptimismPortal is DepositFeed { /// @notice Error emitted when a withdrawal has already been finalized. error WithdrawalAlreadyFinalized(); + /********** + * Events * + **********/ + /// @notice Emitted when a withdrawal is finalized event WithdrawalFinalized(bytes32 indexed); /// @notice Value used to reset the l2Sender, this is more efficient than setting it to zero. address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; + /********************** + * Contract Variables * + **********************/ + /// @notice Minimum time that must elapse before a withdrawal can be finalized. uint256 public immutable FINALIZATION_PERIOD; @@ -52,11 +64,19 @@ contract OptimismPortal is DepositFeed { */ mapping(bytes32 => bool) public finalizedWithdrawals; + /*************** + * Constructor * + ***************/ + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) { L2_ORACLE = _l2Oracle; FINALIZATION_PERIOD = _finalizationPeriod; } + /********************** + * External Functions * + **********************/ + /** * @notice Accepts value so that users can send ETH directly to this contract and * have the funds be deposited to their address on L2. diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 1f9b1194d6aa..94ad3f792153 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -12,11 +12,9 @@ import { * It is predeployed in the L2 state at address 0x4200000000000000000000000000000000000015. */ contract Withdrawer { - /// @notice A unique value hashed with each withdrawal. - uint256 public nonce; - - /// @notice A mapping listing withdrawals which have been initiated herein. - mapping(bytes32 => bool) public withdrawals; + /********** + * Events * + **********/ /** * @notice Emitted any time a withdrawal is initiated. @@ -39,6 +37,20 @@ contract Withdrawer { /// @notice Emitted when the balance of this contract is burned. event WithdrawerBalanceBurnt(uint256 indexed amount); + /********************** + * Contract Variables * + **********************/ + + /// @notice A unique value hashed with each withdrawal. + uint256 public nonce; + + /// @notice A mapping listing withdrawals which have been initiated herein. + mapping(bytes32 => bool) public withdrawals; + + /********************** + * External Functions * + **********************/ + /** * @notice Initiates a withdrawal to execute on L1. * @param _target Address to call on L1 execution. From 898d61cd08e2dd95ac78462074ea475d3e7bbaef Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 5 Apr 2022 23:39:23 -0400 Subject: [PATCH 417/585] specs: Update withdrawals spec to match impl --- .../contracts/contracts/L1/DepositFeed.sol | 2 - .../contracts/contracts/L1/OptimismPortal.sol | 1 + specs/glossary.md | 9 +- specs/withdrawals.md | 187 ++++++++---------- 4 files changed, 88 insertions(+), 111 deletions(-) diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/DepositFeed.sol index 5be293bffea5..3a67e00edfa5 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/DepositFeed.sol @@ -11,7 +11,6 @@ import { * @notice Implements the logic for depositing from L1 to L2. */ contract DepositFeed { - /********** * Errors * **********/ @@ -21,7 +20,6 @@ contract DepositFeed { */ error NonZeroCreationTarget(); - /********** * Events * **********/ diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index e8ca2929e986..5728b96d2ef1 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -94,6 +94,7 @@ contract OptimismPortal is DepositFeed { * @param _target Target address on L1. * @param _data Data to send to the target. * @param _gasLimit Gas to be forwarded to the target. + * @param _timestamp L2 timestamp of the outputRoot. * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. */ diff --git a/specs/glossary.md b/specs/glossary.md index d599d93a451c..fa9851991808 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -292,19 +292,20 @@ cf. [Deposits Specification](deposits.md) [withdrawals]: glossary.md#withdrawals -In general, a withdrawal is a transaction sent from L2 to L1 that may transfer of data and/or value. +In general, a withdrawal is a transaction sent from L2 to L1 that may transfer data and/or value. This term *withdrawal* is somewhat ambiguous as these "transactions" exist at multiple levels. In order to differentiate between the L1 and L2 components of a withdrawal we introduce the following terms: -- A *withdrawing* call or transaction occurs on L2 and initiates a withdrawal. -- A *withdrawn* call or transaction occurs on l1 as the result of an withdrawal being relayed on L1. +- *withdrawal initiating transaction* refers specifically to a transaction on L2 sent to the Withdrawals predeploy. +- *withdrawal finalizing transaction* refers specifically to an L1 transaction which finalizes and relays the + withdrawal. ## Relayer [relayer]: glossary.md#withdrawals -An EOA on L1 which finalizes a withdrawal by providing submitting the data necessary to verify its inclusion on L2. +An EOA on L1 which finalizes a withdrawal by submitting the data necessary to verify its inclusion on L2. ------------------------------------------------------------------------------------------------------------------------ diff --git a/specs/withdrawals.md b/specs/withdrawals.md index 1374447fa757..b52e1c40b6ca 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -33,70 +33,43 @@ finalization. **Table of Contents** -- [Withdrawal initialization on L2](#withdrawal-initialization-on-l2) -- [Withdrawal verification](#withdrawal-verification) - [Withdrawal Flow](#withdrawal-flow) -- [The L2 Withdrawals Contract](#the-l2-withdrawals-contract) + - [On L2](#on-l2) + - [On L1](#on-l1) +- [The L2 Withdrawer Contract](#the-l2-withdrawer-contract) +- [The Optimism Portal Contract](#the-optimism-portal-contract) +- [Withdrawal Verification and Finalization](#withdrawal-verification-and-finalization) - [Security Considerations](#security-considerations) - [Key Properties of Withdrawal Verification](#key-properties-of-withdrawal-verification) - [Handling Successfully Verified Messages That Fail When Relayed](#handling-successfully-verified-messages-that-fail-when-relayed) - [Summary of Definitions](#summary-of-definitions) - [Constants](#constants) - - [Data Structures and Type Aliases](#data-structures-and-type-aliases) -## Withdrawal initialization on L2 - -> Todo: spec out the predeploy contract - -## Withdrawal verification - -In order to verify a `WithdrawalMessage`, the following inputs must be provided: - -| Type | Name | -| --------------------------------- | ------------------ | -| `WithdrawalMessage` | `message` | -| `L2OutputTimestamp` | `timestamp` | -| `WithdrawalsRootInclusionProof` | `storageRootProof` | -| `WithdrawalMessageInclusionProof` | `messageProof` | - -These inputs must satisfy the following conditions: - -1. The `timestamp` is at least `FINALIZATION_WINDOW` seconds old. -1. `OutputOracle.l2Outputs(timestamp)` returns a non-zero value `l2Output`. -1. The `storageRootProof` is valid for the `l2Output` returned in step 2, according to the SSZ encoding described in the - [L2 output commitment construction](./proposals.md#l2-output-commitment-construction). -1. The `messageProof` is valid for the provided `message` and `messageProof` - ## Withdrawal Flow -**On L2:** +We first describe the end to end flow of initiating and finalizing a withdrawal: -1. An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdrawer` predeploy contract. - This is a very simple contract that stores a mapping from the hash of the `WithdrawalMessage` as defined above to a - boolean value. (`mapping (bytes32 => bool) withdrawalMessages`) -2. If ETH is being withdrawn, it can eventually be burned by deploying a contract which immediately `SELFDESTRUCT`s. - This has the benefit of using an existing EVM mechanism for removing the ETH from the world state, without having to - add a diff to L2 Geth. +### On L2 -**On L1:** +An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdrawer` predeploy contract. + This is a very simple contract that stores the a hash of the withdrawal data. -1. A [relayer][g-relayer] submits the required inputs to the `DepositFeed` contract. The relayer may or may not be the - same entity which initiated the withdrawal on L2. -2. The `DepositFeed` contract retrieves the output root from the `OutputOracle`'s `l2Outputs()` function, and performs - the remainder of the verification process internally. -3. If verification is successful, the message is forwarded to the target. - 1. If the message call is successful, the hash is stored in a `successfulMessages` mapping. - 2. Otherwise it is stored in a `repeatableMessages` mapping. -4. If verification fails, the call reverts. +### On L1 -## The L2 Withdrawals Contract +1. A [relayer][g-relayer] submits the required inputs (see below) to the `OptimismPortal` contract. The relayer need + not be the same entity which initiated the withdrawal on L2. +2. The `OptimismPortal` contract retrieves the output root from the `OutputOracle`'s `l2Outputs()` function, and + performs the remainder of the verification process internally. +3. If verification fails, the call reverts. Otherwise the call is forwarded, and the hash is recorded to prevent it from + from being replayed. -The L2 Withdrawals predeploy is a simple contract at `0x4200000000000000000000000000000000000015` which stores messages -to be withdrawn. +## The L2 Withdrawer Contract -It contains a mapping which records withdrawals. +A withdrawal is initiated by calling the Withdrawer contract's `initiateWithdrawal` function. +The Withdrawer is a simple predeploy contract at `0x4200000000000000000000000000000000000015` which stores messages +to be withdrawn. ```js interface Withdrawer { @@ -112,26 +85,77 @@ interface Withdrawer { function initiateWithdrawal( address target, - bytes message, - uint256 gasLimit + uint256 gasLimit, + bytes data, ) external payable; function burn(); } ``` +If called by a contract, the `initiateWithdrawal` function will alias the `sender` address in the reverse of the +manner described in the [deposits spec](./deposits.md#address-aliasing). + +## The Optimism Portal Contract + +The Optimism Portal serves as both the entry and exit point to the Optimism L2. It is a contract which inherits from +the [DepositFeed](./deposits.md#deposit-contract) contract, and in addition provides the following interface for +withdrawals: + +```js +interface OptimismPortal { + + event WithdrawalFinalized(bytes32 indexed); + + function finalizeWithdrawalTransaction( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes calldata _data, + uint256 _timestamp, + WithdrawalVerifier.OutputRootProof calldata _outputRootProof, + bytes calldata _withdrawalProof + ) +} +``` + +## Withdrawal Verification and Finalization + +The following inputs are required to verify and finalize a withdrawal: + +- Withdrawal transaction data: + - `nonce`: Nonce for the provided message. + - `sender`: Message sender address on L2. + - `target`: Target address on L1. + - `data`: Data to send to the target. + - `gasLimit`: Gas to be forwarded to the target. +- Proof and verification data: + - `timestamp`: The L2 timestamp corresponding with the output root. + - `outputRootProof`: The 4 values which are used to derive the output root. + - `withdrawalProof`: An inclusion proof for the given withdrawal in the withdrawer contract. + +These inputs must satisfy the following conditions: + +1. The `timestamp` is at least `FINALIZATION_PERIOD` seconds old. +1. `OutputOracle.l2Outputs(timestamp)` returns a non-zero value `l2Output`. +2. The `l2Output` value is equal to the hash of the components of the `outputRootProof` +1. The `withdrawalProof` is a valid inclusion proof demonstrating that a hash of the Withdrawal transaction data + is contained in the storage of the Withdrawer contract on L2. + ## Security Considerations ### Key Properties of Withdrawal Verification -1. It should not be possible 'double spend' a withdrawal, ie. to relay a `WithdrawalMessage` on L1 which does not +1. It should not be possible 'double spend' a withdrawal, ie. to relay a withdrawal on L1 which does not correspond to a message initiated on L2. For reference, see [this writeup][polygon-dbl-spend] of a vulnerability of this type found on Polygon. [polygon-dbl-spend]: https://gerhard-wagner.medium.com/double-spending-bug-in-polygons-plasma-bridge-2e0954ccadf1 -1. For each `WithdrawalMessage` initiated on L2 (ie. with a unique `messageNonce`), the following properties must hold: - 1. There should be one (and only one) relayable message. +1. For each withdrawal initiated on L2 (ie. with a unique `nonce`), the following properties must hold: + 1. It should only be possible to finalize the withdrawal once. 1. It should not be possible to relay the message with any of its fields modified, ie. 1. Modifying the `sender` field would enable a 'spoofing' attack. 1. Modifying the `target`, `message`, or `value` fields would enable an attacker to dangerously change the @@ -141,15 +165,10 @@ interface Withdrawer { ### Handling Successfully Verified Messages That Fail When Relayed -If the execution of the relayed call fails in the `target` contracts, it is unfortunately not possible to determine -whether or not it was 'supposed' to fail, and whether or not it should be 'replayable'. -Thus we provide the following mitigations: - -// TODO: finish this sentence... - -1. The minimum gas amount to be - -[Insufficient Gas Griefing]:(https://swcregistry.io/docs/SWC-126) +If the execution of the relayed call fails in the `target` contract, it is unfortunately not possible to determine +whether or not it was 'supposed' to fail, and whether or not it should be 'replayable'. For this reason, and to +minimize complexity, we have not provided any replay functionality, this may be implemented in external utility +contracts if desired. ## Summary of Definitions @@ -157,48 +176,6 @@ Thus we provide the following mitigations: | Name | Value | Unit | | --------------------- | --------- | ------- | -| `FINALIZATION_WINDOW` | `604_800` | seconds | - -This `FINALIZATION_WINDOW` value is equivalent to 7 days. - -### Data Structures and Type Aliases - -> TODO: update this section is quite outdated with current impl - -1. A `WithdrawalMessage` is encoded in a struct as follows: - - ```js - struct WithdrawalMessage { - uint256 nonce; - address sender; - uint256 value; - bytes message; - } - ``` - -1. The `L2OutputTimestamp` is an alias for `uint256`, and MUST be a multiple of the `SUBMISSION_INTERVAL` described - in the [L2 Output](./proposals.md#constants) document. - -1. The `WithdrawalsRoot` is an alias for a `bytes32` value, corresponding to the [MPT][g-mpt] - storage root of the Withdrawals predeploy contract at `0x4200000000000000000000000000000000000015` (described below). - -1. The `WithdrawalsRootInclusionProof` proof contains the data necessary to prove that the provided `WithdrawalsRoot` is - included in the - [SSZ merkleization](https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization) - of the `L2Output` as defined in the - [L2 output commitment construction](./proposals.md#l2-output-commitment-construction). - -1. A `WithdrawalMessageInclusionProof` is an MPT proof encoded in a struct as follows: - - ```js - struct WithdrawalMessageInclusionProof { - WithdrawalMessage message; - bytes32 l2withdrawalsRoot; - bytes memory _key; // storage key of the withdrawal message commitment - bytes memory _value; // Always bytes32(1) (boolean validity status of the message) - bytes memory _proof; // MPT inclusion proof for the key/value - } - ``` +| `FINALIZATION_PERIOD` | `604_800` | seconds | -1. This document also refers to the `L2Output` type as defined in the - [L2 output commitment construction](./proposals.md#l2-output-commitment-construction). +This `FINALIZATION_PERIOD` value is equivalent to 7 days. From ae23047ad4d50dd182c90c26c50e83edf9d54231 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 11:41:21 -0400 Subject: [PATCH 418/585] contracts: Fix ETH burning in the withdrawer contract --- .../contracts/contracts/L1/OptimismPortal.sol | 1 + packages/contracts/contracts/L2/Burner.sol | 8 ++++++++ .../contracts/contracts/L2/Withdrawer.sol | 20 ++++--------------- .../contracts/contracts/test/Withdrawer.t.sol | 12 ----------- 4 files changed, 13 insertions(+), 28 deletions(-) create mode 100644 packages/contracts/contracts/L2/Burner.sol diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index 5728b96d2ef1..e5f655105fce 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -92,6 +92,7 @@ contract OptimismPortal is DepositFeed { * @param _nonce Nonce for the provided message. * @param _sender Message sender address on L2. * @param _target Target address on L1. + * @param _value ETH to send to the target. * @param _data Data to send to the target. * @param _gasLimit Gas to be forwarded to the target. * @param _timestamp L2 timestamp of the outputRoot. diff --git a/packages/contracts/contracts/L2/Burner.sol b/packages/contracts/contracts/L2/Burner.sol new file mode 100644 index 000000000000..f922f0a2db84 --- /dev/null +++ b/packages/contracts/contracts/L2/Burner.sol @@ -0,0 +1,8 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +contract Burner { + constructor() payable { + selfdestruct(payable(address(this))); + } +} diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 94ad3f792153..79864d0263df 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -6,6 +6,9 @@ import { AddressAliasHelper } from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +/* Interaction imports */ +import { Burner } from "./Burner.sol"; + /** * @title Withdrawer * @notice The Withdrawer contract facilitates sending both ETH value and data from L2 to L1. @@ -86,22 +89,7 @@ contract Withdrawer { */ function burn() external { uint256 balance = address(this).balance; - assembly { - // Put this code into memory at the scratch space (first word). - // 30 - address(this) - // ff - selfdestruct - mstore(0, 0x30ff) - - // Transfer all funds to a new contract that will selfdestruct - // and destroy all the ether it holds in the process. - pop( - create( - balance(address()), // Fund the new contract with the balance of this one. - 30, // offset - 2 // size - ) - ) - } + Burner burner = new Burner{ value: balance }(); emit WithdrawerBalanceBurnt(balance); } } diff --git a/packages/contracts/contracts/test/Withdrawer.t.sol b/packages/contracts/contracts/test/Withdrawer.t.sol index bd7ece45eb81..0a3a85e5bf92 100644 --- a/packages/contracts/contracts/test/Withdrawer.t.sol +++ b/packages/contracts/contracts/test/Withdrawer.t.sol @@ -100,25 +100,13 @@ contract WithdawerBurnTest is WithdrawerTestCommon { // Test: burn should destroy the ETH held in the contract function test_burn() external { - // Sanity check that setUp worked as expected. assertEq(address(wd).balance, NON_ZERO_VALUE); vm.expectEmit(true, false, false, false); emit WithdrawerBalanceBurnt(NON_ZERO_VALUE); wd.burn(); - // Calculate the address of the contract that will selfdestruct at the end of this tx. - // Based on https://github.com/ethereum-optimism/contracts/blob/532b9a743cf34d66e812cbf1d9f28c452b52e1bd/contracts/optimistic-ethereum/libraries/utils/Lib_EthUtils.sol#L145 - bytes[] memory encoded = new bytes[](2); - encoded[0] = Lib_RLPWriter.writeAddress(address(wd)); // creator - encoded[1] = Lib_RLPWriter.writeUint(0); // nonce - bytes memory encodedList = Lib_RLPWriter.writeList(encoded); - address created = Lib_Bytes32Utils.toAddress(keccak256(encodedList)); // The Withdrawer should have no balance assertEq(address(wd).balance, 0); - - // The created contract should have its balance - assertEq(created.balance, NON_ZERO_VALUE); - } } From e977fffbf48ff5ebd08d4309b54fe75241f8b27d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 12:15:45 -0400 Subject: [PATCH 419/585] specs: Address review comments --- specs/deposits.md | 5 +++-- specs/glossary.md | 6 +++--- specs/withdrawals.md | 32 +++++++++++++++++++++----------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index 54abb7b2bf7f..790990a7adc8 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -235,8 +235,9 @@ The deposit contract handles two special cases: [address-aliasing]: #address-aliasing If the caller is a contract, the address will be transformed by adding -`0x1111000000000000000000000000000000001111` to it. This prevents attacks in which a contract on L1 -has the same address as a contract on L2 but doesn't have the same code. We can safely ignore this +`0x1111000000000000000000000000000000001111` to it. This is the reverse of the +transformation described in the [deposits spec](./withdrawals.md#address-aliasing). This prevents attacks in which a +contract on L1 has the same address as a contract on L2 but doesn't have the same code. We can safely ignore this for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes it possible for users to interact with contracts on L2 even when the Sequencer is down. diff --git a/specs/glossary.md b/specs/glossary.md index fa9851991808..c4aeadce213a 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -294,11 +294,11 @@ cf. [Deposits Specification](deposits.md) In general, a withdrawal is a transaction sent from L2 to L1 that may transfer data and/or value. -This term *withdrawal* is somewhat ambiguous as these "transactions" exist at multiple levels. In order to differentiate +The term *withdrawal* is somewhat ambiguous as these "transactions" exist at multiple levels. In order to differentiate between the L1 and L2 components of a withdrawal we introduce the following terms: -- *withdrawal initiating transaction* refers specifically to a transaction on L2 sent to the Withdrawals predeploy. -- *withdrawal finalizing transaction* refers specifically to an L1 transaction which finalizes and relays the +- A *withdrawal initiating transaction* refers specifically to a transaction on L2 sent to the Withdrawals predeploy. +- A *withdrawal finalizing transaction* refers specifically to an L1 transaction which finalizes and relays the withdrawal. ## Relayer diff --git a/specs/withdrawals.md b/specs/withdrawals.md index b52e1c40b6ca..5fcae8e17e2e 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -12,13 +12,14 @@ **Table of Contents** [Withdrawals][g-withdrawal] are cross domain transactions which are initiated on L2, and finalized by a transaction -executed on L1. They may be used to transfer data and/or ETH from L1 to L2. +executed on L1. Notably, withdrawals may be used by and L2 account to call an L1 contract, or to transfer ETH from +an L2 account to an L1 account. **Vocabulary note**: *withdrawal* can refer to the transaction at various stages of the process, but we introduce -more specific terms to differentiate between the transaction +more specific terms to differentiate: -- *withdrawal initiating transaction* refers specifically to a transaction on L2 sent to the Withdrawals predeploy. -- *withdrawal finalizing transaction* refers specifically to an L1 transaction which finalizes and relays the +- A *withdrawal initiating transaction* refers specifically to a transaction on L2 sent to the Withdrawals predeploy. +- A *withdrawal finalizing transaction* refers specifically to an L1 transaction which finalizes and relays the withdrawal. Withdrawals are initiated on L2 via a call to the Withdrawals predeploy contract, which records the important properties @@ -37,6 +38,7 @@ finalization. - [On L2](#on-l2) - [On L1](#on-l1) - [The L2 Withdrawer Contract](#the-l2-withdrawer-contract) + - [Address Aliasing](#address-aliasing) - [The Optimism Portal Contract](#the-optimism-portal-contract) - [Withdrawal Verification and Finalization](#withdrawal-verification-and-finalization) - [Security Considerations](#security-considerations) @@ -58,10 +60,12 @@ An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdra ### On L1 -1. A [relayer][g-relayer] submits the required inputs (see below) to the `OptimismPortal` contract. The relayer need +1. A [relayer][g-relayer] submits the required inputs to the `OptimismPortal` contract. The relayer need not be the same entity which initiated the withdrawal on L2. -2. The `OptimismPortal` contract retrieves the output root from the `OutputOracle`'s `l2Outputs()` function, and - performs the remainder of the verification process internally. + These inputs include the withdrawal transaction data, inclusion proofs, and a timestamp. The timestamp + must be one for which an L2 output root exists, which commits to the withdrawal as registered on L2. +2. The `OptimismPortal` contract retrieves the output root for the given timestamp from the `OutputOracle`'s + `l2Outputs()` function, and performs the remainder of the verification process internally. 3. If verification fails, the call reverts. Otherwise the call is forwarded, and the hash is recorded to prevent it from from being replayed. @@ -93,8 +97,13 @@ interface Withdrawer { } ``` -If called by a contract, the `initiateWithdrawal` function will alias the `sender` address in the reverse of the -manner described in the [deposits spec](./deposits.md#address-aliasing). +### Address Aliasing + +[address-aliasing]: #address-aliasing + +If called by a contract, the `initiateWithdrawal` function will alias the `sender` address by subtracting +`0x1111000000000000000000000000000000001111`. This is the reverse of the +transformation described in the [deposits spec](./deposits.md#address-aliasing). ## The Optimism Portal Contract @@ -129,18 +138,19 @@ The following inputs are required to verify and finalize a withdrawal: - `nonce`: Nonce for the provided message. - `sender`: Message sender address on L2. - `target`: Target address on L1. + - `value`: ETH to send to the target. - `data`: Data to send to the target. - `gasLimit`: Gas to be forwarded to the target. - Proof and verification data: - `timestamp`: The L2 timestamp corresponding with the output root. - - `outputRootProof`: The 4 values which are used to derive the output root. + - `outputRootProof`: Four `bytes32` values which are used to derive the output root. - `withdrawalProof`: An inclusion proof for the given withdrawal in the withdrawer contract. These inputs must satisfy the following conditions: 1. The `timestamp` is at least `FINALIZATION_PERIOD` seconds old. 1. `OutputOracle.l2Outputs(timestamp)` returns a non-zero value `l2Output`. -2. The `l2Output` value is equal to the hash of the components of the `outputRootProof` +1. The keccak256 hash of the `outputRootProof` values is equal to the `l2Output`. 1. The `withdrawalProof` is a valid inclusion proof demonstrating that a hash of the Withdrawal transaction data is contained in the storage of the Withdrawer contract on L2. From fe5dd087728e7cd77adf119882f747ef2b45b111 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 12:16:31 -0400 Subject: [PATCH 420/585] ops: Address review comments --- .github/workflows/solidity-ci.yml | 7 ------- .gitmodules | 4 ---- ops/Dockerfile.opnode | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/solidity-ci.yml b/.github/workflows/solidity-ci.yml index 094cbb09cc51..d89b82e90ec8 100644 --- a/.github/workflows/solidity-ci.yml +++ b/.github/workflows/solidity-ci.yml @@ -32,13 +32,6 @@ jobs: cache: 'yarn' - run: yarn install - # We don't currently have any hardhat tests that should run in this context - # - name: Build with HH - # run: yarn build:hh - - # # - name: Test - # # run: yarn test:hh - - name: Lint run: yarn lint:check diff --git a/.gitmodules b/.gitmodules index 7b93ec874984..f38688f818ba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,16 +1,12 @@ [submodule "packages/contracts/lib/ds-test"] path = packages/contracts/lib/ds-test url = https://github.com/dapphub/ds-test - ignore = dirty [submodule "packages/contracts/lib/openzeppelin-contracts"] path = packages/contracts/lib/openzeppelin-contracts url = https://github.com/openzeppelin/openzeppelin-contracts - ignore = dirty [submodule "packages/contracts/lib/forge-std"] path = packages/contracts/lib/forge-std url = https://github.com/brockelmore/forge-std - ignore = dirty [submodule "packages/contracts/lib/optimism"] path = packages/contracts/lib/optimism url = https://github.com/ethereum-optimism/optimism - ignore = dirty diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode index ac80494a9eac..813204553dda 100644 --- a/ops/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -1,4 +1,4 @@ -FROM golang:1.17.3-alpine3.13 as builder +FROM golang:1.18.0-alpine3.15 as builder RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash From 42935c83c7129f2b15b848b4bab4e0b3c52a5ee9 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 6 Apr 2022 11:15:41 -0600 Subject: [PATCH 421/585] Update Dockerfile.opnode --- ops/Dockerfile.opnode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode index 813204553dda..621fed31a6df 100644 --- a/ops/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -13,7 +13,7 @@ COPY ./ops/rollup.json /app/rollup.json COPY ./opnode /app/opnode RUN make opnode -FROM alpine:3.13 +FROM alpine:3.15 COPY --from=builder /app/bin/op /usr/local/bin COPY --from=builder /app/opnode-entrypoint.sh /opnode-entrypoint.sh From 38a39303de1ebcb7e711d72b3042ccbd922b03e8 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 6 Apr 2022 11:02:56 -0600 Subject: [PATCH 422/585] ops: Fix devnet - Fixes the devnet config to correctly generate rollup/genesis files. - Fixes a bug that causes the rollup node to get stuck when there's a large timestamp delta between genesis and the current time, as is the case in the devnet. --- Makefile | 3 +++ opnode/rollup/driver/state.go | 2 +- ops/Dockerfile.opnode | 2 ++ ops/genesis-l1.json | 2 +- ops/genesis-l2.json | 2 +- ops/opnode-entrypoint.sh | 29 ++++++++++++++++++++++------- ops/rollup.json | 14 ++++++++++---- 7 files changed, 40 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 1d2d4a76cc14..51bad9466521 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,9 @@ devnet-clean: devnet-down .PHONY: devnet-clean devnet-up: + @test -f ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json + @test -f ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json + @test -f ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json @(cd ./ops && \ DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index c228d5e7906e..f264745d0090 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -237,7 +237,7 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { return eth.L1BlockRef{}, nil } // Don't produce blocks until past the L1 genesis - if nextOrigin.Number <= s.Config.Genesis.L1.Number { + if nextOrigin.Number < s.Config.Genesis.L1.Number { s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis") return eth.L1BlockRef{}, nil } diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode index 621fed31a6df..ec12ff50b173 100644 --- a/ops/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -15,6 +15,8 @@ RUN make opnode FROM alpine:3.15 +RUN apk add --no-cache curl jq + COPY --from=builder /app/bin/op /usr/local/bin COPY --from=builder /app/opnode-entrypoint.sh /opnode-entrypoint.sh COPY --from=builder /app/rollup.json /rollup.json diff --git a/ops/genesis-l1.json b/ops/genesis-l1.json index 88b72018d35e..7cc460c04a9b 100644 --- a/ops/genesis-l1.json +++ b/ops/genesis-l1.json @@ -18,7 +18,7 @@ } }, "nonce": "0x0", - "timestamp": "0x623239da", + "timestamp": "0x624DCCEC", "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000ca062b0fd91172d89bcd4bb084ac4e21972cc4670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x47b760", "difficulty": "0x1", diff --git a/ops/genesis-l2.json b/ops/genesis-l2.json index bb8f37176021..26982a1ea0e6 100644 --- a/ops/genesis-l2.json +++ b/ops/genesis-l2.json @@ -16,7 +16,7 @@ "terminalTotalDifficulty": 0 }, "nonce": "0x1234", - "timestamp": "0x61fc5cf1", + "timestamp": "0x624DCCEC", "extraData": "0x", "gasLimit": "0x4c4b40", "difficulty": "0x1", diff --git a/ops/opnode-entrypoint.sh b/ops/opnode-entrypoint.sh index 745f88fff195..c16640bca81c 100644 --- a/ops/opnode-entrypoint.sh +++ b/ops/opnode-entrypoint.sh @@ -1,18 +1,33 @@ #!/bin/sh set -exu -curl \ - --retry 5 \ +L1_GENESIS=$(curl \ + --fail \ + --retry 10 \ --retry-delay 2 \ + --retry-connrefused \ -X POST \ -H "Content-Type: application/json" \ --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ - http://localhost:9545 \ - | jq -r ".result.hash" \ - | tee l2_genesis_hash.txt + http://l1:8545) + +L2_GENESIS=$(curl \ + --fail \ + --retry 10 \ + --retry-delay 2 \ + --retry-connrefused \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + http://l2:8545) + +echo "L2 genesis timestamp:" +echo $L2_GENESIS | jq -r '.result.timestamp' cat /rollup.json \ - | jq ". | .genesis.l2.hash = \"${cat l2_genesis_hash.txt}\"" \ + | jq ". | .genesis.l1.hash = \"$(echo $L1_GENESIS | jq -r '.result.hash')\"" \ + | jq ". | .genesis.l2.hash = \"$(echo $L2_GENESIS | jq -r '.result.hash')\"" \ + | jq ". | .genesis.l2_time = $(echo $L2_GENESIS | jq -r '.result.timestamp' | xargs printf "%d")" \ | tee /rollup-with-l2-hash.json && \ mv /rollup-with-l2-hash.json /rollup.json @@ -20,7 +35,7 @@ exec op \ --l1 ws://l1:8546 \ --l2 ws://l2:8546 \ --sequencing.enabled \ - --rollup.config /config/rollup.json \ + --rollup.config /rollup.json \ --batchsubmitter.key /config/bss-key.txt \ --l2.eth http://l2:8545 \ --rpc.addr 0.0.0.0 \ diff --git a/ops/rollup.json b/ops/rollup.json index 0c5691f85562..c7fd198775b1 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -11,11 +11,17 @@ "l2_time": 1647573629 }, - "block_time": 1, + "block_time": 2, - "max_sequencer_time_diff": 10, + "max_sequencer_drift": 10, - "seq_window_size": 64, + "seq_window_size": 2, - "l1_chain_id": 900 + "l1_chain_id": 900, + + "fee_recipient_address": "0xff00000000000000000000000000000000000002", + + "batch_inbox_address": "0xff00000000000000000000000000000000000002", + + "batch_sender_address": "0xde3829a23df1479438622a08a116e8eb3f620bb5" } From 00c593b1babf01ec7951ca413ecfba482036ce6f Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 6 Apr 2022 12:16:45 -0600 Subject: [PATCH 423/585] Update opnode/rollup/driver/state.go Co-authored-by: Diederik Loerakker --- opnode/rollup/driver/state.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index f264745d0090..557dda1add0f 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -236,7 +236,8 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) return eth.L1BlockRef{}, nil } - // Don't produce blocks until past the L1 genesis + // Don't produce blocks until at the rollup-genesis block of the L1 chain + // note: deposits within this L1 block will be included in L2. if nextOrigin.Number < s.Config.Genesis.L1.Number { s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis") return eth.L1BlockRef{}, nil From 4a70dd7f6ce5216482434fd49c8d0341263ab9c0 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 6 Apr 2022 12:19:02 -0600 Subject: [PATCH 424/585] Update rollup.json --- ops/rollup.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ops/rollup.json b/ops/rollup.json index c7fd198775b1..805c578cfb99 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -19,7 +19,7 @@ "l1_chain_id": 900, - "fee_recipient_address": "0xff00000000000000000000000000000000000002", + "fee_recipient_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "batch_inbox_address": "0xff00000000000000000000000000000000000002", From e39a51c43a71de85234f98ea72f8417004d53383 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 15:40:17 -0400 Subject: [PATCH 425/585] Update predeploy addresses The new predeploy addresses are incremented by 1 in order to avoid conflicts with the system addresses. --- opnode/predeploys.go | 2 +- packages/contracts/contracts/L2/Withdrawer.sol | 2 +- packages/contracts/contracts/test/OptimismPortal.t.sol | 2 +- packages/contracts/test/withdrawer.spec.ts | 2 +- specs/deposits.md | 4 ++-- specs/withdrawals.md | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/opnode/predeploys.go b/opnode/predeploys.go index 3ab61c47e034..4ff1a985f44c 100644 --- a/opnode/predeploys.go +++ b/opnode/predeploys.go @@ -2,4 +2,4 @@ package opnode import "github.com/ethereum/go-ethereum/common" -var WithdrawalContractAddress = common.HexToAddress("0x4200000000000000000000000000000000000015") +var WithdrawalContractAddress = common.HexToAddress("0x4200000000000000000000000000000000000016") diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 79864d0263df..32c18145e339 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -12,7 +12,7 @@ import { Burner } from "./Burner.sol"; /** * @title Withdrawer * @notice The Withdrawer contract facilitates sending both ETH value and data from L2 to L1. - * It is predeployed in the L2 state at address 0x4200000000000000000000000000000000000015. + * It is predeployed in the L2 state at address 0x4200000000000000000000000000000000000016. */ contract Withdrawer { /********** diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index 564bedf0b3af..e5a8203966d3 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -42,7 +42,7 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { OptimismPortal op; // Target constructor arguments - address withdrawalsPredeploy = 0x4200000000000000000000000000000000000015; + address withdrawalsPredeploy = 0x4200000000000000000000000000000000000016; // Cache of timestamps uint256 startingBlockTimestamp; diff --git a/packages/contracts/test/withdrawer.spec.ts b/packages/contracts/test/withdrawer.spec.ts index 60e346d50ad0..f14dbea972fa 100644 --- a/packages/contracts/test/withdrawer.spec.ts +++ b/packages/contracts/test/withdrawer.spec.ts @@ -16,7 +16,7 @@ import * as rlp from 'rlp' const l2GethProvider = new providers.JsonRpcProvider('http://localhost:9545') const l1GethProvider = new providers.JsonRpcProvider('http://localhost:8545') -const withdrawerAddress = '0x4200000000000000000000000000000000000015' +const withdrawerAddress = '0x4200000000000000000000000000000000000016' const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) const NON_ZERO_GASLIMIT = BigNumber.from(50_000) diff --git a/specs/deposits.md b/specs/deposits.md index 790990a7adc8..a3782080132b 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -142,7 +142,7 @@ This transaction MUST have the following values: 1. `from` is `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001` (the address of the [L1 Attributes depositor account][depositor-account]) -2. `to` is `0x4200000000000000000000000000000000000014` (the address of the [L1 attributes predeployed +2. `to` is `0x4200000000000000000000000000000000000015` (the address of the [L1 attributes predeployed contract][predeploy]). 3. `mint` is `0` 4. `value` is `0` @@ -172,7 +172,7 @@ opcodes during execution of the L1 attributes deposited transaction. [predeploy]: #l1-attributes-predeployed-contract -A predeployed contract on L2 at address `0x4200000000000000000000000000000000000014`, which holds +A predeployed contract on L2 at address `0x4200000000000000000000000000000000000015`, which holds certain block variables from the corresponding L1 block in storage, so that they may be accessed during the execution of the subsequent deposited transactions. diff --git a/specs/withdrawals.md b/specs/withdrawals.md index 5fcae8e17e2e..6f6aafa649e9 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -72,7 +72,7 @@ An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdra ## The L2 Withdrawer Contract A withdrawal is initiated by calling the Withdrawer contract's `initiateWithdrawal` function. -The Withdrawer is a simple predeploy contract at `0x4200000000000000000000000000000000000015` which stores messages +The Withdrawer is a simple predeploy contract at `0x4200000000000000000000000000000000000016` which stores messages to be withdrawn. ```js From dc7ddff79a7d7d4ac2990ca229526d55c265c19e Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 6 Apr 2022 15:09:44 -0600 Subject: [PATCH 426/585] tests: Add tests for batch requests when the parent request fails This test makes sure that we do not retry when the parent request fails. We don't, but it wasn't immediately clear. I also removed a duplicate assertion lib since we're using `testify` everywhere else. --- go.mod | 4 +--- go.sum | 7 +++++-- opnode/l1/batching_test.go | 43 +++++++++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 1fb76d23e921..a699cd88235f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum-optimism/optimistic-specs -go 1.18 +go 1.17 require ( github.com/ethereum/go-ethereum v1.10.16 @@ -10,7 +10,6 @@ require ( github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.5 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 - gotest.tools v2.2.0+incompatible ) require ( @@ -28,7 +27,6 @@ require ( github.com/go-stack/stack v1.8.1 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/go-cmp v0.5.4 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect diff --git a/go.sum b/go.sum index 90a469608a8f..6287e49190b0 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,7 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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= @@ -203,7 +204,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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= @@ -461,6 +461,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -519,6 +520,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v 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.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -572,9 +574,11 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= @@ -698,7 +702,6 @@ 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 h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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= diff --git a/opnode/l1/batching_test.go b/opnode/l1/batching_test.go index 9c5c0b6e8ff9..5dfe93051819 100644 --- a/opnode/l1/batching_test.go +++ b/opnode/l1/batching_test.go @@ -2,14 +2,14 @@ package l1 import ( "context" + "errors" "fmt" - "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - log "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "gotest.tools/assert" + "testing" ) type elemCall struct { @@ -77,9 +77,7 @@ func (tc *batchTestCase) Run(t *testing.T) { }).Return([]error{batchCall.err}) // wrap to preserve nil as type of error } - log := testlog.Logger(t, log.LvlError) - - err := fetchBatched(context.Background(), log, requests, tc.GetBatch, tc.maxRetry, tc.maxPerBatch, tc.maxParallel) + err := fetchBatched(context.Background(), testlog.Logger(t, log.LvlError), requests, tc.GetBatch, tc.maxRetry, tc.maxPerBatch, tc.maxParallel) assert.Equal(t, err, tc.err) tc.AssertExpectations(t) @@ -264,3 +262,34 @@ func TestFetchBatched(t *testing.T) { t.Run(tc.name, tc.Run) } } + +type parentErrBatchTestCase struct { + mock.Mock +} + +func (c *parentErrBatchTestCase) GetBatch(ctx context.Context, b []rpc.BatchElem) error { + return c.Mock.MethodCalled("get", b).Get(0).([]error)[0] +} + +func (c *parentErrBatchTestCase) Run(t *testing.T) { + var requests []rpc.BatchElem + for i := 0; i < 2; i++ { + requests = append(requests, rpc.BatchElem{ + Method: "testing", + Args: []interface{}{i}, + }) + } + + // shouldn't retry if it's an error on the actual request + expErr := errors.New("fail") + c.On("get", requests).Run(func(args mock.Arguments) { + }).Return([]error{expErr}) + err := fetchBatched(context.Background(), testlog.Logger(t, log.LvlError), requests, c.GetBatch, 2, 2, 1) + assert.Equal(t, expErr, err) + c.AssertExpectations(t) +} + +func TestFetchBatchedContextTimeout(t *testing.T) { + var c parentErrBatchTestCase + c.Run(t) +} From d3ba284dcabf8af8a9eb9e9c5cff5fefc1eb13a0 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 6 Apr 2022 15:02:57 -0700 Subject: [PATCH 427/585] opnode: Don't start sequencing blocks until past the L1 genesis (#325) This has to be reverted to ensure that the sequencer starts producing blocks at the same location as the verifier. Sometimes the previous code would cause reorgs on the sequencer (expected), and sometimes it would cause a chain split (unexpected and unexplained as of writing this commit message 4/6/22). --- opnode/rollup/driver/state.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 557dda1add0f..0424d13c2ac2 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -236,9 +236,8 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) return eth.L1BlockRef{}, nil } - // Don't produce blocks until at the rollup-genesis block of the L1 chain - // note: deposits within this L1 block will be included in L2. - if nextOrigin.Number < s.Config.Genesis.L1.Number { + // Don't produce blocks until past the rollup-genesis block of the L1 chain + if nextOrigin.Number <= s.Config.Genesis.L1.Number { s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis") return eth.L1BlockRef{}, nil } From b68cafef7f49f0971605566bff524b1d91956fa4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 7 Apr 2022 00:17:53 +0200 Subject: [PATCH 428/585] opnode: update to latest L2 geth --- go.mod | 8 +++++--- go.sum | 15 +++++++++++---- opnode/l2/api.go | 29 ++++++++++++++--------------- opnode/l2/source.go | 27 +++++++++++++++++++-------- opnode/rollup/driver/driver.go | 2 +- opnode/rollup/driver/step.go | 10 +++++----- 6 files changed, 55 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index 1fb76d23e921..ae98795dad37 100644 --- a/go.mod +++ b/go.mod @@ -16,11 +16,13 @@ require ( require ( github.com/VictoriaMetrics/fastcache v1.9.0 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.2 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect github.com/fjl/memsize v0.0.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect @@ -33,7 +35,7 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/huin/goupnp v1.0.2 // indirect + github.com/huin/goupnp v1.0.3 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect @@ -66,7 +68,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220405004857-d5e1fc1a74bd +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220406213206-248249306ec5 // For local debugging: -// replace github.com/ethereum/go-ethereum v1.10.16 => ../reference-optimistic-geth +//replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/go.sum b/go.sum index 90a469608a8f..bdf67d3acf9c 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,9 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd/btcec/v2 v2.1.2 h1:YoYoC9J0jwfukodSBMzZYUVQ8PTiYg4BnOWiJVzTmLs= +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/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= @@ -108,6 +111,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 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= @@ -128,8 +135,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220405004857-d5e1fc1a74bd h1:9lcMyd+cWztoY/v42cAW7DvyyI0O2iqq3+zTsZhV1JI= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220405004857-d5e1fc1a74bd/go.mod h1:DE7Qn/NgxDNnrl+Oju/tczSsn1aZ7rERXZDLHmVUmC8= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220406213206-248249306ec5 h1:DQF/m7Jafs7bJTTAjQ8dKKcdv58VtFZ+lfF0AjOJeFM= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220406213206-248249306ec5/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= 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= @@ -237,8 +244,8 @@ github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM 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.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= -github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= -github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 3acc0843540e..d290a84ae6f5 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -5,6 +5,8 @@ import ( "fmt" "reflect" + "github.com/ethereum/go-ethereum/core/beacon" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum/go-ethereum/common" @@ -85,8 +87,7 @@ type Uint256Quantity = uint256.Int type Data = hexutil.Bytes -// TODO: implement neat 8 byte typed payload ID and upstream it to geth api definitions -type PayloadID = hexutil.Bytes +type PayloadID = beacon.PayloadID type ExecutionPayload struct { ParentHashField common.Hash `json:"parentHash"` @@ -94,7 +95,7 @@ type ExecutionPayload struct { StateRoot Bytes32 `json:"stateRoot"` ReceiptsRoot Bytes32 `json:"receiptsRoot"` LogsBloom Bytes256 `json:"logsBloom"` - Random Bytes32 `json:"random"` + PrevRandao Bytes32 `json:"prevRandao"` BlockNumber Uint64Quantity `json:"blockNumber"` GasLimit Uint64Quantity `json:"gasLimit"` GasUsed Uint64Quantity `json:"gasUsed"` @@ -151,7 +152,7 @@ type PayloadAttributes struct { // value for the timestamp field of the new payload Timestamp Uint64Quantity `json:"timestamp"` // value for the random field of the new payload - Random Bytes32 `json:"random"` + PrevRandao Bytes32 `json:"prevRandao"` // suggested value for the coinbase field of the new payload SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient"` // Transactions to force into the block (always at the start of the transactions list). @@ -169,9 +170,16 @@ const ( ExecutionInvalid ExecutePayloadStatus = "INVALID" // sync process is in progress ExecutionSyncing ExecutePayloadStatus = "SYNCING" + // returned if the payload is not fully validated, and does not extend the canonical chain, + // but will be remembered for later (on reorgs or sync updates and such) + ExecutionAccepted ExecutePayloadStatus = "ACCEPTED" + // if the block-hash in the payload is not correct + ExecutionInvalidBlockHash ExecutePayloadStatus = "INVALID_BLOCK_HASH" + // proof-of-stake transition only, not used in rollup + ExecutionInvalidTerminalBlock ExecutePayloadStatus = "INVALID_TERMINAL_BLOCK" ) -type ExecutePayloadResult struct { +type PayloadStatusV1 struct { // the result of the payload execution Status ExecutePayloadStatus `json:"status"` // the hash of the most recent valid block in the branch defined by payload and its ancestors @@ -189,18 +197,9 @@ type ForkchoiceState struct { FinalizedBlockHash common.Hash `json:"finalizedBlockHash"` } -type ForkchoiceUpdatedStatus string - -const ( - // given payload is valid - UpdateSuccess ForkchoiceUpdatedStatus = "SUCCESS" - // sync process is in progress - UpdateSyncing ForkchoiceUpdatedStatus = "SYNCING" -) - type ForkchoiceUpdatedResult struct { // the result of the payload execution - Status ForkchoiceUpdatedStatus `json:"status"` + PayloadStatus PayloadStatusV1 `json:"payloadStatus"` // the payload id if requested PayloadID *PayloadID `json:"payloadId"` } diff --git a/opnode/l2/source.go b/opnode/l2/source.go index c7b8f14cdcfb..a41b77d879e7 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -68,25 +68,30 @@ func (s *Source) ForkchoiceUpdate(ctx context.Context, fc *ForkchoiceState, attr e.Error("Failed to share forkchoice-updated signal") } } - switch result.Status { - case UpdateSyncing: + switch result.PayloadStatus.Status { + case ExecutionSyncing: return nil, fmt.Errorf("updated forkchoice, but node is syncing: %v", err) - case UpdateSuccess: + case ExecutionAccepted, ExecutionInvalidTerminalBlock, ExecutionInvalidBlockHash: + // ACCEPTED, INVALID_TERMINAL_BLOCK, INVALID_BLOCK_HASH are only for execution + return nil, fmt.Errorf("unexpected %s status, could not update forkchoice: %v", result.PayloadStatus.Status, err) + case ExecutionInvalid: + return nil, fmt.Errorf("cannot update forkchoice, block is invalid: %v", err) + case ExecutionValid: return &result, nil default: - return nil, fmt.Errorf("unknown forkchoice status on %s: %q, ", fc.SafeBlockHash, string(result.Status)) + return nil, fmt.Errorf("unknown forkchoice status on %s: %q, ", fc.SafeBlockHash, string(result.PayloadStatus.Status)) } } // ExecutePayload executes a built block on the execution engine and returns an error if it was not successful. -func (s *Source) ExecutePayload(ctx context.Context, payload *ExecutionPayload) error { +func (s *Source) NewPayload(ctx context.Context, payload *ExecutionPayload) error { e := s.log.New("block_hash", payload.BlockHash) e.Debug("sending payload for execution") execCtx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() - var result ExecutePayloadResult - err := s.rpc.CallContext(execCtx, &result, "engine_executePayloadV1", payload) + var result PayloadStatusV1 + err := s.rpc.CallContext(execCtx, &result, "engine_newPayloadV1", payload) e.Debug("Received payload execution result", "status", result.Status, "latestValidHash", result.LatestValidHash, "message", result.ValidationError) if err != nil { e.Error("Payload execution failed", "err", err) @@ -97,9 +102,15 @@ func (s *Source) ExecutePayload(ctx context.Context, payload *ExecutionPayload) case ExecutionValid: return nil case ExecutionSyncing: - return fmt.Errorf("failed to execute payload %s, node is syncing, latest valid hash is %s", payload.ID(), result.LatestValidHash) + return fmt.Errorf("failed to execute payload %s, node is syncing", payload.ID()) case ExecutionInvalid: return fmt.Errorf("execution payload %s was INVALID! Latest valid hash is %s, ignoring bad block: %q", payload.ID(), result.LatestValidHash, result.ValidationError) + case ExecutionInvalidBlockHash: + return fmt.Errorf("execution payload %s has INVALID BLOCKHASH! %v", payload.BlockHash, result.ValidationError) + case ExecutionInvalidTerminalBlock: + return fmt.Errorf("engine is misconfigured. Received invalid-terminal-block error while engine API should be active at genesis. err: %v", result.ValidationError) + case ExecutionAccepted: + return fmt.Errorf("execution payload cannot be validated yet, latest valid hash is %s", result.LatestValidHash) default: return fmt.Errorf("unknown execution status on %s: %q, ", payload.ID(), string(result.Status)) } diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index b9161fac3a25..747ee31b4c1f 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -31,7 +31,7 @@ type Downloader interface { type Engine interface { GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) - ExecutePayload(ctx context.Context, payload *l2.ExecutionPayload) error + NewPayload(ctx context.Context, payload *l2.ExecutionPayload) error BlockByHash(context.Context, common.Hash) (*types.Block, error) BlockByNumber(context.Context, *big.Int) (*types.Block, error) } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 4c5db0633760..57fc8c1c5824 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -65,7 +65,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, attrs := &l2.PayloadAttributes{ Timestamp: hexutil.Uint64(l2Head.Time + d.Config.BlockTime), - Random: l2.Bytes32(l1Info.MixDigest()), + PrevRandao: l2.Bytes32(l1Info.MixDigest()), SuggestedFeeRecipient: d.Config.FeeRecipientAddress, Transactions: txns, NoTxPool: false, @@ -170,7 +170,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S txns = append(txns, batch.Transactions...) attrs := &l2.PayloadAttributes{ Timestamp: hexutil.Uint64(batch.Timestamp), - Random: l2.Bytes32(l1Info.MixDigest()), + PrevRandao: l2.Bytes32(l1Info.MixDigest()), SuggestedFeeRecipient: d.Config.FeeRecipientAddress, Transactions: txns, NoTxPool: false, @@ -216,8 +216,8 @@ func attributesMatchBlock(attrs *l2.PayloadAttributes, parentHash common.Hash, b if uint64(attrs.Timestamp) != block.Time() { return fmt.Errorf("timestamp field does not match. expected: %v. got: %v", uint64(attrs.Timestamp), block.Time()) } - if attrs.Random != l2.Bytes32(block.MixDigest()) { - return fmt.Errorf("random field does not match. expected: %v. got: %v", attrs.Random, l2.Bytes32(block.MixDigest())) + if attrs.PrevRandao != l2.Bytes32(block.MixDigest()) { + return fmt.Errorf("random field does not match. expected: %v. got: %v", attrs.PrevRandao, l2.Bytes32(block.MixDigest())) } if len(attrs.Transactions) != len(block.Transactions()) { return fmt.Errorf("transaction count does not match. expected: %v. got: %v", len(attrs.Transactions), len(block.Transactions())) @@ -281,7 +281,7 @@ func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, if err != nil { return nil, fmt.Errorf("failed to get execution payload: %w", err) } - err = d.l2.ExecutePayload(ctx, payload) + err = d.l2.NewPayload(ctx, payload) if err != nil { return nil, fmt.Errorf("failed to insert execution payload: %w", err) } From fe310d02f6a0976ad6d8f360b7b108148547d558 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Thu, 7 Apr 2022 00:47:54 +0200 Subject: [PATCH 429/585] readme: fix typos and break lines (#327) --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 010b11dbf040..283aadf27887 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This repository holds the work-in-progress specification for the next version of Optimism. -This spec is developped iteratively, specifying a rollup of increasing +This spec is developed iteratively, specifying a rollup of increasing complexity. The current stage specifies a "rollup" whose only transactions are deposits (L2 transactions submitted on L1). @@ -18,7 +18,11 @@ Please note that this specification is currently under heavy construction. ## Local Devnet Setup -You can spin up a local devnet via `docker-compose`. For convenence, we have defined `make` targets to start and stop the devnet with a single command. To run the devnet, you will need `docker` and `docker-compose` installed. Then, as a precondition, make sure that you have compiled the contracts by `cd`ing into `packages/contracts` and running `yarn` followed by `yarn build`. You'll only need to do this if you change the contracts in the future. +You can spin up a local devnet via `docker-compose`. +For convenience, we have defined `make` targets to start and stop the devnet with a single command. +To run the devnet, you will need `docker` and `docker-compose` installed. +Then, as a precondition, make sure that you have compiled the contracts by `cd`ing into `packages/contracts` +and running `yarn` followed by `yarn build`. You'll only need to do this if you change the contracts in the future. Then, run the following: @@ -28,14 +32,17 @@ make devnet-down # stops the devnet make devnet-clean # removes the devnet by deleting images and persistent volumes ``` -L1 is accessible at `http://localhost:8545`, and L2 is accessible at `http://localhost:8546`. Any Ethereum tool - Metamask, `seth`, etc. - can use these endpoints. Note that you will need to specify the L2 chain ID manually if you use Metamask. The devnet's L2 chain ID is 901. +L1 is accessible at `http://localhost:8545`, and L2 is accessible at `http://localhost:8546`. +Any Ethereum tool - Metamask, `seth`, etc. - can use these endpoints. +Note that you will need to specify the L2 chain ID manually if you use Metamask. The devnet's L2 chain ID is 901. The devnet comes with a pre-funded account you can use as a faucet: - Address: `0xde3829a23df1479438622a08a116e8eb3f620bb5` - Private key: `bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7` -The faucet account exists on both L1 and L2. To deposit onto L2 from L1, you can use the `deposit` hardhat task. Run the following from the `packags/contracts` directory: +The faucet account exists on both L1 and L2. To deposit onto L2 from L1, you can use the `deposit` hardhat task. +Run the following from the `packags/contracts` directory: ```bash npx hardhat deposit --amount-eth --to
From 355f4137272e0a7fcd1a48171962ac61bbe805f1 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 6 Apr 2022 16:56:16 -0600 Subject: [PATCH 430/585] Update ref optimistic geth image (#328) --- ops/Dockerfile.l2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ops/Dockerfile.l2 b/ops/Dockerfile.l2 index 7777d68949a6..a8a08c8a4afb 100644 --- a/ops/Dockerfile.l2 +++ b/ops/Dockerfile.l2 @@ -1,4 +1,4 @@ -FROM mslipper/reference-optimistic-geth:latest +FROM ethereumoptimism/reference-optimistic-geth:latest ARG L1_BLOCK_INFO_BYTECODE="" ARG WITHDRAWER_BYTECODE="" From 9d1630544de3b19b206a61e5332fa0d3b41d4026 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 6 Apr 2022 21:13:00 -0600 Subject: [PATCH 431/585] ci: Improve timestamp management in devnet (#329) This change sets timestamps to the current timestamp on fresh devnet deploys. This avoids the devnet having to fill in a bunch of blocks on startup. The timestamp is preserved between runs; `make devnet-clean` will erase the timestamp data if you want to start anew. --- Makefile | 3 ++- ops/Dockerfile.l1 | 8 ++++++-- ops/Dockerfile.l2 | 2 ++ ops/docker-compose.yml | 2 ++ ops/genesis-l1.json | 2 +- ops/genesis-l2.json | 2 +- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 51bad9466521..381bede163a4 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,8 @@ devnet-up: DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ WITHDRAWER_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json | jq .deployedBytecode) \ - docker-compose up --build) + GENESIS_TIMESTAMP=$(shell date +%s) \ + BUILDKIT_PROGRESS=plain docker-compose up --build) .PHONY: devnet-up devnet-down: diff --git a/ops/Dockerfile.l1 b/ops/Dockerfile.l1 index e1655c864e05..4ce0bd5b6d17 100644 --- a/ops/Dockerfile.l1 +++ b/ops/Dockerfile.l1 @@ -1,14 +1,18 @@ FROM ethereum/client-go:v1.10.16 ARG DEPOSIT_FEED_BYTECODE="" +ARG GENESIS_TIMESTAMP="" RUN apk add --no-cache jq COPY entrypoint.sh /entrypoint.sh COPY genesis-l1.json /genesis.json -RUN cat /genesis.json | jq ". | .alloc.deaddeaddeaddeaddeaddeaddeaddeaddead0001.code = \"$DEPOSIT_FEED_BYTECODE\"" | tee /genesis-with-bytecode.json && \ - mv /genesis-with-bytecode.json /genesis.json +RUN cat /genesis.json | \ + jq ". | .alloc.deaddeaddeaddeaddeaddeaddeaddeaddead0001.code = \"$DEPOSIT_FEED_BYTECODE\"" | \ + jq ". | .timestamp = \"$GENESIS_TIMESTAMP\"" | \ + tee /genesis-with-bytecode.json && \ + mv /genesis-with-bytecode.json /genesis.json VOLUME ["/db"] diff --git a/ops/Dockerfile.l2 b/ops/Dockerfile.l2 index a8a08c8a4afb..dd47af40fbbc 100644 --- a/ops/Dockerfile.l2 +++ b/ops/Dockerfile.l2 @@ -2,6 +2,7 @@ FROM ethereumoptimism/reference-optimistic-geth:latest ARG L1_BLOCK_INFO_BYTECODE="" ARG WITHDRAWER_BYTECODE="" +ARG GENESIS_TIMESTAMP="" RUN apk add --no-cache jq @@ -10,6 +11,7 @@ COPY genesis-l2.json /genesis.json RUN cat /genesis.json | jq ". | .alloc.\"4200000000000000000000000000000000000014\".code = \"$L1_BLOCK_INFO_BYTECODE\"" \ | jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$WITHDRAWER_BYTECODE\"" \ + | jq ". | .timestamp = \"$GENESIS_TIMESTAMP\"" \ | tee /genesis-with-bytecode.json && \ mv /genesis-with-bytecode.json /genesis.json diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index db652e1a8f76..eaddc79c3245 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -11,6 +11,7 @@ services: dockerfile: Dockerfile.l1 args: DEPOSIT_FEED_BYTECODE: $DEPOSIT_FEED_BYTECODE + GENESIS_TIMESTAMP: $GENESIS_TIMESTAMP ports: - "8545:8545" volumes: @@ -23,6 +24,7 @@ services: args: L1_BLOCK_INFO_BYTECODE: $L1_BLOCK_INFO_BYTECODE WITHDRAWER_BYTECODE: $WITHDRAWER_BYTECODE + GENESIS_TIMESTAMP: $GENESIS_TIMESTAMP ports: - "9545:8545" volumes: diff --git a/ops/genesis-l1.json b/ops/genesis-l1.json index 7cc460c04a9b..e5ff1cc6e53f 100644 --- a/ops/genesis-l1.json +++ b/ops/genesis-l1.json @@ -18,7 +18,7 @@ } }, "nonce": "0x0", - "timestamp": "0x624DCCEC", + "timestamp": "", "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000ca062b0fd91172d89bcd4bb084ac4e21972cc4670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x47b760", "difficulty": "0x1", diff --git a/ops/genesis-l2.json b/ops/genesis-l2.json index 26982a1ea0e6..b3a1dbd491da 100644 --- a/ops/genesis-l2.json +++ b/ops/genesis-l2.json @@ -16,7 +16,7 @@ "terminalTotalDifficulty": 0 }, "nonce": "0x1234", - "timestamp": "0x624DCCEC", + "timestamp": "", "extraData": "0x", "gasLimit": "0x4c4b40", "difficulty": "0x1", From e4374fd4c9808dfa2a8e6d0a94239bcdeed5280d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 13:52:55 -0400 Subject: [PATCH 432/585] contracts: Move withdrawal logic into abstract contract --- .../contracts/contracts/L1/OptimismPortal.sol | 136 +------------ .../L1/{ => abstracts}/DepositFeed.sol | 4 +- .../L1/abstracts/WithdrawalsRelay.sol | 146 ++++++++++++++ .../Lib_WithdrawalVerifier.sol | 5 +- .../contracts/test/DepositFeed.t.sol | 12 +- .../contracts/test/OptimismPortal.t.sol | 140 +------------- .../contracts/test/WithdrawalsRelay.t.sol | 179 ++++++++++++++++++ 7 files changed, 349 insertions(+), 273 deletions(-) rename packages/contracts/contracts/L1/{ => abstracts}/DepositFeed.sol (94%) create mode 100644 packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol rename packages/contracts/contracts/L1/{ => libraries}/Lib_WithdrawalVerifier.sol (92%) create mode 100644 packages/contracts/contracts/test/WithdrawalsRelay.t.sol diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index e5f655105fce..d3fb9b0cfa2a 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -2,76 +2,27 @@ pragma solidity 0.8.10; /* Inherited Imports */ -import { DepositFeed } from "./DepositFeed.sol"; +import { DepositFeed } from "./abstracts/DepositFeed.sol"; +import { WithdrawalsRelay } from "./abstracts/WithdrawalsRelay.sol"; /* Interactions Imports */ import { L2OutputOracle } from "./L2OutputOracle.sol"; -/* Library Imports */ -import { WithdrawalVerifier } from "./Lib_WithdrawalVerifier.sol"; - /** * @title OptimismPortal * @notice The OptimismPortal is a contract on L1 used to deposit and withdraw between L2 and L1. + * The OptimismPortal must inherit from both the DepositFeed and WithdrawalsRelay as it holds the + * pool of ETH which is deposited to and withdrawn from L2. Aside from affecting the ETH balance, + * the deposit and withdrawal codepaths should be independent from one another. */ -contract OptimismPortal is DepositFeed { - /********** - * Errors * - **********/ - - /// @notice Error emitted when attempting to finalize a withdrawal too early. - error NotYetFinal(); - - /// @notice Error emitted when the output root proof is invalid. - error InvalidOutputRootProof(); - - /// @notice Error emitted when the withdrawal inclusion proof is invalid. - error InvalidWithdrawalInclusionProof(); - - /// @notice Error emitted when a withdrawal has already been finalized. - error WithdrawalAlreadyFinalized(); - - /********** - * Events * - **********/ - - /// @notice Emitted when a withdrawal is finalized - event WithdrawalFinalized(bytes32 indexed); - - /// @notice Value used to reset the l2Sender, this is more efficient than setting it to zero. - address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; - - /********************** - * Contract Variables * - **********************/ - - /// @notice Minimum time that must elapse before a withdrawal can be finalized. - uint256 public immutable FINALIZATION_PERIOD; - - /// @notice Address of the L2OutputOracle. - L2OutputOracle public immutable L2_ORACLE; - - /** - * @notice Public variable which can be used to read the address of the L2 account which - * initated the withdrawal. Can also be used to determine whether or not execution is occuring - * downstream of a call to finalizeWithdrawalTransaction(). - */ - address public l2Sender = DEFAULT_L2_SENDER; - - /** - * @notice A list of withdrawal hashes which have been successfully finalized. - * Used for replay protection. - */ - mapping(bytes32 => bool) public finalizedWithdrawals; - +contract OptimismPortal is DepositFeed, WithdrawalsRelay { /*************** * Constructor * ***************/ - constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) { - L2_ORACLE = _l2Oracle; - FINALIZATION_PERIOD = _finalizationPeriod; - } + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) + WithdrawalsRelay(_l2Oracle, _finalizationPeriod) + {} /********************** * External Functions * @@ -86,73 +37,4 @@ contract OptimismPortal is DepositFeed { receive() external payable { depositTransaction(msg.sender, msg.value, 30000, false, bytes("")); } - - /** - * @notice Finalizes a withdrawal transaction. - * @param _nonce Nonce for the provided message. - * @param _sender Message sender address on L2. - * @param _target Target address on L1. - * @param _value ETH to send to the target. - * @param _data Data to send to the target. - * @param _gasLimit Gas to be forwarded to the target. - * @param _timestamp L2 timestamp of the outputRoot. - * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. - * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. - */ - function finalizeWithdrawalTransaction( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes calldata _data, - uint256 _timestamp, - WithdrawalVerifier.OutputRootProof calldata _outputRootProof, - bytes calldata _withdrawalProof - ) external { - // Check that the timestamp is 7 days old. - unchecked { - if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { - revert NotYetFinal(); - } - } - - // Get the output root. - bytes32 outputRoot = L2_ORACLE.getL2Output(_timestamp); - - // Verify that the output root can be generated with the elements in the proof. - if (outputRoot != WithdrawalVerifier._deriveOutputRoot(_outputRootProof)) { - revert InvalidOutputRootProof(); - } - - // Verify that the hash of the withdrawal transaction's arguments are included in the - // storage hash of the withdrawer contract. - bytes32 withdrawalHash = keccak256( - abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) - ); - if ( - WithdrawalVerifier._verifyWithdrawalInclusion( - withdrawalHash, - _outputRootProof.withdrawerStorageRoot, - _withdrawalProof - ) == false - ) { - revert InvalidWithdrawalInclusionProof(); - } - - // Check that this withdrawal has not already been finalized. - if (finalizedWithdrawals[withdrawalHash] == true) { - revert WithdrawalAlreadyFinalized(); - } - - l2Sender = _sender; - // Make the call. - _target.call{ value: _value, gas: _gasLimit }(_data); - l2Sender = DEFAULT_L2_SENDER; - - // All withdrawals are immediately finalized. If the ability to replay a transaction is - // required, that support can be provided in external contracts. - finalizedWithdrawals[withdrawalHash] = true; - emit WithdrawalFinalized(withdrawalHash); - } } diff --git a/packages/contracts/contracts/L1/DepositFeed.sol b/packages/contracts/contracts/L1/abstracts/DepositFeed.sol similarity index 94% rename from packages/contracts/contracts/L1/DepositFeed.sol rename to packages/contracts/contracts/L1/abstracts/DepositFeed.sol index 3a67e00edfa5..edce3e067122 100644 --- a/packages/contracts/contracts/L1/DepositFeed.sol +++ b/packages/contracts/contracts/L1/abstracts/DepositFeed.sol @@ -4,13 +4,13 @@ pragma solidity 0.8.10; /* Library Imports */ import { AddressAliasHelper -} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +} from "../../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; /** * @title DepositFeed * @notice Implements the logic for depositing from L1 to L2. */ -contract DepositFeed { +abstract contract DepositFeed { /********** * Errors * **********/ diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol new file mode 100644 index 000000000000..d47aafbed4b9 --- /dev/null +++ b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol @@ -0,0 +1,146 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/* Interactions Imports */ +import { L2OutputOracle } from "../L2OutputOracle.sol"; + +/* Library Imports */ +import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; + +/** + * @title WithdrawalsRelay + * @notice The WithdrawalsRelay is inherited by the OptimismPortal on L1, and faciliates finalizing + * withdrawals between L2 and L1. + */ +abstract contract WithdrawalsRelay { + /********** + * Errors * + **********/ + + /// @notice Error emitted when attempting to finalize a withdrawal too early. + error NotYetFinal(); + + /// @notice Error emitted when the output root proof is invalid. + error InvalidOutputRootProof(); + + /// @notice Error emitted when the withdrawal inclusion proof is invalid. + error InvalidWithdrawalInclusionProof(); + + /// @notice Error emitted when a withdrawal has already been finalized. + error WithdrawalAlreadyFinalized(); + + /********** + * Events * + **********/ + + /// @notice Emitted when a withdrawal is finalized + event WithdrawalFinalized(bytes32 indexed); + + /// @notice Value used to reset the l2Sender, this is more efficient than setting it to zero. + address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; + + /********************** + * Contract Variables * + **********************/ + + /// @notice Minimum time that must elapse before a withdrawal can be finalized. + uint256 public immutable FINALIZATION_PERIOD; + + /// @notice Address of the L2OutputOracle. + L2OutputOracle public immutable L2_ORACLE; + + /** + * @notice Public variable which can be used to read the address of the L2 account which + * initated the withdrawal. Can also be used to determine whether or not execution is occuring + * downstream of a call to finalizeWithdrawalTransaction(). + */ + address public l2Sender = DEFAULT_L2_SENDER; + + /** + * @notice A list of withdrawal hashes which have been successfully finalized. + * Used for replay protection. + */ + mapping(bytes32 => bool) public finalizedWithdrawals; + + /*************** + * Constructor * + ***************/ + + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) { + L2_ORACLE = _l2Oracle; + FINALIZATION_PERIOD = _finalizationPeriod; + } + + /********************** + * External Functions * + **********************/ + + /** + * @notice Finalizes a withdrawal transaction. + * @param _nonce Nonce for the provided message. + * @param _sender Message sender address on L2. + * @param _target Target address on L1. + * @param _value ETH to send to the target. + * @param _data Data to send to the target. + * @param _gasLimit Gas to be forwarded to the target. + * @param _timestamp L2 timestamp of the outputRoot. + * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. + * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. + */ + function finalizeWithdrawalTransaction( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes calldata _data, + uint256 _timestamp, + WithdrawalVerifier.OutputRootProof calldata _outputRootProof, + bytes calldata _withdrawalProof + ) external { + // Check that the timestamp is 7 days old. + unchecked { + if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { + revert NotYetFinal(); + } + } + + // Get the output root. + bytes32 outputRoot = L2_ORACLE.getL2Output(_timestamp); + + // Verify that the output root can be generated with the elements in the proof. + if (outputRoot != WithdrawalVerifier._deriveOutputRoot(_outputRootProof)) { + revert InvalidOutputRootProof(); + } + + // Verify that the hash of the withdrawal transaction's arguments are included in the + // storage hash of the withdrawer contract. + bytes32 withdrawalHash = keccak256( + abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) + ); + if ( + WithdrawalVerifier._verifyWithdrawalInclusion( + withdrawalHash, + _outputRootProof.withdrawerStorageRoot, + _withdrawalProof + ) == false + ) { + revert InvalidWithdrawalInclusionProof(); + } + + // Check that this withdrawal has not already been finalized. + if (finalizedWithdrawals[withdrawalHash] == true) { + revert WithdrawalAlreadyFinalized(); + } + + l2Sender = _sender; + // Make the call. + _target.call{ value: _value, gas: _gasLimit }(_data); + l2Sender = DEFAULT_L2_SENDER; + + // All withdrawals are immediately finalized. If the ability to replay a transaction is + // required, that support can be provided in external contracts. + finalizedWithdrawals[withdrawalHash] = true; + emit WithdrawalFinalized(withdrawalHash); + } +} diff --git a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol similarity index 92% rename from packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol rename to packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol index 13cc90be96a0..d86bd8833162 100644 --- a/packages/contracts/contracts/L1/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol @@ -1,13 +1,10 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -/* Interactions Imports */ -import { L2OutputOracle } from "./L2OutputOracle.sol"; - /* Library Imports */ import { Lib_SecureMerkleTrie -} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; +} from "../../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; /** * @title WithdrawalVerifier diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol index 5b699cbeed95..5d1fcc467217 100644 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -1,14 +1,20 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +/* Testing utilities */ import { DSTest } from "../../lib/ds-test/src/test.sol"; import { Vm } from "../../lib/forge-std/src/Vm.sol"; -import { DepositFeed } from "../L1/DepositFeed.sol"; +/* Library Imports */ import { AddressAliasHelper } from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +/* Target contract */ +import { DepositFeed } from "../L1/abstracts/DepositFeed.sol"; + +contract Target is DepositFeed {} + contract DepositFeedTest is DSTest { Vm vm = Vm(HEVM_ADDRESS); address immutable ZERO_ADDRESS = address(0); @@ -18,7 +24,7 @@ contract DepositFeedTest is DSTest { uint256 immutable NON_ZERO_GASLIMIT = 50000; bytes NON_ZERO_DATA = hex"1111"; - DepositFeed df; + Target df; event TransactionDeposited( address indexed from, @@ -31,7 +37,7 @@ contract DepositFeedTest is DSTest { ); function setUp() external { - df = new DepositFeed(); + df = new Target(); } // Test: depositTransaction fails when contract creation has a non-zero destination address diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index e5a8203966d3..50ea6c93ef21 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -4,16 +4,14 @@ pragma solidity 0.8.10; /* Testing utilities */ import { DSTest } from "../../lib/ds-test/src/test.sol"; import { Vm } from "../../lib/forge-std/src/Vm.sol"; -import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; /* Target contract dependencies */ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -import { WithdrawalVerifier } from "../L1/Lib_WithdrawalVerifier.sol"; /* Target contract */ import { OptimismPortal } from "../L1/OptimismPortal.sol"; -contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { +contract OptimismPortal_Test is DSTest { event TransactionDeposited( address indexed from, address indexed to, @@ -31,145 +29,13 @@ contract OptimismPortal_finalizeWithdrawalTransaction_Test is DSTest { // Dependencies L2OutputOracle oracle; - // Oracle constructor arguments - address sequencer = 0x000000000000000000000000000000000000AbBa; - uint256 submissionInterval = 1800; - uint256 l2BlockTime = 2; - bytes32 genesisL2Output = keccak256(abi.encode(0)); - uint256 historicalTotalBlocks = 100; - - // Test target OptimismPortal op; - // Target constructor arguments - address withdrawalsPredeploy = 0x4200000000000000000000000000000000000016; - - // Cache of timestamps - uint256 startingBlockTimestamp; - uint256 appendedTimestamp; - - // By default the first block has timestamp zero, which will cause underflows in the tests, - // so we jump ahead to the exact time that I wrote this line. - uint256 initTime = 1648757197; - - // Withdrawal call parameters - uint256 wdNonce = 0; - address wdSender = 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5; - address wdTarget = 0x1111111111111111111111111111111111111111; - uint256 wdValue = 0; - uint256 wdGasLimit = 50_000; - bytes wdData = - hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - - // Generate an output that we can work with. We can use whatever values we want - // except for the withdrawerStorageRoot. This one was generated by running the withdrawer.spec.ts - // test script against Geth. - bytes32 version = bytes32(hex"00"); - bytes32 stateRoot = keccak256(abi.encode(1)); - bytes32 withdrawerStorageRoot = - 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; // eth_getProof (storageHash) - bytes32 latestBlockhash = keccak256(abi.encode(2)); - - // This proof was generated by running - // make devnet-up - // Then in another terminal - // packages/contracts/test/withdrawer.spec.ts - // Invalid large internal hash - bytes withdrawalProof = - hex"f879b853f8518080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28808080808080a0fc935bb380a99df15c4aae91dacba616986d33af599d458d5388fa5fec3ac80780808080808080a3e2a036125dacbefad1d42a65c3425f7b5c8b559dac475adb31578315e77ec70a3f9701"; - - // we'll set this value in the `setUp` function and cache it here for reuse in each test - WithdrawalVerifier.OutputRootProof outputRootProof; - - constructor() { - // Move time forward so we have a non-zero starting timestamp - vm.warp(initTime); - - // Deploy the L2OutputOracle and transfer owernship to the sequencer - oracle = new L2OutputOracle( - submissionInterval, - l2BlockTime, - genesisL2Output, - historicalTotalBlocks, - sequencer - ); - startingBlockTimestamp = block.timestamp; - - op = new OptimismPortal(oracle, 7 days); - } - function setUp() external { - vm.warp(initTime); - bytes32 outputRoot = keccak256( - abi.encode(version, stateRoot, withdrawerStorageRoot, latestBlockhash) - ); - - uint256 nextTimestamp = oracle.nextTimestamp(); - // Warp to 1 second after the timestamp we'll append - vm.warp(nextTimestamp + 1); - vm.prank(sequencer); - oracle.appendL2Output(outputRoot, nextTimestamp, 0, 0); - - // cache the appendedTimestamp - appendedTimestamp = nextTimestamp; - outputRootProof = WithdrawalVerifier.OutputRootProof({ - version: version, - stateRoot: stateRoot, - withdrawerStorageRoot: withdrawerStorageRoot, - latestBlockhash: latestBlockhash - }); - } - - function test_verifyWithdrawal() external { - // Warp to after the finality window - vm.warp(appendedTimestamp + 7 days); - op.finalizeWithdrawalTransaction( - wdNonce, - wdSender, - wdTarget, - wdValue, - wdGasLimit, - wdData, - appendedTimestamp, - outputRootProof, - withdrawalProof - ); - } - - function test_cannotVerifyRecentWithdrawal() external { - // This call should fail because the output root we're using was appended 1 second ago. - vm.expectRevert(abi.encodeWithSignature("NotYetFinal()")); - op.finalizeWithdrawalTransaction( - wdNonce, - wdSender, - wdTarget, - wdValue, - wdGasLimit, - wdData, - appendedTimestamp, - outputRootProof, - hex"ffff" - ); + // Oracle value is zero, but this test does not depend on it. + op = new OptimismPortal(oracle, 7 days); } - function test_cannotVerifyInvalidProof() external { - // This call should fail because the output proof is modified - vm.warp(appendedTimestamp + 7 days); - vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); - WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; - invalidOutpuRootProof.latestBlockhash = 0; - op.finalizeWithdrawalTransaction( - wdNonce, - wdSender, - wdTarget, - wdValue, - wdGasLimit, - wdData, - appendedTimestamp, - invalidOutpuRootProof, - hex"ffff" - ); - } function test_receive_withEthValueFromEOA() external { // EOA emulation diff --git a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol new file mode 100644 index 000000000000..544c66d9bb6c --- /dev/null +++ b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol @@ -0,0 +1,179 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/* Testing utilities */ +import { DSTest } from "../../lib/ds-test/src/test.sol"; +import { Vm } from "../../lib/forge-std/src/Vm.sol"; + +/* Target contract dependencies */ +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { WithdrawalVerifier } from "../L1/libraries/Lib_WithdrawalVerifier.sol"; + +/* Target contract */ +import { WithdrawalsRelay } from "../L1/abstracts/WithdrawalsRelay.sol"; + + +contract Target is WithdrawalsRelay { + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) + WithdrawalsRelay(_l2Oracle, _finalizationPeriod) + {} +} + +contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is DSTest { + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 mint, + uint256 value, + uint256 gasLimit, + bool isCreation, + bytes data + ); + + // Utilities + Vm vm = Vm(HEVM_ADDRESS); + bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); + + // Dependencies + L2OutputOracle oracle; + + // Oracle constructor arguments + address sequencer = 0x000000000000000000000000000000000000AbBa; + uint256 submissionInterval = 1800; + uint256 l2BlockTime = 2; + bytes32 genesisL2Output = keccak256(abi.encode(0)); + uint256 historicalTotalBlocks = 100; + + // Test target + Target wr; + + // Target constructor arguments + address withdrawalsPredeploy = 0x4200000000000000000000000000000000000015; + + // Cache of timestamps + uint256 startingBlockTimestamp; + uint256 appendedTimestamp; + + // By default the first block has timestamp zero, which will cause underflows in the tests, + // so we jump ahead to the exact time that I wrote this line. + uint256 initTime = 1648757197; + + // Withdrawal call parameters + uint256 wdNonce = 0; + address wdSender = 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5; + address wdTarget = 0x1111111111111111111111111111111111111111; + uint256 wdValue = 0; + uint256 wdGasLimit = 50_000; + bytes wdData = + hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; + + // Generate an output that we can work with. We can use whatever values we want + // except for the withdrawerStorageRoot. This one was generated by running the withdrawer.spec.ts + // test script against Geth. + bytes32 version = bytes32(hex"00"); + bytes32 stateRoot = keccak256(abi.encode(1)); + bytes32 withdrawerStorageRoot = + 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; // eth_getProof (storageHash) + bytes32 latestBlockhash = keccak256(abi.encode(2)); + + // This proof was generated by running + // make devnet-up + // Then in another terminal + // packages/contracts/test/withdrawer.spec.ts + // Invalid large internal hash + bytes withdrawalProof = + hex"f879b853f8518080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28808080808080a0fc935bb380a99df15c4aae91dacba616986d33af599d458d5388fa5fec3ac80780808080808080a3e2a036125dacbefad1d42a65c3425f7b5c8b559dac475adb31578315e77ec70a3f9701"; + + // we'll set this value in the `setUp` function and cache it here for reuse in each test + WithdrawalVerifier.OutputRootProof outputRootProof; + + constructor() { + // Move time forward so we have a non-zero starting timestamp + vm.warp(initTime); + + // Deploy the L2OutputOracle and transfer owernship to the sequencer + oracle = new L2OutputOracle( + submissionInterval, + l2BlockTime, + genesisL2Output, + historicalTotalBlocks, + sequencer + ); + startingBlockTimestamp = block.timestamp; + + wr = new Target(oracle, 7 days); + } + + function setUp() external { + vm.warp(initTime); + bytes32 outputRoot = keccak256( + abi.encode(version, stateRoot, withdrawerStorageRoot, latestBlockhash) + ); + + uint256 nextTimestamp = oracle.nextTimestamp(); + // Warp to 1 second after the timestamp we'll append + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); + oracle.appendL2Output(outputRoot, nextTimestamp, 0, 0); + + // cache the appendedTimestamp + appendedTimestamp = nextTimestamp; + outputRootProof = WithdrawalVerifier.OutputRootProof({ + version: version, + stateRoot: stateRoot, + withdrawerStorageRoot: withdrawerStorageRoot, + latestBlockhash: latestBlockhash + }); + } + + function test_verifyWithdrawal() external { + // Warp to after the finality window + vm.warp(appendedTimestamp + 7 days); + wr.finalizeWithdrawalTransaction( + wdNonce, + wdSender, + wdTarget, + wdValue, + wdGasLimit, + wdData, + appendedTimestamp, + outputRootProof, + withdrawalProof + ); + } + + function test_cannotVerifyRecentWithdrawal() external { + // This call should fail because the output root we're using was appended 1 second ago. + vm.expectRevert(abi.encodeWithSignature("NotYetFinal()")); + wr.finalizeWithdrawalTransaction( + wdNonce, + wdSender, + wdTarget, + wdValue, + wdGasLimit, + wdData, + appendedTimestamp, + outputRootProof, + hex"ffff" + ); + } + + function test_cannotVerifyInvalidProof() external { + // This call should fail because the output proof is modified + vm.warp(appendedTimestamp + 7 days); + vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); + WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; + invalidOutpuRootProof.latestBlockhash = 0; + wr.finalizeWithdrawalTransaction( + wdNonce, + wdSender, + wdTarget, + wdValue, + wdGasLimit, + wdData, + appendedTimestamp, + invalidOutpuRootProof, + hex"ffff" + ); + } +} From 8c309996407f0e58c40c72a6b16dffba96deedfe Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 14:01:33 -0400 Subject: [PATCH 433/585] contracts: Move withdrawal hashing logic into library --- .../L1/abstracts/WithdrawalsRelay.sol | 11 +++++++--- .../L1/libraries/Lib_WithdrawalVerifier.sol | 20 +++++++++++++++++++ .../contracts/contracts/test/Withdrawer.t.sol | 1 - 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol index d47aafbed4b9..7808645cf8fd 100644 --- a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol +++ b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol @@ -81,8 +81,8 @@ abstract contract WithdrawalsRelay { * @param _sender Message sender address on L2. * @param _target Target address on L1. * @param _value ETH to send to the target. - * @param _data Data to send to the target. * @param _gasLimit Gas to be forwarded to the target. + * @param _data Data to send to the target. * @param _timestamp L2 timestamp of the outputRoot. * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. @@ -115,8 +115,13 @@ abstract contract WithdrawalsRelay { // Verify that the hash of the withdrawal transaction's arguments are included in the // storage hash of the withdrawer contract. - bytes32 withdrawalHash = keccak256( - abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data) + bytes32 withdrawalHash = WithdrawalVerifier._deriveWithdrawalHash( + _nonce, + _sender, + _target, + _value, + _gasLimit, + _data ); if ( WithdrawalVerifier._verifyWithdrawalInclusion( diff --git a/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol index d86bd8833162..605a8223b325 100644 --- a/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol @@ -19,6 +19,26 @@ library WithdrawalVerifier { bytes32 latestBlockhash; } + /** + * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract + * @param _nonce Nonce for the provided message. + * @param _sender Message sender address on L2. + * @param _target Target address on L1. + * @param _value ETH to send to the target. + * @param _gasLimit Gas to be forwarded to the target. + * @param _data Data to send to the target. + */ + function _deriveWithdrawalHash( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes calldata _data + ) external pure returns (bytes32) { + return keccak256(abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data)); + } + /** * @notice Derives the output root corresponding to the elements provided in the proof. * @param _outputRootProof The elements which were hashed together to generate the output root. diff --git a/packages/contracts/contracts/test/Withdrawer.t.sol b/packages/contracts/contracts/test/Withdrawer.t.sol index 0a3a85e5bf92..3836e79df8d4 100644 --- a/packages/contracts/contracts/test/Withdrawer.t.sol +++ b/packages/contracts/contracts/test/Withdrawer.t.sol @@ -108,5 +108,4 @@ contract WithdawerBurnTest is WithdrawerTestCommon { // The Withdrawer should have no balance assertEq(address(wd).balance, 0); } - } From ec1cc88f73f2147fc23aa7df829db75f6d46bba7 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 14:54:23 -0400 Subject: [PATCH 434/585] contracts: Update .gas-snapshot --- packages/contracts/.gas-snapshot | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 50e05d3300cf..7fad498aa87b 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,12 +1,12 @@ -DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11352) -DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 21076) +DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11233) +DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 20962) DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 21427) -DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 21094) +DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 20980) DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 21467) -DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 28117) -DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 25856) -DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 27785) -DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 25817) +DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 28003) +DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 25031) +DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 27671) +DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 28407) L1BLockTest:test_basefee() (gas: 7509) L1BLockTest:test_hash() (gas: 7508) L1BLockTest:test_number() (gas: 7509) @@ -18,8 +18,15 @@ L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18307) L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21227) L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13090) L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49528) -L2OutputOracleTest:test_computeL2BlockNumber() (gas: 15556) +L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14893) L2OutputOracleTest:test_getL2Output() (gas: 15073) L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9610) L2OutputOracleTest:test_nextTimestamp() (gas: 11943) L2OutputOracleTest_Constructor:test_constructor() (gas: 29122) +OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24175) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43988) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 203784) +WithdawerBurnTest:test_burn() (gas: 50289) +WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71947) +WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72412) From 2084c0252688ab84f4d4b55c75eab919d023ee64 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 15:13:49 -0400 Subject: [PATCH 435/585] contracts: silence compiler warnings --- .../contracts/contracts/L1/abstracts/WithdrawalsRelay.sol | 3 ++- packages/contracts/contracts/L2/Withdrawer.sol | 2 +- packages/contracts/contracts/test/OptimismPortal.t.sol | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol index 7808645cf8fd..0b36d92d3d55 100644 --- a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol +++ b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol @@ -140,7 +140,8 @@ abstract contract WithdrawalsRelay { l2Sender = _sender; // Make the call. - _target.call{ value: _value, gas: _gasLimit }(_data); + (bool s, ) = _target.call{ value: _value, gas: _gasLimit }(_data); + s; // Silence the compiler's "Return value of low-level calls not used" warning. l2Sender = DEFAULT_L2_SENDER; // All withdrawals are immediately finalized. If the ability to replay a transaction is diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 32c18145e339..dc01de87b18e 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -89,7 +89,7 @@ contract Withdrawer { */ function burn() external { uint256 balance = address(this).balance; - Burner burner = new Burner{ value: balance }(); + new Burner{ value: balance }(); emit WithdrawerBalanceBurnt(balance); } } diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index 50ea6c93ef21..fbcbdedddd69 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -36,14 +36,15 @@ contract OptimismPortal_Test is DSTest { op = new OptimismPortal(oracle, 7 days); } - function test_receive_withEthValueFromEOA() external { // EOA emulation vm.prank(address(this), address(this)); vm.expectEmit(true, true, false, true); emit TransactionDeposited(address(this), address(this), 100, 100, 30_000, false, hex""); - address(op).call{ value: 100 }(hex""); + + (bool s, ) = address(op).call{ value: 100 }(hex""); + s; // Silence the compiler's "Return value of low-level calls not used" warning. assertEq(address(op).balance, 100); } From 891d5c3021af5a2892d307887d9d1b15535abd6e Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Thu, 7 Apr 2022 10:18:35 -0700 Subject: [PATCH 436/585] feat: expose debug http api (#334) --- ops/entrypoint.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ops/entrypoint.sh b/ops/entrypoint.sh index de5c25039465..6c318dd097fb 100644 --- a/ops/entrypoint.sh +++ b/ops/entrypoint.sh @@ -39,6 +39,7 @@ exec geth \ --http.vhosts="*" \ --http.addr=0.0.0.0 \ --http.port=8545 \ + --http.api=debug,eth,txpool,net,engine \ --ws \ --ws.addr=0.0.0.0 \ --ws.port=8546 \ @@ -53,4 +54,4 @@ exec geth \ --miner.etherbase=$BLOCK_SIGNER_ADDRESS \ --password="$GETH_DATA_DIR"/password \ --allow-insecure-unlock \ - "$@" \ No newline at end of file + "$@" From b1f74f5d0fbbc96490e8ad6a0e040ebb305e4132 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 7 Apr 2022 10:32:46 -0700 Subject: [PATCH 437/585] opnode: Use l2 safe head instead of l2 head Epochs should be inserted on top of the L2 Safe Head, not the unsafe head. This was causing problems when a reorg would occur and the node would start building in the wrong spot. --- opnode/rollup/driver/state.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 0424d13c2ac2..0cbdaab30a13 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -109,7 +109,7 @@ func (s *state) Close() error { // This is either the last block of the window, or the L1 base block if the window is not populated. func (s *state) l1WindowBufEnd() eth.BlockID { if len(s.l1WindowBuf) == 0 { - return s.l2Head.L1Origin + return s.l2SafeHead.L1Origin } return s.l1WindowBuf[len(s.l1WindowBuf)-1] } @@ -364,7 +364,7 @@ func (s *state) loop() { } // Run step if we are able to if s.l1Head.Number-s.l2SafeHead.L1Origin.Number >= s.Config.SeqWindowSize { - s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) + s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2SafeHead.L1Origin) requestStep() } case <-stepRequest: @@ -382,8 +382,8 @@ func (s *state) loop() { } // Immediately run next step if we have enough blocks. - if s.l1Head.Number-s.l2Head.L1Origin.Number >= s.Config.SeqWindowSize { - s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin) + if s.l1Head.Number-s.l2SafeHead.L1Origin.Number >= s.Config.SeqWindowSize { + s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2SafeHead.L1Origin) requestStep() } } From cc9cd72bb60b5c6e1d8cdebb37d92ba5d5cdaf82 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 7 Apr 2022 10:35:40 -0700 Subject: [PATCH 438/585] opnode: Clear l1WindowBuf on insertEpoch failure This is done to handle the case that the l1WindowBuf does not start in the correct location (direct check is difficult with context). The correct response to that is to clear the window and initialize it from the correct block. --- opnode/rollup/driver/state.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 0cbdaab30a13..c1cb7a73cf4d 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -289,6 +289,9 @@ func (s *state) handleEpoch(ctx context.Context) (bool, error) { newL2Head, newL2SafeHead, reorg, err := s.output.insertEpoch(ctx, s.l2Head, s.l2SafeHead, s.l2Finalized, window) cancel() if err != nil { + // Cannot easily check that s.l1WindowBuf[0].ParentHash == s.l2Safehead.L1Origin.Hash in this function, so if insertEpoch + // may have found a problem with that, clear the buffer and try again later. + s.l1WindowBuf = nil s.log.Error("Error in running the output step.", "err", err, "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead) return false, err } From 279d04a6183cbb9403107c9d50a76c25d9c075df Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Thu, 7 Apr 2022 11:19:08 -0700 Subject: [PATCH 439/585] hardhat: clean up the hardhat deposit task --- packages/contracts/tasks/deposits.ts | 37 ++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/packages/contracts/tasks/deposits.ts b/packages/contracts/tasks/deposits.ts index 6d547e03f225..7d194b685beb 100644 --- a/packages/contracts/tasks/deposits.ts +++ b/packages/contracts/tasks/deposits.ts @@ -2,27 +2,50 @@ import { task, types } from 'hardhat/config' import { Contract, providers, utils, Wallet } from 'ethers' import dotenv from 'dotenv' +dotenv.config() + task('deposit', 'Deposits funds onto L2.') - .addParam('l1ProviderUrl', 'L1 provider URL.', null, types.string) + .addParam( + 'l1ProviderUrl', + 'L1 provider URL.', + 'http://localhost:8545', + types.string + ) .addParam('to', 'Recipient address.', null, types.string) .addParam('amountEth', 'Amount in ETH to send.', null, types.string) + .addOptionalParam( + 'privateKey', + 'Private key to send transaction', + process.env.PRIVATE_KEY, + types.string + ) .addOptionalParam( 'depositContractAddr', 'Address of deposit contract.', 'deaddeaddeaddeaddeaddeaddeaddeaddead0001', types.string ) - .setAction(async ({ l1ProviderUrl, to, amountEth, depositContractAddr }) => { + .setAction(async (args) => { + const { l1ProviderUrl, to, amountEth, depositContractAddr, privateKey } = + args const depositFeedArtifact = require('../artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json') - dotenv.config() + const l1Provider = new providers.JsonRpcProvider(l1ProviderUrl) - if (!process.env.PRIVATE_KEY) { - throw new Error('You must define PRIVATE_KEY in your environment.') + let l1Wallet: Wallet | providers.JsonRpcSigner + if (privateKey) { + l1Wallet = new Wallet(privateKey, l1Provider) + } else { + l1Wallet = l1Provider.getSigner() + } + + const from = await l1Wallet.getAddress() + console.log(`Sending from ${from}`) + const balance = await l1Wallet.getBalance() + if (balance.eq(0)) { + throw new Error(`${from} has no balance`) } - const l1Provider = new providers.JsonRpcProvider(l1ProviderUrl) - const l1Wallet = new Wallet(process.env.PRIVATE_KEY!, l1Provider) const depositFeed = new Contract( depositContractAddr, depositFeedArtifact.abi From 7d1fa949cb6d5c159448e093521aab1e6c4c98e5 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Thu, 7 Apr 2022 14:34:52 -0400 Subject: [PATCH 440/585] fix: oe => optimism (#338) --- specs/introduction.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/introduction.md b/specs/introduction.md index 133804888463..aff5cf187b7e 100644 --- a/specs/introduction.md +++ b/specs/introduction.md @@ -1,4 +1,4 @@ -# Optimistic Ethereum Introduction +# Introduction @@ -52,7 +52,7 @@ anywhere. ### 🎶 All together now 🎶 -**Optimistic Ethereum is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_.** +**Optimism is an _EVM equivalent_, _optimistic rollup_ protocol designed to _scale Ethereum_.** ## Protocol Guarantees @@ -77,7 +77,7 @@ proofs can also be plugged in once they have been made feasible. ## Network Participants -There are three actors in Optimistic Ethereum: users, sequencers, and verifiers. +There are three actors in Optimism: users, sequencers, and verifiers. ![Network Overview](./assets/network-participants-overview.svg) @@ -126,7 +126,7 @@ provide context when diving into any particular component specification. ### Depositing and Sending Transactions Users will often begin their L2 journey by depositing ETH from L1. Once they have ETH to pay fees, they'll start -sending transactions on L2. The following diagram demonstrates this interaction and all key Optimistic Ethereum +sending transactions on L2. The following diagram demonstrates this interaction and all key Optimism components which are utilized: ![Diagram of Depositing and Sending Transactions](./assets/sequencer-handling-deposits-and-transactions.svg) From 19b57235c34107594261c9269607f7a475c8ace5 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 7 Apr 2022 11:01:05 -0700 Subject: [PATCH 441/585] opnode: Rework state test to build on safe head This also got caught up in the unsafe/safe head confusion. --- opnode/rollup/driver/state_test.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index f8d8b1ba2314..118ac796be09 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -102,7 +102,7 @@ func advanceL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo assert.Equal(t, int(s.Config.SeqWindowSize), len(args.l1Window), "Invalid L1 window size") assert.Equal(t, len(expectedWindow), len(args.l1Window), "L1 Window size does not match expectedWindow") for i := range expectedWindow { - assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") + assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match in advancing L2 in window element %d", i) } outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} } @@ -112,7 +112,7 @@ func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo assert.Equal(t, int(s.Config.SeqWindowSize), len(args.l1Window), "Invalid L1 window size") assert.Equal(t, len(expectedWindow), len(args.l1Window), "L1 Window size does not match expectedWindow") for i := range expectedWindow { - assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match") + assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match on reorg in window element %d", i) } outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} @@ -136,7 +136,7 @@ func (tc *stateTestCase) Run(t *testing.T) { outputReturn := make(chan outputReturnArgs) outputHandler := func(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) { // TODO: Not sequencer, but need to pass unsafeL2Head here for the test. - outputIn <- outputArgs{l2Head: l2Head.ID(), l2Finalized: l2Finalized, l1Window: l1Input} + outputIn <- outputArgs{l2Head: l2SafeHead.ID(), l2Finalized: l2Finalized, l1Window: l1Input} r := <-outputReturn return r.l2Head, r.l2Head, false, r.err } @@ -159,7 +159,7 @@ func (tc *stateTestCase) Run(t *testing.T) { <-time.After(5 * time.Millisecond) assert.Equal(t, step.l1head.ID(), state.l1Head.ID(), "l1 head") - assert.Equal(t, step.l2head.ID(), state.l2SafeHead.ID(), "l2 head") + assert.Equal(t, step.l2head.ID(), state.l2SafeHead.ID(), "l2 safe head") } } @@ -183,8 +183,8 @@ func TestDriver(t *testing.T) { }, { name: "Reorg", - l1Chains: []string{"abcdefg", "abcxyzw"}, - l2Chains: []string{"ABCDEF", "ABCXYZ"}, + l1Chains: []string{"abcdefg", "abcwxyz"}, + l2Chains: []string{"ABCDEF", "ABCWXY"}, seqWindow: 2, genesis: fakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ @@ -195,11 +195,11 @@ func TestDriver(t *testing.T) { {l1act: advanceL1, l2act: advanceL2, l1head: "e:4", l2head: "D:3", window: []testID{"d:3", "e:4"}}, {l1act: advanceL1, l2act: advanceL2, l1head: "f:5", l2head: "E:4", window: []testID{"e:4", "f:5"}}, {l1act: advanceL1, l2act: advanceL2, l1head: "g:6", l2head: "F:5", window: []testID{"f:5", "g:6"}}, - {l1act: stutterL1, l2act: reorg__L2, l1head: "w:6", l2head: "X:3", window: []testID{"x:3", "y:4"}, reorg: true}, - {l1act: stutterL1, l2act: advanceL2, l1head: "w:6", l2head: "Y:4", window: []testID{"y:4", "z:5"}}, - {l1act: stutterL1, l2act: advanceL2, l1head: "w:6", l2head: "Z:5", window: []testID{"z:5", "w:6"}}, - {l1act: stutterL1, l2act: stutterL2, l1head: "w:6", l2head: "Z:5", window: []testID{"z:5", "w:6"}}, - {l1act: stutterL1, l2act: stutterL2, l1head: "w:6", l2head: "Z:5", window: []testID{"z:5", "w:6"}}, + {l1act: stutterL1, l2act: reorg__L2, l1head: "z:6", l2head: "C:2", window: []testID{"c:2", "w:3"}, reorg: true}, + {l1act: stutterL1, l2act: advanceL2, l1head: "z:6", l2head: "W:3", window: []testID{"w:3", "x:4"}}, + {l1act: stutterL1, l2act: advanceL2, l1head: "z:6", l2head: "X:4", window: []testID{"x:4", "y:5"}}, + {l1act: stutterL1, l2act: advanceL2, l1head: "z:6", l2head: "Y:5", window: []testID{"y:5", "z:6"}}, + {l1act: stutterL1, l2act: stutterL2, l1head: "z:6", l2head: "Y:5", window: []testID{}}, }, }, { From 1dad265a93d4ce60cc0e7fec4b845bb71460fe25 Mon Sep 17 00:00:00 2001 From: Murphy Law Date: Thu, 7 Apr 2022 14:49:12 -0400 Subject: [PATCH 442/585] opnode: fix setL1BlockValues selector used for deposits (#339) Solidity ABI only looks at the function name and types, but does not consider the name of the function parameters. --- opnode/rollup/derive/payload_attributes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 5d442e5d9481..5f57d3e64fed 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -20,7 +20,7 @@ var ( DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint256,bool,bytes)" DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) DepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") - L1InfoFuncSignature = "setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash)" + L1InfoFuncSignature = "setL1BlockValues(uint256,uint256,uint256,bytes32)" L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] L1InfoPredeployAddr = common.HexToAddress("0x4242424242424242424242424242424242424242") ) From 1a353bd8666b824cb79483c854faf421100f1fa6 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 6 Apr 2022 23:28:50 -0400 Subject: [PATCH 443/585] rollup: fix address of the L1 Block Attributes contracts --- opnode/rollup/derive/payload_attributes.go | 2 +- opnode/test/system_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 5d442e5d9481..2b75c01e169b 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -22,7 +22,7 @@ var ( DepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") L1InfoFuncSignature = "setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash)" L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] - L1InfoPredeployAddr = common.HexToAddress("0x4242424242424242424242424242424242424242") + L1InfoPredeployAddr = common.HexToAddress("0x4200000000000000000000000000000000000015") ) // UnmarshalLogEvent decodes an EVM log entry emitted by the deposit contract into typed deposit data. diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 5077eb489dd0..9a1c1c9bdf11 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -98,7 +98,7 @@ func TestSystemE2E(t *testing.T) { }, cliqueSigners: []string{"m/44'/60'/0'/0/0"}, depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - l1InforPredeployAddress: "0x4242424242424242424242424242424242424242", + l1InforPredeployAddress: "0x4200000000000000000000000000000000000015", } // Create genesis & assign it to ethconfigs initializeGenesis(cfg) From 776017b3f924b4b4591c5bd3f07871efe4116f70 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 7 Apr 2022 10:22:06 -0400 Subject: [PATCH 444/585] fix: typo in l1InfoPredeployAddress --- opnode/test/setup.go | 4 ++-- opnode/test/system_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index b2efdf2760ea..bc63eeeb7c18 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -49,7 +49,7 @@ type systemConfig struct { premine map[string]int // Derivation path -> amount in ETH (not wei) cliqueSigners []string // derivation path depositContractAddress string - l1InforPredeployAddress string + l1InfoPredeployAddress string wallet *hdwallet.Wallet } @@ -101,7 +101,7 @@ func initializeGenesis(cfg *systemConfig) { } l1Alloc[common.HexToAddress(cfg.depositContractAddress)] = core.GenesisAccount{Code: common.FromHex(deposit.DepositDeployedBin), Balance: common.Big0} - l2Alloc[common.HexToAddress(cfg.l1InforPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} + l2Alloc[common.HexToAddress(cfg.l1InfoPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} genesisTimestamp := uint64(time.Now().Unix()) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 9a1c1c9bdf11..cb357269669d 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -98,7 +98,7 @@ func TestSystemE2E(t *testing.T) { }, cliqueSigners: []string{"m/44'/60'/0'/0/0"}, depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - l1InforPredeployAddress: "0x4200000000000000000000000000000000000015", + l1InfoPredeployAddress: "0x4200000000000000000000000000000000000015", } // Create genesis & assign it to ethconfigs initializeGenesis(cfg) From ee7250e0950ca9174311b2f3c1dec84aa752253e Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 7 Apr 2022 11:51:15 -0700 Subject: [PATCH 445/585] fix: gofmt and goimports CI was asking for goimport'd when all it needed was gofmt. --- opnode/test/setup.go | 16 ++++++++-------- opnode/test/system_test.go | 7 +++---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index bc63eeeb7c18..3d370f267f6b 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -42,15 +42,15 @@ type gethConfig struct { // systemConfig holds the information necessary to create a L1 <-> Rollup <-> L2 system type systemConfig struct { - mnemonic string - l1 gethConfig - l2Verifier gethConfig - l2Sequencer gethConfig - premine map[string]int // Derivation path -> amount in ETH (not wei) - cliqueSigners []string // derivation path - depositContractAddress string + mnemonic string + l1 gethConfig + l2Verifier gethConfig + l2Sequencer gethConfig + premine map[string]int // Derivation path -> amount in ETH (not wei) + cliqueSigners []string // derivation path + depositContractAddress string l1InfoPredeployAddress string - wallet *hdwallet.Wallet + wallet *hdwallet.Wallet } func precompileAlloc() core.GenesisAlloc { diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index cb357269669d..dcb34be2d233 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -8,13 +8,12 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" @@ -96,8 +95,8 @@ func TestSystemE2E(t *testing.T) { l2OutputHDPath: 10000000, bssHDPath: 10000000, }, - cliqueSigners: []string{"m/44'/60'/0'/0/0"}, - depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", + cliqueSigners: []string{"m/44'/60'/0'/0/0"}, + depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", l1InfoPredeployAddress: "0x4200000000000000000000000000000000000015", } // Create genesis & assign it to ethconfigs From b94892d81b97f152233f59ba85417b7ae67a0c58 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 7 Apr 2022 15:27:39 -0400 Subject: [PATCH 446/585] opnode: Import constants --- opnode/test/system_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index dcb34be2d233..6c8f2289738b 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" @@ -96,8 +97,8 @@ func TestSystemE2E(t *testing.T) { bssHDPath: 10000000, }, cliqueSigners: []string{"m/44'/60'/0'/0/0"}, - depositContractAddress: "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - l1InfoPredeployAddress: "0x4200000000000000000000000000000000000015", + depositContractAddress: derive.DepositContractAddr.Hex(), + l1InfoPredeployAddress: derive.L1InfoPredeployAddr.Hex(), } // Create genesis & assign it to ethconfigs initializeGenesis(cfg) From a056280cd1be67275394974a0a2fe7553e636684 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Thu, 7 Apr 2022 10:42:18 -0700 Subject: [PATCH 447/585] ops: fix formatting, add docker buildkit support --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 381bede163a4..ce09c66cce7d 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ devnet-up: DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ WITHDRAWER_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json | jq .deployedBytecode) \ - GENESIS_TIMESTAMP=$(shell date +%s) \ - BUILDKIT_PROGRESS=plain docker-compose up --build) + GENESIS_TIMESTAMP=$(shell date +%s) \ + BUILDKIT_PROGRESS=plain DOCKER_BUILDKIT=1 docker-compose up --build) .PHONY: devnet-up devnet-down: From abcb8df0cae6880cc238efc6f754ecc3df3a018e Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Thu, 7 Apr 2022 10:44:29 -0700 Subject: [PATCH 448/585] ops: prune volumes on devnet-down --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ce09c66cce7d..131473335bab 100644 --- a/Makefile +++ b/Makefile @@ -29,5 +29,5 @@ devnet-up: .PHONY: devnet-up devnet-down: - @(cd ./ops && docker-compose down) + @(cd ./ops && docker-compose down -v) .PHONY: devnet-stop From fb396a4d6148eb04815672b0c08244791229ed8c Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Thu, 7 Apr 2022 16:33:07 -0400 Subject: [PATCH 449/585] fix: replace fraud with fault (#337) --- specs/assets/network-participants-overview.svg | 2 +- .../sequencer-handling-deposits-and-transactions.svg | 2 +- specs/assets/verifier-executing-fraud-proof.svg | 2 +- specs/introduction.md | 10 +++++----- specs/overview.md | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/specs/assets/network-participants-overview.svg b/specs/assets/network-participants-overview.svg index d70a983f7b9d..9eeac12aecc1 100644 --- a/specs/assets/network-participants-overview.svg +++ b/specs/assets/network-participants-overview.svg @@ -1,4 +1,4 @@ -
Ethereum L1 Chain
Ethereum L1 Chain

Network Participants Overview

Network Participants Overview
Query data
(eg. block explorers)
Query data...
Submit transactions
Submit transactions
Submit deposits
Submit deposits
Users
Users
Submit batches and assertions
Submit batches and assertions
P2P Realtime Updates
P2P Realtime Updates
Verifiers
Verifi...
Verify block hash assertions &
submit fraud proofs
Verify block hash assertions &...
Sequencers
Viewer does not support full SVG 1.1
\ No newline at end of file +
Ethereum L1 Chain
Ethereum L1 Chain

Network Participants Overview

Network Participants Overview
Query data
(eg. block explorers)
Query data...
Submit transactions
Submit transactions
Submit deposits
Submit deposits
Users
Users
Submit batches and assertions
Submit batches and assertions
P2P Realtime Updates
P2P Realtime Updates
Verifiers
Verifi...
Verify block hash assertions &
submit fault proofs
Verify block hash assertions &...
Sequencers
Viewer does not support full SVG 1.1
diff --git a/specs/assets/sequencer-handling-deposits-and-transactions.svg b/specs/assets/sequencer-handling-deposits-and-transactions.svg index c6a8b8185125..eea840e1ddc6 100644 --- a/specs/assets/sequencer-handling-deposits-and-transactions.svg +++ b/specs/assets/sequencer-handling-deposits-and-transactions.svg @@ -1,4 +1,4 @@ -
3. Insert deposit block
3. Insert deposit block
Rollup Node
Rollup Node
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to the batch inbox
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the batch inbox.
Queries for all...
Batch Inbox
Batch Inbox

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
L2 Output Submitter
L2 Output Submitter
Queries for the next
assertable block hash &
submits it to the
L2 Output Oracle.
Queries for the next...
L2 Output Oracle
L2 Output Oracle
8. Verify block hash in the fraud proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fraud proof VM...
Text is not SVG - cannot display
\ No newline at end of file +
3. Insert deposit block
3. Insert deposit block
Rollup Node
Rollup Node
2. Get Blocks (including deposit event)
2. Get Blocks (including deposit event)
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Fault Proof VM
Fault Proof VM
Executes blocks in the fault proof VM and
generates witnesses.
Executes blocks in the fault proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine (mining mode)
Execution Engine (mining mode)
(eg. Geth)
(eg. Geth)
Accept transactions, build blocks,
store the chain, serve RPC requests.
Accept transactions, build blocks,...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
4
4
5. Get
latest
sequencer
blocks
5. Get...
6. Submit sequencer blocks
(ie. a batch) to the batch inbox
6. Submit sequencer blocks...
Sequencer
Batch Submitter
Sequencer...
Queries for all
sequencer blocks &
submits them to
the batch inbox.
Queries for all...
Batch Inbox
Batch Inbox

Sequencer Syncing Deposits & Accepting a Transaction 

Sequencer Syncing Deposits & Accepting a Transaction 
RPC
RPC
TxPool
TxPool
4. Send Transaction
4. Send Transaction
1. Submit Deposit
1. Submit Deposit
User
User
Note:  Sequencer will likely run a consensus
protocol not demonstrated in this diagram.
Note:  Sequencer will likely run a consen...
!!
!!
7. Get latest assertable block hash
7. Get latest assertable block hash
9. Submit validated
block hash assertion
9. Submit validated...
L2 Output Submitter
L2 Output Submitter
Queries for the next
assertable block hash &
submits it to the
L2 Output Oracle.
Queries for the next...
L2 Output Oracle
L2 Output Oracle
8. Verify block hash in the fault proof VM
to detect on-chain<->off-chain divergence
8. Verify block hash in the fault proof VM...
Text is not SVG - cannot display
diff --git a/specs/assets/verifier-executing-fraud-proof.svg b/specs/assets/verifier-executing-fraud-proof.svg index 29428313323c..d05881d5c2b9 100644 --- a/specs/assets/verifier-executing-fraud-proof.svg +++ b/specs/assets/verifier-executing-fraud-proof.svg @@ -1,4 +1,4 @@ -
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Node
Rollup Node
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fraud & performs
challenges.
Watches L1 chain for fraud & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fraud Proof VM
Fraud Proof VM
Executes blocks in the fraud proof VM and
generates witnesses.
Executes blocks in the fraud proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 Output Oracle Contract
L2 Output Oracle Contract
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fraud Proof

Verifier Detecting & Executing a Fraud Proof
Text is not SVG - cannot display
\ No newline at end of file +
2. Insert and reorg blocks
2. Insert and reorg blocks
Rollup Node
Rollup Node
1. Get Blocks
1. Get Blocks
Ethereum L1 Chain
Ethereum L1 Chain
Rollup(
Rollup(
)
)
L1
L1
L2
L2
Transform latest L1 blocks
into L2 block inputs
Transform latest L1 blocks...
Execution Engine
Execution Engine
(eg. Geth)
(eg. Geth)
Execute blocks, store the chain,
serve RPC calls.
Execute blocks, store the chai...
EVM
EVM
Chain
Chain
State
State
RPC
RPC
3. Read
BlockHash
Assertion
3. Read...
4. Get
corresponding
block hash
4. Get...
5. Get witness
for invalid assertion
5. Get witness...
6. Isolate disputed
state transition
6. Isolate disputed...
7. Verify disputed
state transition
7. Verify disputed...
Challenger Agent
Challenger Agent
Watches L1 chain for fault & performs
challenges.
Watches L1 chain for fault & perform...
local_blockhash ≠ assertion_blockhash
local_blockhash ≠ assertion_blockhash
Fault Proof VM
Fault Proof VM
Executes blocks in the fault proof VM and
generates witnesses.
Executes blocks in the fault proof VM an...
Data to generate the witnesses
(eg. storage, blocks...)
is fetched from L1 & L2 nodes.
Data to generate the witnesses...
L2 Output Oracle Contract
L2 Output Oracle Contract
k-section
game
k-section...
Single-step
verifier
Single-step...

Verifier Detecting & Executing a Fault Proof

Verifier Detecting & Executing a Fault Proof
Text is not SVG - cannot display
diff --git a/specs/introduction.md b/specs/introduction.md index aff5cf187b7e..83f77c8205ac 100644 --- a/specs/introduction.md +++ b/specs/introduction.md @@ -39,7 +39,7 @@ reducing fees can be achieved by better utilizing bandwidth, computation and sto [Optimistic rollup](https://vitalik.ca/general/2021/01/05/rollup.html) is a layer 2 scalability technique which increases the computation & storage capacity of Ethereum without sacrificing security or decentralization. Transaction -data is submitted on-chain but executed off-chain. If there is an error in the off-chain execution, a fraud proof can +data is submitted on-chain but executed off-chain. If there is an error in the off-chain execution, a fault proof can be submitted on-chain to correct the error and protect user funds. In the same way you don't go to court unless there is a dispute, you don't execute transactions on on-chain unless there is an error. @@ -71,8 +71,8 @@ chain is available, so is the rollup. guaranteed to _only_ finalize correct (ie. valid) rollup block hashes given a **single honest verifier** assumption. If there is ever an invalid block hash asserted on layer 1, an honest verifier will prove it is invalid and win a bond. -**Footnote**: There are two main ways to enforce validity of a rollup: fraud proofs (optimistic rollup) and validity -proofs (zkRollup). For the purposes of this spec we only focus on fraud proofs but it is worth noting that validity +**Footnote**: There are two main ways to enforce validity of a rollup: fault proofs (optimistic rollup) and validity +proofs (zkRollup). For the purposes of this spec we only focus on fault proofs but it is worth noting that validity proofs can also be plugged in once they have been made feasible. ## Network Participants @@ -139,7 +139,7 @@ Links to components mentioned in this diagram: - Sequencer Batch Submitter (WIP) - [L2 Output Oracle](./proposals.md#l2-output-oracle-smart-contract) - [L2 Output Submitter](./proposals#proposing-l2-output-commitments) -- Fraud Proof VM (WIP) +- Fault Proof VM (WIP) ### Withdrawing @@ -155,5 +155,5 @@ Links to components mentioned in this diagram: ## Next Steps This is a choose your own adventure. Are you interested in how a verifier works under the hood? Maybe you want to dive -deep into the bit flippin' Fraud Proof VM? All key components have been linked at least once in this doc, so you should +deep into the bit flippin' Fault Proof VM? All key components have been linked at least once in this doc, so you should now have the context you need to dive in deeper. [The world is yours](https://www.youtube.com/watch?v=e5PnuIRnJW8)! diff --git a/specs/overview.md b/specs/overview.md index a550c8c50190..96723e14ed42 100644 --- a/specs/overview.md +++ b/specs/overview.md @@ -59,7 +59,7 @@ token deposits (tokens are locked on L1, then minted on L2 via a deposited trans - The BatchInbox is a regular EOA address. This lets us pass on gast cost savings by not executing any EVM code. - **L2OutputOracle**: A smart contract that stores [L2 output roots](./glossary.md#l2-output) for use with withdrawals -and fraud proofs. +and fault proofs. ### L2 Components From 8d7a1ee8c262ac38773ea4dccf109a869a4be108 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 7 Apr 2022 15:09:27 -0700 Subject: [PATCH 450/585] opnode: Fix bug in block creation (#345) The NoTxPool flag was incorrectly set to falses in the InsertEpoch function. --- opnode/rollup/driver/step.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 57fc8c1c5824..3ffeeac16ca6 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -173,7 +173,9 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S PrevRandao: l2.Bytes32(l1Info.MixDigest()), SuggestedFeeRecipient: d.Config.FeeRecipientAddress, Transactions: txns, - NoTxPool: false, + // we are verifying, not sequencing, we've got all transactions and do not pull from the tx-pool + // (that would make the block derivation non-deterministic) + NoTxPool: true, } // We are either verifying blocks (with a potential for a reorg) or inserting a safe head to the chain From b4ff49ba94cf5ba4b24d7500bb813b3f8d7710aa Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 7 Apr 2022 15:21:37 -0700 Subject: [PATCH 451/585] opnode: Don't allow arbitrary mints (#346) The ordering of `mint, value` was switched to be `value, mint` when parsing emitted logs. This allows users to control their mint rather than using `msg.value` which is being fed directly into the event. Thanks to Mofi (Inphi) for finding this. --- opnode/rollup/derive/payload_attributes.go | 5 +++-- opnode/rollup/derive/payload_attributes_test.go | 6 +++--- opnode/test/system_test.go | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 487b8c58700e..b0ff020ffcca 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -64,8 +64,6 @@ func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.D // unindexed data offset := uint64(0) - dep.Value = new(big.Int).SetBytes(ev.Data[offset : offset+32]) - offset += 32 dep.Mint = new(big.Int).SetBytes(ev.Data[offset : offset+32]) // 0 mint is represented as nil to skip minting code @@ -74,6 +72,9 @@ func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.D } offset += 32 + dep.Value = new(big.Int).SetBytes(ev.Data[offset : offset+32]) + offset += 32 + gas := new(big.Int).SetBytes(ev.Data[offset : offset+32]) if !gas.IsUint64() { return nil, fmt.Errorf("bad gas value: %x", ev.Data[offset:offset+32]) diff --git a/opnode/rollup/derive/payload_attributes_test.go b/opnode/rollup/derive/payload_attributes_test.go index 7a9f8e2280c2..93897495938a 100644 --- a/opnode/rollup/derive/payload_attributes_test.go +++ b/opnode/rollup/derive/payload_attributes_test.go @@ -72,14 +72,14 @@ func GenerateDepositLog(deposit *types.DepositTx) *types.Log { data := make([]byte, 6*32) offset := 0 - deposit.Value.FillBytes(data[offset : offset+32]) - offset += 32 - if deposit.Mint != nil { deposit.Mint.FillBytes(data[offset : offset+32]) } offset += 32 + deposit.Value.FillBytes(data[offset : offset+32]) + offset += 32 + binary.BigEndian.PutUint64(data[offset+24:offset+32], deposit.Gas) offset += 32 if deposit.To == nil { // isCreation diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 6c8f2289738b..3838dfc133dd 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -312,7 +312,8 @@ func TestSystemE2E(t *testing.T) { // Finally send TX mintAmount := big.NewInt(1_000_000_000_000) - _, err = depositContract.DepositTransaction(opts, fromAddr, mintAmount, big.NewInt(1_000_000), false, nil) + opts.Value = mintAmount + _, err = depositContract.DepositTransaction(opts, fromAddr, common.Big0, big.NewInt(1_000_000), false, nil) require.Nil(t, err, "with deposit tx") // Wait for tx to be mined on L1 (or timeout) From 77cb146666b51dbe20270e25d2663371ff700e8f Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 02:14:30 +0200 Subject: [PATCH 452/585] opnode,specs: deposit tx-hash uniqueness based on L1 --- go.mod | 2 +- go.sum | 4 +- opnode/rollup/derive/payload_attributes.go | 90 ++++++++++++++----- .../rollup/derive/payload_attributes_test.go | 79 +++++++++------- opnode/rollup/driver/step.go | 9 +- specs/deposits.md | 25 +++++- specs/rollup-node.md | 3 +- 7 files changed, 144 insertions(+), 68 deletions(-) diff --git a/go.mod b/go.mod index ae98795dad37..4d6c069e4d00 100644 --- a/go.mod +++ b/go.mod @@ -68,7 +68,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220406213206-248249306ec5 +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220407230310-98cc1af1db56 // For local debugging: //replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/go.sum b/go.sum index bdf67d3acf9c..230625a8ed0c 100644 --- a/go.sum +++ b/go.sum @@ -135,8 +135,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220406213206-248249306ec5 h1:DQF/m7Jafs7bJTTAjQ8dKKcdv58VtFZ+lfF0AjOJeFM= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220406213206-248249306ec5/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220407230310-98cc1af1db56 h1:Lonn7nAcLfAT2z5Ft+TVWsmp8DByfmWAaJ/fXI/8xsI= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220407230310-98cc1af1db56/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= 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= diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index b0ff020ffcca..793540c7f319 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -25,6 +25,44 @@ var ( L1InfoPredeployAddr = common.HexToAddress("0x4200000000000000000000000000000000000015") ) +type UserDepositSource struct { + L1BlockHash common.Hash + LogIndex uint64 +} + +const ( + UserDepositSourceDomain = 0 + L1InfoDepositSourceDomain = 1 +) + +func (dep *UserDepositSource) SourceHash() common.Hash { + var input [32 * 2]byte + copy(input[:32], dep.L1BlockHash[:]) + binary.BigEndian.PutUint64(input[32*2-8:], dep.LogIndex) + depositIDHash := crypto.Keccak256Hash(input[:]) + var domainInput [32 * 2]byte + binary.BigEndian.PutUint64(domainInput[32-8:32], UserDepositSourceDomain) + copy(domainInput[32:], depositIDHash[:]) + return crypto.Keccak256Hash(domainInput[:]) +} + +type L1InfoDepositSource struct { + L1BlockHash common.Hash + SeqNumber uint64 +} + +func (dep *L1InfoDepositSource) SourceHash() common.Hash { + var input [32 * 2]byte + copy(input[:32], dep.L1BlockHash[:]) + binary.BigEndian.PutUint64(input[32*2-8:], dep.SeqNumber) + depositIDHash := crypto.Keccak256Hash(input[:]) + + var domainInput [32 * 2]byte + binary.BigEndian.PutUint64(domainInput[32-8:32], L1InfoDepositSourceDomain) + copy(domainInput[32:], depositIDHash[:]) + return crypto.Keccak256Hash(domainInput[:]) +} + // UnmarshalLogEvent decodes an EVM log entry emitted by the deposit contract into typed deposit data. // // parse log data for: @@ -38,10 +76,8 @@ var ( // data data // ); // -// Deposits additionally get: -// - blockNum matching the L1 block height -// - txIndex: matching the deposit index, not L1 transaction index, since there can be multiple deposits per L1 tx -func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.DepositTx, error) { +// Additionally, the event log-index and +func UnmarshalLogEvent(ev *types.Log) (*types.DepositTx, error) { if len(ev.Topics) != 3 { return nil, fmt.Errorf("expected 3 event topics (event identity, indexed from, indexed to)") } @@ -54,8 +90,11 @@ func UnmarshalLogEvent(blockNum uint64, txIndex uint64, ev *types.Log) (*types.D var dep types.DepositTx - dep.BlockHeight = blockNum - dep.TransactionIndex = txIndex + source := UserDepositSource{ + L1BlockHash: ev.BlockHash, + LogIndex: uint64(ev.Index), + } + dep.SourceHash = source.SourceHash() // indexed 0 dep.From = common.BytesToAddress(ev.Topics[1][12:]) @@ -128,8 +167,9 @@ type L1Info interface { ReceiptHash() common.Hash } -// L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block -func L1InfoDeposit(l2BlockHeight uint64, block L1Info) *types.DepositTx { +// L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block, +// and the L2 block-height difference with the start of the epoch. +func L1InfoDeposit(seqNumber uint64, block L1Info) *types.DepositTx { data := make([]byte, 4+8+8+32+32) offset := 0 copy(data[offset:4], L1InfoFuncBytes4) @@ -142,20 +182,24 @@ func L1InfoDeposit(l2BlockHeight uint64, block L1Info) *types.DepositTx { offset += 32 copy(data[offset:offset+32], block.Hash().Bytes()) + source := L1InfoDepositSource{ + L1BlockHash: block.Hash(), + SeqNumber: seqNumber, + } + return &types.DepositTx{ - BlockHeight: l2BlockHeight, - TransactionIndex: 0, // always the first transaction - From: DepositContractAddr, - To: &L1InfoPredeployAddr, - Mint: nil, - Value: big.NewInt(0), - Gas: 99_999_999, - Data: data, + SourceHash: source.SourceHash(), + From: DepositContractAddr, + To: &L1InfoPredeployAddr, + Mint: nil, + Value: big.NewInt(0), + Gas: 99_999_999, + Data: data, } } // UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block -func UserDeposits(l2BlockHeight uint64, receipts []*types.Receipt) ([]*types.DepositTx, error) { +func UserDeposits(receipts []*types.Receipt) ([]*types.DepositTx, error) { var out []*types.DepositTx for _, rec := range receipts { @@ -164,8 +208,7 @@ func UserDeposits(l2BlockHeight uint64, receipts []*types.Receipt) ([]*types.Dep } for _, log := range rec.Logs { if log.Address == DepositContractAddr { - // offset transaction index by 1, the first is the l1-info tx - dep, err := UnmarshalLogEvent(l2BlockHeight, uint64(len(out))+1, log) + dep, err := UnmarshalLogEvent(log) if err != nil { return nil, fmt.Errorf("malformatted L1 deposit log: %v", err) } @@ -286,8 +329,9 @@ func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, nextL return out } -func L1InfoDepositBytes(l2BlockHeight uint64, l1Info L1Info) (hexutil.Bytes, error) { - l1Tx := types.NewTx(L1InfoDeposit(l2BlockHeight, l1Info)) +// L1InfoDepositBytes returns a serialized L1-info attributes transaction. +func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info) (hexutil.Bytes, error) { + l1Tx := types.NewTx(L1InfoDeposit(seqNumber, l1Info)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { return nil, fmt.Errorf("failed to encode L1 info tx") @@ -295,8 +339,8 @@ func L1InfoDepositBytes(l2BlockHeight uint64, l1Info L1Info) (hexutil.Bytes, err return opaqueL1Tx, nil } -func DeriveDeposits(l2BlockHeight uint64, receipts []*types.Receipt) ([]hexutil.Bytes, error) { - userDeposits, err := UserDeposits(l2BlockHeight, receipts) +func DeriveDeposits(receipts []*types.Receipt) ([]hexutil.Bytes, error) { + userDeposits, err := UserDeposits(receipts) if err != nil { return nil, fmt.Errorf("failed to derive user deposits: %v", err) } diff --git a/opnode/rollup/derive/payload_attributes_test.go b/opnode/rollup/derive/payload_attributes_test.go index 93897495938a..cdae082dee46 100644 --- a/opnode/rollup/derive/payload_attributes_test.go +++ b/opnode/rollup/derive/payload_attributes_test.go @@ -28,7 +28,7 @@ func RandETH(rng *rand.Rand, max int64) *big.Int { } // Returns a DepositEvent customized on the basis of the id parameter. -func GenerateDeposit(blockNum uint64, txIndex uint64, rng *rand.Rand) *types.DepositTx { +func GenerateDeposit(source UserDepositSource, rng *rand.Rand) *types.DepositTx { dataLen := rng.Int63n(10_000) data := make([]byte, dataLen) rng.Read(data) @@ -44,14 +44,13 @@ func GenerateDeposit(blockNum uint64, txIndex uint64, rng *rand.Rand) *types.Dep } dep := &types.DepositTx{ - BlockHeight: blockNum, - TransactionIndex: txIndex, - From: GenerateAddress(rng), - To: to, - Value: RandETH(rng, 200), - Gas: uint64(rng.Int63n(10 * 1e6)), // 10 M gas max - Data: data, - Mint: mint, + SourceHash: source.SourceHash(), + From: GenerateAddress(rng), + To: to, + Value: RandETH(rng, 200), + Gas: uint64(rng.Int63n(10 * 1e6)), // 10 M gas max + Data: data, + Mint: mint, } return dep } @@ -118,11 +117,17 @@ func TestUnmarshalLogEvent(t *testing.T) { for i := int64(0); i < 100; i++ { t.Run(fmt.Sprintf("random_deposit_%d", i), func(t *testing.T) { rng := rand.New(rand.NewSource(1234 + i)) - blockNum := rng.Uint64() - txIndex := uint64(rng.Intn(10000)) - depInput := GenerateDeposit(blockNum, txIndex, rng) + source := UserDepositSource{ + L1BlockHash: randomHash(rng), + LogIndex: uint64(rng.Intn(10000)), + } + depInput := GenerateDeposit(source, rng) log := GenerateDepositLog(depInput) - depOutput, err := UnmarshalLogEvent(blockNum, txIndex, log) + + log.TxIndex = uint(rng.Intn(10000)) + log.Index = uint(source.LogIndex) + log.BlockHash = source.L1BlockHash + depOutput, err := UnmarshalLogEvent(log) if err != nil { t.Fatal(err) } @@ -142,54 +147,64 @@ type receiptData struct { } type DeriveUserDepositsTestCase struct { - name string - height uint64 + name string // generate len(receipts) receipts receipts []receiptData } func TestDeriveUserDeposits(t *testing.T) { testCases := []DeriveUserDepositsTestCase{ - {"no deposits", 100, []receiptData{}}, - {"other log", 100, []receiptData{{true, []bool{false}}}}, - {"success deposit", 100, []receiptData{{true, []bool{true}}}}, - {"failed deposit", 100, []receiptData{{false, []bool{true}}}}, - {"mixed deposits", 100, []receiptData{{true, []bool{true}}, {false, []bool{true}}}}, - {"success multiple logs", 100, []receiptData{{true, []bool{true, true}}}}, - {"failed multiple logs", 100, []receiptData{{false, []bool{true, true}}}}, - {"not all deposit logs", 100, []receiptData{{true, []bool{true, false, true}}}}, - {"random", 100, []receiptData{{true, []bool{false, false, true}}, {false, []bool{}}, {true, []bool{true}}}}, + {"no deposits", []receiptData{}}, + {"other log", []receiptData{{true, []bool{false}}}}, + {"success deposit", []receiptData{{true, []bool{true}}}}, + {"failed deposit", []receiptData{{false, []bool{true}}}}, + {"mixed deposits", []receiptData{{true, []bool{true}}, {false, []bool{true}}}}, + {"success multiple logs", []receiptData{{true, []bool{true, true}}}}, + {"failed multiple logs", []receiptData{{false, []bool{true, true}}}}, + {"not all deposit logs", []receiptData{{true, []bool{true, false, true}}}}, + {"random", []receiptData{{true, []bool{false, false, true}}, {false, []bool{}}, {true, []bool{true}}}}, } for i, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { rng := rand.New(rand.NewSource(1234 + int64(i))) var receipts []*types.Receipt var expectedDeposits []*types.DepositTx - for _, rData := range testCase.receipts { + logIndex := uint(0) + blockHash := randomHash(rng) + for txIndex, rData := range testCase.receipts { var logs []*types.Log status := types.ReceiptStatusSuccessful if !rData.goodReceipt { status = types.ReceiptStatusFailed } for _, isDeposit := range rData.DepositLogs { + var ev *types.Log if isDeposit { - dep := GenerateDeposit(testCase.height, uint64(1+len(expectedDeposits)), rng) + source := UserDepositSource{L1BlockHash: blockHash, LogIndex: uint64(logIndex)} + dep := GenerateDeposit(source, rng) if status == types.ReceiptStatusSuccessful { expectedDeposits = append(expectedDeposits, dep) } - logs = append(logs, GenerateDepositLog(dep)) + ev = GenerateDepositLog(dep) } else { - logs = append(logs, GenerateLog(GenerateAddress(rng), nil, nil)) + ev = GenerateLog(GenerateAddress(rng), nil, nil) } + ev.TxIndex = uint(txIndex) + ev.Index = logIndex + ev.BlockHash = blockHash + logs = append(logs, ev) + logIndex++ } receipts = append(receipts, &types.Receipt{ - Type: types.DynamicFeeTxType, - Status: status, - Logs: logs, + Type: types.DynamicFeeTxType, + Status: status, + Logs: logs, + BlockHash: blockHash, + TransactionIndex: uint(txIndex), }) } - got, err := UserDeposits(testCase.height, receipts) + got, err := UserDeposits(receipts) assert.NoError(t, err) assert.Equal(t, len(got), len(expectedDeposits)) for d, depTx := range got { diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 3ffeeac16ca6..787a781c2500 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -48,13 +48,14 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, return l2Head, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) } - l1InfoTx, err := derive.L1InfoDepositBytes(l2Head.Number+1, l1Info) + seqNumber := l2Head.Number + 1 - l2SafeHead.Number + l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info) if err != nil { return l2Head, nil, err } var txns []l2.Data txns = append(txns, l1InfoTx) - deposits, err := derive.DeriveDeposits(l2Head.Number+1, receipts) + deposits, err := derive.DeriveDeposits(receipts) d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Head, "l1Origin", l1Origin) if err != nil { return l2Head, nil, fmt.Errorf("failed to derive deposits: %v", err) @@ -124,7 +125,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to get L1 timestamp of next L1 block: %v", err) } - deposits, err := derive.DeriveDeposits(l2SafeHead.Number+1, receipts) + deposits, err := derive.DeriveDeposits(receipts) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to derive deposits: %w", err) } @@ -159,7 +160,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S var reorg bool for i, batch := range batches { var txns []l2.Data - l1InfoTx, err := derive.L1InfoDepositBytes(lastSafeHead.Number+1, l1Info) + l1InfoTx, err := derive.L1InfoDepositBytes(uint64(i), l1Info) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to create l1InfoTx: %w", err) } diff --git a/specs/deposits.md b/specs/deposits.md index a3782080132b..f067ee0d9367 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -23,6 +23,7 @@ with the authorization and validation conditions on L2. **Table of Contents** - [The Deposited Transaction Type](#the-deposited-transaction-type) + - [Source hash computation](#source-hash-computation) - [Kinds of Deposited Transactions](#kinds-of-deposited-transactions) - [Validation and Authorization of Deposited Transactions](#validation-and-authorization-of-deposited-transactions) - [Execution](#execution) @@ -55,8 +56,7 @@ fields (rlp encoded in the order they appear here): [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -- `uint64 blockHeight`: the block-height of the L2 block -- `uint64 transactionIndex`: the transaction-index within the L2 transactions list +- `bytes32 sourceHash`: the source-hash, uniquely identifies the origin of the deposit - `address from`: The address of the sender account. - `address to`: The address of the recipient account, or the null (zero-length) address if the deposited transaction is a contract creation. @@ -75,8 +75,25 @@ Picking a high identifier minimizes the risk that the identifier will be used be transaction type on the L1 chain in the future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. -The extra blockHeight and transactionIndex in deposits will be used to ensure that deposited transactions -will be unique. Without them, two different deposited transaction could have the same exact hash. +### Source hash computation + +The `sourceHash` of a deposit transaction is computed based on the origin: + +- User-deposited: + `keccak256(bytes32(uint256(0)), keccak256(l1BlockHash, bytes32(uint256(l1LogIndex))))`. + Where the `l1BlockHash`, and `l1LogIndex` all refer to the inclusion of the deposit log event on L1. + `l1LogIndex` is the index of the deposit event log in the combined list of log events of the block. +- L1 attributes deposited: + `keccak256(bytes32(uint256(1)), keccak256(bytes32(uint256(l1BlockHash)), bytes32(uint256(seqNumber))`. + Where `l1BlockHash` refers to the L1 block hash of which the info attributes are deposited. + And `seqNumber = l2BlockNum - l2EpochStartBlockNum`, + where `l2BlockNum` is the L2 block number of the inclusion of the deposit tx in L2, + and `l2EpochStartBlockNum` is the L2 block number of the first L2 block in the epoch. + +Without a `sourceHash` in a deposit, two different deposited transactions could have the same exact hash. + +The outer `keccak256` hashes the actual uniquely identifying information with a domain, +to avoid collisions between different types of sources. We do not use the sender's nonce to ensure uniqueness because this would require an extra L2 EVM state read from the [execution engine][g-exec-engine] during block-derivation. diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 2ab1bb4c4282..33be6323a702 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -98,8 +98,7 @@ The rollup reads the following data from the [sequencing window][g-sequencing-wi - timestamp - basefee - *random* (the output of the [`RANDOM` opcode][random]) - - L1 log entries emitted for [user deposits][g-deposits], derived transactions are augmented with - `blockHeight` and `transactionIndex` of the transaction in L2. + - L1 log entries emitted for [user deposits][g-deposits], augmented with a [sourceHash](./deposits.md#). - Of each block in the window: - Sequencer batches, derived from the transactions: - The transaction receiver is the sequencer inbox address From c073a6c89d606f6207badf88b2c73f3c8c809d83 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 02:44:52 +0200 Subject: [PATCH 453/585] opnode/l1: verify critical receipt/log info we get from RPC --- opnode/l1/receipts.go | 38 +++++++++++++++++++++++++++++++++++++- opnode/l1/source.go | 2 +- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/opnode/l1/receipts.go b/opnode/l1/receipts.go index d22a3cb94133..b808f9443aac 100644 --- a/opnode/l1/receipts.go +++ b/opnode/l1/receipts.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" @@ -12,7 +14,7 @@ import ( ) // fetchReceipts fetches the receipts of the transactions using RPC batching, verifies if the receipts are complete and correct, and then returns results -func fetchReceipts(ctx context.Context, receiptHash common.Hash, txs types.Transactions, getBatch batchCallContextFn) (types.Receipts, error) { +func fetchReceipts(ctx context.Context, block eth.BlockID, receiptHash common.Hash, txs types.Transactions, getBatch batchCallContextFn) (types.Receipts, error) { if len(txs) == 0 { if receiptHash != types.EmptyRootHash { return nil, fmt.Errorf("no transactions, but got non-empty receipt trie root: %s", receiptHash) @@ -33,10 +35,44 @@ func fetchReceipts(ctx context.Context, receiptHash common.Hash, txs types.Trans if err := getBatch(ctx, receiptRequests); err != nil { return nil, fmt.Errorf("failed to fetch batch of receipts: %v", err) } + + // We don't trust the RPC to provide consistent cached receipt info that we use for critical rollup derivation work. + // Let's check everything quickly. + logIndex := uint(0) for i, r := range receipts { if r == nil { // on reorgs or other cases the receipts may disappear before they can be retrieved. return nil, fmt.Errorf("receipt of tx %d returns nil on retrieval", i) } + if r.TransactionIndex != uint(i) { + return nil, fmt.Errorf("receipt %d has unexpected tx index %d", i, r.TransactionIndex) + } + if r.BlockNumber.Uint64() != block.Number { + return nil, fmt.Errorf("receipt %d has unexpected block number %d, expected %d", i, r.BlockNumber, block.Number) + } + if r.BlockHash != block.Hash { + return nil, fmt.Errorf("receipt %d has unexpected block hash %s, expected %s", i, r.BlockHash, block.Hash) + } + for j, log := range r.Logs { + if log.Index != logIndex { + return nil, fmt.Errorf("log %d (%d of tx %d) has unexpected log index %d", logIndex, j, i, log.Index) + } + if log.TxIndex != uint(i) { + return nil, fmt.Errorf("log %d has unexpected tx index %d", log.Index, log.TxIndex) + } + if log.BlockHash != block.Hash { + return nil, fmt.Errorf("log %d of block %s has unexpected block hash %s", log.Index, block.Hash, log.BlockHash) + } + if log.BlockNumber != block.Number { + return nil, fmt.Errorf("log %d of block %d has unexpected block number %d", log.Index, block.Number, log.BlockNumber) + } + if h := txs[i].Hash(); log.TxHash != h { + return nil, fmt.Errorf("log %d of tx %s has unexpected tx hash %s", log.Index, h, log.TxHash) + } + if log.Removed { + return nil, fmt.Errorf("canonical log (%d) must never be removed due to reorg", log.Index) + } + logIndex++ + } } // Sanity-check: external L1-RPC sources are notorious for not returning all receipts, diff --git a/opnode/l1/source.go b/opnode/l1/source.go index f68addab8131..7d78ddc2d30f 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -234,7 +234,7 @@ func (s *Source) Fetch(ctx context.Context, blockHash common.Hash) (derive.L1Inf return nil, nil, nil, err } - receipts, err := fetchReceipts(ctx, info.receiptHash, txs, s.batchCall) + receipts, err := fetchReceipts(ctx, info.ID(), info.receiptHash, txs, s.batchCall) if err != nil { return nil, nil, nil, err } From 1467d368d85b1c95eecda8ceec43214454d7e673 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 03:55:55 +0200 Subject: [PATCH 454/585] opnode/test: reconstruct deposit hash in e2e test, fetch l2 deposit receipt --- opnode/test/system_test.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 3838dfc133dd..7af570818ecc 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -313,7 +313,7 @@ func TestSystemE2E(t *testing.T) { // Finally send TX mintAmount := big.NewInt(1_000_000_000_000) opts.Value = mintAmount - _, err = depositContract.DepositTransaction(opts, fromAddr, common.Big0, big.NewInt(1_000_000), false, nil) + l1DepTx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, big.NewInt(1_000_000), false, nil) require.Nil(t, err, "with deposit tx") // Wait for tx to be mined on L1 (or timeout) @@ -352,6 +352,19 @@ loop: } } + // Based on the L1 event log, compute the deposit-tx hash, and receive the receipt from the derived L2 deposit tx. + ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + l1DepReceipt, err := l1Client.TransactionReceipt(ctx, l1DepTx.Hash()) + require.Nil(t, err, "Could not get L1 deposit receipt") + reconstructedDep, err := derive.UnmarshalLogEvent(l1DepReceipt.Logs[0]) + require.NoError(t, err) + l2DepTx := types.NewTx(reconstructedDep) + depHash := l2DepTx.Hash() + depositReceipt, err := l2Client.TransactionReceipt(context.Background(), depHash) + require.NoError(t, err) + require.Equal(t, depositReceipt.Status, types.ReceiptStatusSuccessful) + // Confirm balance ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) defer cancel() From acdecb327109a7e12bda79e1d1e671e2e04d10d1 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 03:56:31 +0200 Subject: [PATCH 455/585] opnode/l1: fix panic on channel send after close, sema channel can stay open --- opnode/l1/request_sema.go | 1 - 1 file changed, 1 deletion(-) diff --git a/opnode/l1/request_sema.go b/opnode/l1/request_sema.go index 4a7dc892d2e4..960bdc31c54a 100644 --- a/opnode/l1/request_sema.go +++ b/opnode/l1/request_sema.go @@ -38,6 +38,5 @@ func (lc *limitClient) EthSubscribe(ctx context.Context, channel interface{}, ar } func (lc *limitClient) Close() { - close(lc.sema) lc.c.Close() } From e8f732ba1abd550f0bdc70a9ed4f3ab3fe14187c Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 04:06:21 +0200 Subject: [PATCH 456/585] go.mod: l2 geth update with improved deposit tx hash --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4d6c069e4d00..e5147b113d82 100644 --- a/go.mod +++ b/go.mod @@ -68,7 +68,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220407230310-98cc1af1db56 +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220408020128-a9d9c835433e // For local debugging: //replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/go.sum b/go.sum index 230625a8ed0c..b0dabc63cbf1 100644 --- a/go.sum +++ b/go.sum @@ -135,8 +135,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220407230310-98cc1af1db56 h1:Lonn7nAcLfAT2z5Ft+TVWsmp8DByfmWAaJ/fXI/8xsI= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220407230310-98cc1af1db56/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220408020128-a9d9c835433e h1:jf42JF7YfNFqgzxkDFjq752UXMMvSFvsD6G8ezslQg0= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220408020128-a9d9c835433e/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= 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= From 8b0a7ded64fbe8fe1d2bced202eb9442611ca9a8 Mon Sep 17 00:00:00 2001 From: norswap Date: Fri, 8 Apr 2022 06:35:33 +0200 Subject: [PATCH 457/585] README: remove alpha branch + update description (#332) --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 283aadf27887..85656c4573f3 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,8 @@ This repository holds the work-in-progress specification for the next version of Optimism. This spec is developed iteratively, specifying a rollup of increasing -complexity. The current stage specifies a "rollup" whose only transactions are -deposits (L2 transactions submitted on L1). - -A more detailed, though potentially out of date specification can be found on -the `alpha` branch. +complexity. The current stage specifies a "rollup" with deposits, withdrawals and sequenced (L2-native) transactions. +Some aspects, such as the fee logic and calldata compression, are still missing or in placeholder state. ## Work in Progress From 7d0490bba0b7061a2398a24d70fd77615e9878b0 Mon Sep 17 00:00:00 2001 From: norswap Date: Thu, 7 Apr 2022 15:57:49 +0200 Subject: [PATCH 458/585] allow building everything from top-level makefile --- Makefile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 131473335bab..41c5b8779cd1 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,20 @@ +build: submodules opnode contracts +.PHONY: build + +submodules: + # CI will checkout submodules on its own (and fails on these commands) + if [ -z "$$GITHUB_ENV" ]; then \ + git submodule init; \ + git submodule update; \ + fi +.PHONY: submodules + opnode: go build -o ./bin/op ./opnode/cmd .PHONY: opnode contracts: - cd ./packages/contracts && yarn build + cd ./packages/contracts && yarn install && yarn build .PHONY: contracts clean: From b5e2eae3c13e289a3c455cd820a19f2135fc0175 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 7 Apr 2022 16:07:06 +0200 Subject: [PATCH 459/585] allow testing from top level makefile --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 41c5b8779cd1..e1e59959d837 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,17 @@ submodules: opnode: go build -o ./bin/op ./opnode/cmd -.PHONY: opnode +.PHONY: opnoed contracts: cd ./packages/contracts && yarn install && yarn build .PHONY: contracts +test: + cd ./opnode && make test + cd ./packages/contracts && yarn test +.PHONY: test + clean: rm -rf ./bin .PHONY: clean From e57f43b1091db02901e8cf581b35ae2f81c993df Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Thu, 7 Apr 2022 22:34:49 -0600 Subject: [PATCH 460/585] Update Makefile Co-authored-by: Joshua Gutow --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e1e59959d837..ef7294288957 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ submodules: opnode: go build -o ./bin/op ./opnode/cmd -.PHONY: opnoed +.PHONY: opnode contracts: cd ./packages/contracts && yarn install && yarn build From 04a37836bc53959829400cf9a2069f4a1644033c Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 14:47:02 +0200 Subject: [PATCH 461/585] opnode/l1: wrap errors and fmt test imports --- opnode/l1/batching.go | 3 ++- opnode/l1/batching_test.go | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/opnode/l1/batching.go b/opnode/l1/batching.go index abfd49d6b5f2..74d3add64265 100644 --- a/opnode/l1/batching.go +++ b/opnode/l1/batching.go @@ -29,10 +29,11 @@ type batchResult struct { // fetchBatched fetches the given requests in batches of at most maxPerBatch elements, and with at most maxRetry retries per batch. // Batch requests may be split into maxParallel go-routines. +// Retries only apply to individual request errors, not to the outer batch-requests that combine them into batches. func fetchBatched(ctx context.Context, log log.Logger, requests []rpc.BatchElem, getBatch batchCallContextFn, maxRetry int, maxPerBatch int, maxParallel int) error { batchRequest := func(ctx context.Context, missing []rpc.BatchElem) (failed []rpc.BatchElem, err error) { if err := getBatch(ctx, missing); err != nil { - return nil, fmt.Errorf("failed batch-retrieval of receipts: %v", err) + return nil, fmt.Errorf("failed batch-retrieval: %w", err) } for _, elem := range missing { if elem.Error != nil { diff --git a/opnode/l1/batching_test.go b/opnode/l1/batching_test.go index 5dfe93051819..c625eb2a21b8 100644 --- a/opnode/l1/batching_test.go +++ b/opnode/l1/batching_test.go @@ -4,12 +4,13 @@ import ( "context" "errors" "fmt" + "testing" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "testing" ) type elemCall struct { @@ -285,7 +286,7 @@ func (c *parentErrBatchTestCase) Run(t *testing.T) { c.On("get", requests).Run(func(args mock.Arguments) { }).Return([]error{expErr}) err := fetchBatched(context.Background(), testlog.Logger(t, log.LvlError), requests, c.GetBatch, 2, 2, 1) - assert.Equal(t, expErr, err) + assert.ErrorIs(t, err, expErr) c.AssertExpectations(t) } From db0ec75160f5565adf5eac98746cce90cd4c27c8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 16:18:47 +0200 Subject: [PATCH 462/585] opnode: don't expose types.Block to derive or driver packages, prefer l2.ExecutionPayload --- opnode/l2/api.go | 88 ++++++++++++++++------------------ opnode/l2/source.go | 78 +++++++++++++++++++++++++++--- opnode/rollup/derive/invert.go | 40 ---------------- opnode/rollup/driver/driver.go | 4 +- opnode/rollup/driver/step.go | 61 +++++++++++------------ 5 files changed, 142 insertions(+), 129 deletions(-) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index d290a84ae6f5..cb0980ad6a37 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -5,12 +5,11 @@ import ( "fmt" "reflect" - "github.com/ethereum/go-ethereum/core/beacon" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/beacon" "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" ) @@ -90,62 +89,57 @@ type Data = hexutil.Bytes type PayloadID = beacon.PayloadID type ExecutionPayload struct { - ParentHashField common.Hash `json:"parentHash"` - FeeRecipient common.Address `json:"feeRecipient"` - StateRoot Bytes32 `json:"stateRoot"` - ReceiptsRoot Bytes32 `json:"receiptsRoot"` - LogsBloom Bytes256 `json:"logsBloom"` - PrevRandao Bytes32 `json:"prevRandao"` - BlockNumber Uint64Quantity `json:"blockNumber"` - GasLimit Uint64Quantity `json:"gasLimit"` - GasUsed Uint64Quantity `json:"gasUsed"` - Timestamp Uint64Quantity `json:"timestamp"` - ExtraData BytesMax32 `json:"extraData"` - BaseFeePerGas Uint256Quantity `json:"baseFeePerGas"` - BlockHash common.Hash `json:"blockHash"` + ParentHash common.Hash `json:"parentHash"` + FeeRecipient common.Address `json:"feeRecipient"` + StateRoot Bytes32 `json:"stateRoot"` + ReceiptsRoot Bytes32 `json:"receiptsRoot"` + LogsBloom Bytes256 `json:"logsBloom"` + PrevRandao Bytes32 `json:"prevRandao"` + BlockNumber Uint64Quantity `json:"blockNumber"` + GasLimit Uint64Quantity `json:"gasLimit"` + GasUsed Uint64Quantity `json:"gasUsed"` + Timestamp Uint64Quantity `json:"timestamp"` + ExtraData BytesMax32 `json:"extraData"` + BaseFeePerGas Uint256Quantity `json:"baseFeePerGas"` + BlockHash common.Hash `json:"blockHash"` // Array of transaction objects, each object is a byte list (DATA) representing // TransactionType || TransactionPayload or LegacyTransaction as defined in EIP-2718 - TransactionsField []Data `json:"transactions"` + Transactions []Data `json:"transactions"` } func (payload *ExecutionPayload) ID() eth.BlockID { return eth.BlockID{Hash: payload.BlockHash, Number: uint64(payload.BlockNumber)} } -// Implement block interface to enable derive.BlockReferences over a payload -// type Block interface { -// Hash() common.Hash -// NumberU64() uint64 -// ParentHash() common.Hash -// Transactions() types.Transactions -// } - -func (payload *ExecutionPayload) Hash() common.Hash { - return payload.BlockHash -} - -func (payload *ExecutionPayload) NumberU64() uint64 { - return uint64(payload.BlockNumber) -} - -func (payload *ExecutionPayload) Time() uint64 { - return uint64(payload.Timestamp) -} - -func (payload *ExecutionPayload) ParentHash() common.Hash { - return payload.ParentHashField -} - -func (payload *ExecutionPayload) Transactions() types.Transactions { - res := make([]*types.Transaction, len(payload.TransactionsField)) - for i, t := range payload.TransactionsField { - res[i] = new(types.Transaction) - err := res[i].UnmarshalBinary(t) +func BlockAsPayload(bl *types.Block) (*ExecutionPayload, error) { + baseFee, overflow := uint256.FromBig(bl.BaseFee()) + if overflow { + return nil, fmt.Errorf("invalid base fee in block: %s", bl.BaseFee()) + } + opaqueTxs := make([]Data, len(bl.Transactions())) + for i, tx := range bl.Transactions() { + otx, err := tx.MarshalBinary() if err != nil { - panic(err) + return nil, fmt.Errorf("tx %d failed to marshal: %v", i, err) } + opaqueTxs[i] = otx } - return res + return &ExecutionPayload{ + ParentHash: bl.ParentHash(), + FeeRecipient: bl.Coinbase(), + StateRoot: Bytes32(bl.Root()), + ReceiptsRoot: Bytes32(bl.ReceiptHash()), + LogsBloom: Bytes256(bl.Bloom()), + PrevRandao: Bytes32(bl.MixDigest()), + BlockNumber: Uint64Quantity(bl.NumberU64()), + GasLimit: Uint64Quantity(bl.GasLimit()), + GasUsed: Uint64Quantity(bl.GasUsed()), + Timestamp: Uint64Quantity(bl.Time()), + ExtraData: bl.Extra(), + BaseFeePerGas: Uint256Quantity(*baseFee), + BlockHash: bl.Hash(), + Transactions: opaqueTxs, + }, nil } type PayloadAttributes struct { diff --git a/opnode/l2/source.go b/opnode/l2/source.go index a41b77d879e7..94e3e640d711 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -36,12 +36,30 @@ func (s *Source) Close() { s.rpc.Close() } -func (s *Source) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return s.client.BlockByHash(ctx, hash) +func (s *Source) PayloadByHash(ctx context.Context, hash common.Hash) (*ExecutionPayload, error) { + // TODO: we really do not need to parse every single tx and block detail, keeping transactions encoded is faster. + block, err := s.client.BlockByHash(ctx, hash) + if err != nil { + return nil, fmt.Errorf("failed to retrieve L2 block by hash: %v", err) + } + payload, err := BlockAsPayload(block) + if err != nil { + return nil, fmt.Errorf("failed to read L2 block as payload: %w", err) + } + return payload, nil } -func (s *Source) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - return s.client.BlockByNumber(ctx, number) +func (s *Source) PayloadByNumber(ctx context.Context, number *big.Int) (*ExecutionPayload, error) { + // TODO: we really do not need to parse every single tx and block detail, keeping transactions encoded is faster. + block, err := s.client.BlockByNumber(ctx, number) + if err != nil { + return nil, fmt.Errorf("failed to retrieve L2 block by number: %v", err) + } + payload, err := BlockAsPayload(block) + if err != nil { + return nil, fmt.Errorf("failed to read L2 block as payload: %w", err) + } + return payload, nil } // ForkchoiceUpdate updates the forkchoice on the execution client. If attributes is not nil, the engine client will also begin building a block @@ -147,7 +165,7 @@ func (s *Source) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2 // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) } - return derive.BlockReferences(block, s.genesis) + return blockToBlockRef(block) } // L2BlockRefByHash returns the block & parent ids based on the supplied hash. The returned BlockRef may not be in the canonical chain @@ -157,5 +175,53 @@ func (s *Source) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth. // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) } - return derive.BlockReferences(block, s.genesis) + return blockToBlockRef(block) +} + +func blockToBlockRef(block *types.Block) (eth.L2BlockRef, error) { + txs := block.Transactions() + if len(txs) == 0 { + return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", block.Hash()) + } + tx := txs[0] + if tx.Type() != types.DepositTxType { + return eth.L2BlockRef{}, fmt.Errorf("first block tx has unexpected tx type: %d", tx.Type()) + } + l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) + if err != nil { + return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) + } + return eth.L2BlockRef{ + Hash: block.Hash(), + Number: block.NumberU64(), + ParentHash: block.ParentHash(), + Time: block.Time(), + L1Origin: eth.BlockID{Hash: l1Hash, Number: l1Number}, + }, nil +} + +func PayloadToBlockRef(payload *ExecutionPayload) (eth.L2BlockRef, error) { + if len(payload.Transactions) == 0 { + return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", payload.BlockHash) + } + var tx types.Transaction + if err := tx.UnmarshalBinary(payload.Transactions[0]); err != nil { + return eth.L2BlockRef{}, fmt.Errorf("failed to decode first tx to read l1 info from: %v", err) + } + if tx.Type() != types.DepositTxType { + return eth.L2BlockRef{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type()) + } + l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) + if err != nil { + return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) + } + l1Origin := eth.BlockID{Hash: l1Hash, Number: l1Number} + + return eth.L2BlockRef{ + Hash: payload.BlockHash, + Number: uint64(payload.BlockNumber), + ParentHash: payload.ParentHash, + Time: uint64(payload.Timestamp), + L1Origin: l1Origin, + }, nil } diff --git a/opnode/rollup/derive/invert.go b/opnode/rollup/derive/invert.go index b17a79270265..fecae3e575ee 100644 --- a/opnode/rollup/derive/invert.go +++ b/opnode/rollup/derive/invert.go @@ -5,10 +5,7 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" ) // L1InfoDepositTxData is the inverse of L1InfoDeposit, to see where the L2 chain is derived from @@ -27,40 +24,3 @@ func L1InfoDepositTxData(data []byte) (nr uint64, time uint64, baseFee *big.Int, blockHash.SetBytes(data[offset : offset+32]) return } - -type Block interface { - Hash() common.Hash - NumberU64() uint64 - ParentHash() common.Hash - Transactions() types.Transactions - Time() uint64 -} - -// BlockReferences takes a L2 block and determines which L1 block it was derived from, its L2 parent id, and its own id. -func BlockReferences(l2Block Block, genesis *rollup.Genesis) (eth.L2BlockRef, error) { - id := eth.L2BlockRef{ - Hash: l2Block.Hash(), - Number: l2Block.NumberU64(), - ParentHash: l2Block.ParentHash(), - Time: l2Block.Time(), - } - - if id.Number <= genesis.L2.Number { - if id.Hash != genesis.L2.Hash { - return eth.L2BlockRef{}, fmt.Errorf("unexpected L2 genesis block: %s:%d, expected %s", id.Hash, id.Number, genesis.L2) - } - id.L1Origin = genesis.L1 - return id, nil - } - - txs := l2Block.Transactions() - if len(txs) == 0 || txs[0].Type() != types.DepositTxType { - return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", l2Block.Hash()) - } - l1Number, _, _, l1Hash, err := L1InfoDepositTxData(txs[0].Data()) - if err != nil { - return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) - } - id.L1Origin = eth.BlockID{Hash: l1Hash, Number: l1Number} - return id, nil -} diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 747ee31b4c1f..c27890cc464a 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -32,8 +32,8 @@ type Engine interface { GetPayload(ctx context.Context, payloadId l2.PayloadID) (*l2.ExecutionPayload, error) ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) NewPayload(ctx context.Context, payload *l2.ExecutionPayload) error - BlockByHash(context.Context, common.Hash) (*types.Block, error) - BlockByNumber(context.Context, *big.Int) (*types.Block, error) + PayloadByHash(context.Context, common.Hash) (*l2.ExecutionPayload, error) + PayloadByNumber(context.Context, *big.Int) (*l2.ExecutionPayload, error) } type L1Chain interface { diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 787a781c2500..7ade4a42df4e 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -1,6 +1,7 @@ package driver import ( + "bytes" "context" "errors" "fmt" @@ -85,10 +86,10 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, BatchV1: derive.BatchV1{ Epoch: rollup.Epoch(l1Info.NumberU64()), Timestamp: uint64(payload.Timestamp), - Transactions: payload.TransactionsField[depositStart:], + Transactions: payload.Transactions[depositStart:], }, } - ref, err := derive.BlockReferences(payload, &d.Config.Genesis) + ref, err := l2.PayloadToBlockRef(payload) return ref, batch, err } @@ -110,7 +111,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S epoch := rollup.Epoch(l1Input[0].Number) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - l2Info, err := d.l2.BlockByHash(fetchCtx, l2SafeHead.Hash) + l2Info, err := d.l2.PayloadByHash(fetchCtx, l2SafeHead.Hash) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to fetch L2 block info of %s: %w", l2SafeHead, err) } @@ -139,7 +140,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S return l2Head, l2SafeHead, false, fmt.Errorf("failed to fetch create batches from transactions: %w", err) } // Make batches contiguous - minL2Time := l2Info.Time() + d.Config.BlockTime + minL2Time := uint64(l2Info.Timestamp) + d.Config.BlockTime maxL2Time := l1Info.Time() + d.Config.MaxSequencerDrift if minL2Time+d.Config.BlockTime > maxL2Time { maxL2Time = minL2Time + d.Config.BlockTime @@ -156,7 +157,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S lastHead := l2Head lastSafeHead := l2SafeHead didReorg := false - var payload derive.Block + var payload *l2.ExecutionPayload var reorg bool for i, batch := range batches { var txns []l2.Data @@ -190,7 +191,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) } - newLast, err := derive.BlockReferences(payload, &d.Config.Genesis) + newLast, err := l2.PayloadToBlockRef(payload) if err != nil { return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to derive block references: %w", err) } @@ -212,29 +213,22 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S // attributesMatchBlock checks if the L2 attributes pre-inputs match the output // nil if it is a match. If err is not nil, the error contains the reason for the mismatch -func attributesMatchBlock(attrs *l2.PayloadAttributes, parentHash common.Hash, block *types.Block) error { - if parentHash != block.ParentHash() { - return fmt.Errorf("parent hash field does not match. expected: %v. got: %v", parentHash, block.ParentHash()) +func attributesMatchBlock(attrs *l2.PayloadAttributes, parentHash common.Hash, block *l2.ExecutionPayload) error { + if parentHash != block.ParentHash { + return fmt.Errorf("parent hash field does not match. expected: %v. got: %v", parentHash, block.ParentHash) } - if uint64(attrs.Timestamp) != block.Time() { - return fmt.Errorf("timestamp field does not match. expected: %v. got: %v", uint64(attrs.Timestamp), block.Time()) + if attrs.Timestamp != block.Timestamp { + return fmt.Errorf("timestamp field does not match. expected: %v. got: %v", uint64(attrs.Timestamp), block.Timestamp) } - if attrs.PrevRandao != l2.Bytes32(block.MixDigest()) { - return fmt.Errorf("random field does not match. expected: %v. got: %v", attrs.PrevRandao, l2.Bytes32(block.MixDigest())) + if attrs.PrevRandao != block.PrevRandao { + return fmt.Errorf("random field does not match. expected: %v. got: %v", attrs.PrevRandao, block.PrevRandao) } - if len(attrs.Transactions) != len(block.Transactions()) { - return fmt.Errorf("transaction count does not match. expected: %v. got: %v", len(attrs.Transactions), len(block.Transactions())) + if len(attrs.Transactions) != len(block.Transactions) { + return fmt.Errorf("transaction count does not match. expected: %v. got: %v", len(attrs.Transactions), block.Transactions) } - btxs := block.Transactions() - for i := range attrs.Transactions { - var tx types.Transaction - err := tx.UnmarshalBinary(attrs.Transactions[i]) - if err != nil { - return fmt.Errorf("failed to decode transaction %d in attributes: %w", i, err) - } - - if tx.Hash() != btxs[i].Hash() { - return fmt.Errorf("transaction %d does not match. expected: %v. got: %v", i, tx.Hash(), btxs[i].Hash()) + for i, otx := range attrs.Transactions { + if expect := block.Transactions[i]; !bytes.Equal(otx, expect) { + return fmt.Errorf("transaction %d does not match. expected: %x. got: %x", i, expect, otx) } } return nil @@ -242,29 +236,28 @@ func attributesMatchBlock(attrs *l2.PayloadAttributes, parentHash common.Hash, b // verifySafeBlock reconciles the supplied payload attributes against the actual L2 block. // If they do not match, it inserts the new block and sets the head and safe head to the new block in the FC. -func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, parent eth.BlockID) (derive.Block, bool, error) { - block, err := d.l2.BlockByNumber(ctx, new(big.Int).SetUint64(parent.Number+1)) +func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, parent eth.BlockID) (*l2.ExecutionPayload, bool, error) { + payload, err := d.l2.PayloadByNumber(ctx, new(big.Int).SetUint64(parent.Number+1)) if err != nil { return nil, false, fmt.Errorf("failed to get L2 block: %w", err) } - err = attributesMatchBlock(attrs, parent.Hash, block) + err = attributesMatchBlock(attrs, parent.Hash, payload) if err != nil { // Have reorg - d.log.Warn("Detected L2 reorg when verifying L2 safe head", "parent", parent, "prev_block", block.Hash(), "mismatch", err) + d.log.Warn("Detected L2 reorg when verifying L2 safe head", "parent", parent, "prev_block", payload.BlockHash, "mismatch", err) fc.HeadBlockHash = parent.Hash fc.SafeBlockHash = parent.Hash payload, err := d.insertHeadBlock(ctx, fc, attrs, true) return payload, true, err } - // If match, just bump the safe head - d.log.Debug("Verified L2 block", "number", block.Number(), "hash", block.Hash()) - fc.SafeBlockHash = block.Hash() + // If the attributes match, just bump the safe head + d.log.Debug("Verified L2 block", "number", payload.BlockNumber, "hash", payload.BlockHash) + fc.SafeBlockHash = payload.BlockHash _, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { return nil, false, fmt.Errorf("failed to execute ForkchoiceUpdated: %w", err) } - return block, false, nil - + return payload, false, nil } // insertHeadBlock creates, executes, and inserts the specified block as the head block. From a0405324a290142d344357a9e1a59749a4eae3cf Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 8 Apr 2022 17:40:21 +0200 Subject: [PATCH 463/585] opnode: add comments, fix genesis base case to get l1 origin --- opnode/l2/source.go | 81 +++++++++++++++++++++++------------- opnode/rollup/driver/step.go | 4 +- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/opnode/l2/source.go b/opnode/l2/source.go index 94e3e640d711..96fc4a0fa199 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -165,7 +165,7 @@ func (s *Source) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2 // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) } - return blockToBlockRef(block) + return blockToBlockRef(block, s.genesis) } // L2BlockRefByHash returns the block & parent ids based on the supplied hash. The returned BlockRef may not be in the canonical chain @@ -175,47 +175,68 @@ func (s *Source) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth. // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) } - return blockToBlockRef(block) + return blockToBlockRef(block, s.genesis) } -func blockToBlockRef(block *types.Block) (eth.L2BlockRef, error) { - txs := block.Transactions() - if len(txs) == 0 { - return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", block.Hash()) - } - tx := txs[0] - if tx.Type() != types.DepositTxType { - return eth.L2BlockRef{}, fmt.Errorf("first block tx has unexpected tx type: %d", tx.Type()) - } - l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) - if err != nil { - return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) +// blockToBlockRef extracts the essential L2BlockRef information from a block, +// falling back to genesis information if necessary. +func blockToBlockRef(block *types.Block, genesis *rollup.Genesis) (eth.L2BlockRef, error) { + var l1Origin eth.BlockID + if block.NumberU64() == genesis.L2.Number { + if block.Hash() != genesis.L2.Hash { + return eth.L2BlockRef{}, fmt.Errorf("expected L2 genesis hash to match L2 block at genesis block number %d: %s <> %s", genesis.L2.Number, block.Hash(), genesis.L2.Hash) + } + l1Origin = genesis.L1 + } else { + txs := block.Transactions() + if len(txs) == 0 { + return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", block.Hash()) + } + tx := txs[0] + if tx.Type() != types.DepositTxType { + return eth.L2BlockRef{}, fmt.Errorf("first block tx has unexpected tx type: %d", tx.Type()) + } + l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) + if err != nil { + return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) + } + l1Origin = eth.BlockID{Hash: l1Hash, Number: l1Number} } return eth.L2BlockRef{ Hash: block.Hash(), Number: block.NumberU64(), ParentHash: block.ParentHash(), Time: block.Time(), - L1Origin: eth.BlockID{Hash: l1Hash, Number: l1Number}, + L1Origin: l1Origin, }, nil } -func PayloadToBlockRef(payload *ExecutionPayload) (eth.L2BlockRef, error) { - if len(payload.Transactions) == 0 { - return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", payload.BlockHash) - } - var tx types.Transaction - if err := tx.UnmarshalBinary(payload.Transactions[0]); err != nil { - return eth.L2BlockRef{}, fmt.Errorf("failed to decode first tx to read l1 info from: %v", err) - } - if tx.Type() != types.DepositTxType { - return eth.L2BlockRef{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type()) - } - l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) - if err != nil { - return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) +// PayloadToBlockRef extracts the essential L2BlockRef information from an execution payload, +// falling back to genesis information if necessary. +func PayloadToBlockRef(payload *ExecutionPayload, genesis *rollup.Genesis) (eth.L2BlockRef, error) { + var l1Origin eth.BlockID + if uint64(payload.BlockNumber) == genesis.L2.Number { + if payload.BlockHash != genesis.L2.Hash { + return eth.L2BlockRef{}, fmt.Errorf("expected L2 genesis hash to match L2 block at genesis block number %d: %s <> %s", genesis.L2.Number, payload.BlockHash, genesis.L2.Hash) + } + l1Origin = genesis.L1 + } else { + if len(payload.Transactions) == 0 { + return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", payload.BlockHash) + } + var tx types.Transaction + if err := tx.UnmarshalBinary(payload.Transactions[0]); err != nil { + return eth.L2BlockRef{}, fmt.Errorf("failed to decode first tx to read l1 info from: %v", err) + } + if tx.Type() != types.DepositTxType { + return eth.L2BlockRef{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type()) + } + l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) + if err != nil { + return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) + } + l1Origin = eth.BlockID{Hash: l1Hash, Number: l1Number} } - l1Origin := eth.BlockID{Hash: l1Hash, Number: l1Number} return eth.L2BlockRef{ Hash: payload.BlockHash, diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 7ade4a42df4e..7a4cba672974 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -89,7 +89,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, Transactions: payload.Transactions[depositStart:], }, } - ref, err := l2.PayloadToBlockRef(payload) + ref, err := l2.PayloadToBlockRef(payload, &d.Config.Genesis) return ref, batch, err } @@ -191,7 +191,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) } - newLast, err := l2.PayloadToBlockRef(payload) + newLast, err := l2.PayloadToBlockRef(payload, &d.Config.Genesis) if err != nil { return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to derive block references: %w", err) } From 39fe50a76e070e34cb17b0f048c779d7646441be Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 8 Apr 2022 10:02:29 -0600 Subject: [PATCH 464/585] init: integration tests (#344) Co-authored-by: Javed Khan --- .github/workflows/devnet-ci.yml | 39 + .gitignore | 4 + Makefile | 19 +- README.md | 9 +- ops/genesis-l1.json | 5 +- ops/genesis-l2.json | 5 +- packages/integration-tests/.gitignore | 2 + .../integration-tests/contracts/Counter.sol | 15 + .../integration-tests/contracts/ERC20.sol | 72 + .../contracts/MultiDepositor.sol | 27 + .../integration-tests/contracts/Reverter.sol | 9 + packages/integration-tests/package.json | 70 + .../integration-tests/test/deposit.spec.ts | 95 + packages/integration-tests/test/rpc.spec.ts | 48 + .../test/shared/constants.ts | 1 + packages/integration-tests/test/shared/env.ts | 59 + .../integration-tests/test/shared/setup.ts | 10 + .../integration-tests/test/shared/utils.ts | 11 + packages/integration-tests/tsconfig.json | 17 + packages/integration-tests/yarn.lock | 9237 +++++++++++++++++ tsconfig.json | 23 + 21 files changed, 9772 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/devnet-ci.yml create mode 100644 packages/integration-tests/.gitignore create mode 100644 packages/integration-tests/contracts/Counter.sol create mode 100644 packages/integration-tests/contracts/ERC20.sol create mode 100644 packages/integration-tests/contracts/MultiDepositor.sol create mode 100644 packages/integration-tests/contracts/Reverter.sol create mode 100644 packages/integration-tests/package.json create mode 100644 packages/integration-tests/test/deposit.spec.ts create mode 100644 packages/integration-tests/test/rpc.spec.ts create mode 100644 packages/integration-tests/test/shared/constants.ts create mode 100644 packages/integration-tests/test/shared/env.ts create mode 100644 packages/integration-tests/test/shared/setup.ts create mode 100644 packages/integration-tests/test/shared/utils.ts create mode 100644 packages/integration-tests/tsconfig.json create mode 100644 packages/integration-tests/yarn.lock create mode 100644 tsconfig.json diff --git a/.github/workflows/devnet-ci.yml b/.github/workflows/devnet-ci.yml new file mode 100644 index 000000000000..22a119dfad42 --- /dev/null +++ b/.github/workflows/devnet-ci.yml @@ -0,0 +1,39 @@ +name: Devnet integration tests + +on: + push: + branches: + - 'main' + - 'staging' + - 'feat/*' + pull_request: + workflow_dispatch: + +jobs: + compose-devnet: + runs-on: ubuntu-latest + name: Run integration tests on devnet + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + + - uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'yarn' + + - run: | + curl -L -o /tmp/foundry.tgz https://github.com/gakonst/foundry/releases/download/nightly-9c2469488c6872e5d17198555f7d8e1a80173151/foundry_nightly_linux_amd64.tar.gz + tar -xzvf /tmp/foundry.tgz + mv forge /usr/local/bin + mv cast /usr/local/bin + name: Install forge + + - run: cd packages/contracts && yarn install && yarn build + - run: cd packages/integration-tests && yarn install && yarn build:contracts + + - run: make devnet-up + name: Bring up the stack + + - run: sleep 10 && docker ps && make integration-tests \ No newline at end of file diff --git a/.gitignore b/.gitignore index 44f8fca85218..6a916fac28bc 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ bin # vim swap files *.sw* + +integration-tests/cache/ +integration-tests/artifacts/ +**/*.env \ No newline at end of file diff --git a/Makefile b/Makefile index ef7294288957..21552d596667 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +COMPOSEFLAGS=-d +ITESTS_L2_HOST=http://localhost:9545 + build: submodules opnode contracts .PHONY: build @@ -41,9 +44,23 @@ devnet-up: L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ WITHDRAWER_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json | jq .deployedBytecode) \ GENESIS_TIMESTAMP=$(shell date +%s) \ - BUILDKIT_PROGRESS=plain DOCKER_BUILDKIT=1 docker-compose up --build) + BUILDKIT_PROGRESS=plain DOCKER_BUILDKIT=1 docker-compose up --build $(COMPOSEFLAGS)) .PHONY: devnet-up devnet-down: @(cd ./ops && docker-compose down -v) .PHONY: devnet-stop + +integration-tests: + curl \ + --fail \ + --retry 10 \ + --retry-delay 2 \ + --retry-connrefused \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + $(ITESTS_L2_HOST) + + cd packages/integration-tests && yarn test +.PHONY: integration-tests \ No newline at end of file diff --git a/README.md b/README.md index 85656c4573f3..c9f84b1611bc 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ Note that you will need to specify the L2 chain ID manually if you use Metamask. The devnet comes with a pre-funded account you can use as a faucet: -- Address: `0xde3829a23df1479438622a08a116e8eb3f620bb5` -- Private key: `bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7` +- Address: `0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266` +- Private key: `ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` The faucet account exists on both L1 and L2. To deposit onto L2 from L1, you can use the `deposit` hardhat task. Run the following from the `packags/contracts` directory: @@ -53,6 +53,11 @@ L2_PROVIDER_URL=http://localhost:8546 PRIVATE_KEY=bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 ``` +The batch submitter uses the account below to submit batches to L1: + +- Address: `0xde3829a23df1479438622a08a116e8eb3f620bb5` +- Private key: `bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7` + ## Contributing ### Basic Contributions diff --git a/ops/genesis-l1.json b/ops/genesis-l1.json index e5ff1cc6e53f..7f38d28636a8 100644 --- a/ops/genesis-l1.json +++ b/ops/genesis-l1.json @@ -20,7 +20,7 @@ "nonce": "0x0", "timestamp": "", "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000ca062b0fd91172d89bcd4bb084ac4e21972cc4670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0x47b760", + "gasLimit": "0xE4E1C0", "difficulty": "0x1", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x0000000000000000000000000000000000000000", @@ -796,6 +796,9 @@ "de3829a23df1479438622a08a116e8eb3f620bb5": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, + "f39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, "deaddeaddeaddeaddeaddeaddeaddeaddead0001": { "code": "", "balance": "0x0" diff --git a/ops/genesis-l2.json b/ops/genesis-l2.json index b3a1dbd491da..565b154714a1 100644 --- a/ops/genesis-l2.json +++ b/ops/genesis-l2.json @@ -18,7 +18,7 @@ "nonce": "0x1234", "timestamp": "", "extraData": "0x", - "gasLimit": "0x4c4b40", + "gasLimit": "0xE4E1C0", "difficulty": "0x1", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x0000000000000000000000000000000000000000", @@ -794,6 +794,9 @@ "de3829a23df1479438622a08a116e8eb3f620bb5": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, + "f39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, "4200000000000000000000000000000000000014": { "code": "", "balance": "0x0" diff --git a/packages/integration-tests/.gitignore b/packages/integration-tests/.gitignore new file mode 100644 index 000000000000..1f343a97af99 --- /dev/null +++ b/packages/integration-tests/.gitignore @@ -0,0 +1,2 @@ +artifacts +cache \ No newline at end of file diff --git a/packages/integration-tests/contracts/Counter.sol b/packages/integration-tests/contracts/Counter.sol new file mode 100644 index 000000000000..195f8eed57b1 --- /dev/null +++ b/packages/integration-tests/contracts/Counter.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.8.10; + +contract Counter { + uint256 public value = 0; + + constructor() {} + + function getValue() public view returns (uint256) { + return value; + } + + function incValue() public { + value++; + } +} \ No newline at end of file diff --git a/packages/integration-tests/contracts/ERC20.sol b/packages/integration-tests/contracts/ERC20.sol new file mode 100644 index 000000000000..c67efd462b79 --- /dev/null +++ b/packages/integration-tests/contracts/ERC20.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +contract ERC20 { + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); + + uint256 constant private MAX_UINT256 = 2**256 - 1; + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowed; + /* + NOTE: + The following variables are OPTIONAL vanities. One does not have to include them. + They allow one to customise the token contract & in no way influences the core functionality. + Some wallets/interfaces might not even bother to look at this information. + */ + string public name; //fancy name: eg OVM Coin + uint8 public decimals; //How many decimals to show. + string public symbol; //An identifier: eg OVM + uint256 public totalSupply; + + constructor( + uint256 _initialAmount, + string memory _tokenName, + uint8 _decimalUnits, + string memory _tokenSymbol + ) public { + balances[msg.sender] = _initialAmount; // Give the creator all initial tokens + totalSupply = _initialAmount; // Update total supply + name = _tokenName; // Set the name for display purposes + decimals = _decimalUnits; // Amount of decimals for display purposes + symbol = _tokenSymbol; // Set the symbol for display purposes + } + + function transfer(address _to, uint256 _value) public returns (bool success) { + require(balances[msg.sender] >= _value, "insufficient balance"); + balances[msg.sender] -= _value; + balances[_to] += _value; + emit Transfer(msg.sender, _to, _value); + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { + uint256 allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value, "bad allowance"); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT256) { + allowed[_from][msg.sender] -= _value; + } + emit Transfer(_from, _to, _value); + return true; + } + + function balanceOf(address _owner) public view returns (uint256 balance) { + return balances[_owner]; + } + + function approve(address _spender, uint256 _value) public returns (bool success) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } + + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} diff --git a/packages/integration-tests/contracts/MultiDepositor.sol b/packages/integration-tests/contracts/MultiDepositor.sol new file mode 100644 index 000000000000..50658b458097 --- /dev/null +++ b/packages/integration-tests/contracts/MultiDepositor.sol @@ -0,0 +1,27 @@ +pragma solidity 0.8.10; + +interface DepositFeed { + function depositTransaction( + address _to, + uint256 _value, + uint256 _gasLimit, + bool _isCreation, + bytes memory _data + ) external payable; +} + +contract MultiDepositor { + DepositFeed df = DepositFeed(0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001); + + function deposit(address to) external payable { + for (uint i = 0; i < 3; i++) { + df.depositTransaction{ value: 1000000000 }( + to, + 1000, + 3000000, + false, + "" + ); + } + } +} \ No newline at end of file diff --git a/packages/integration-tests/contracts/Reverter.sol b/packages/integration-tests/contracts/Reverter.sol new file mode 100644 index 000000000000..2fbda79b4d66 --- /dev/null +++ b/packages/integration-tests/contracts/Reverter.sol @@ -0,0 +1,9 @@ +pragma solidity 0.8.10; + +contract Reverter { + string constant public revertMessage = "This is a simple reversion."; + + function doRevert() public pure { + revert(revertMessage); + } +} \ No newline at end of file diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json new file mode 100644 index 000000000000..c2bd35b97365 --- /dev/null +++ b/packages/integration-tests/package.json @@ -0,0 +1,70 @@ +{ + "private": true, + "name": "@eth-optimism/integration-tests", + "version": "0.5.9", + "description": "[Optimism] Integration tests", + "scripts": { + "lint": "yarn lint:fix && yarn lint:check", + "lint:fix": "yarn lint:check --fix", + "lint:check": "eslint . --max-warnings=0", + "build:contracts": "forge build --root . -c contracts -o artifacts", + "test": "ts-mocha --timeout 30000 test/**/*.spec.ts", + "test:actor": "IS_LIVE_NETWORK=true ts-node actor-tests/lib/runner.ts", + "test:integration:live": "NO_NETWORK=true IS_LIVE_NETWORK=true hardhat --network optimism test", + "clean": "rimraf cache artifacts", + "pre-commit": "lint-staged" + }, + "keywords": [ + "optimism", + "ethereum", + "integration", + "tests" + ], + "homepage": "https://github.com/ethereum-optimism/optimism/tree/develop/packages/integration-tests#readme", + "license": "MIT", + "author": "Optimism PBC", + "repository": { + "type": "git", + "url": "https://github.com/ethereum-optimism/optimism.git" + }, + "devDependencies": { + "@eth-optimism/contracts": "0.5.20", + "@eth-optimism/core-utils": "0.8.3", + "@eth-optimism/sdk": "1.0.4", + "@ethersproject/abstract-provider": "^5.5.1", + "@ethersproject/providers": "^5.5.3", + "@ethersproject/transactions": "^5.5.0", + "@types/chai": "^4.2.18", + "@types/chai-as-promised": "^7.1.4", + "@types/mocha": "^8.2.2", + "@types/rimraf": "^3.0.0", + "@typescript-eslint/eslint-plugin": "^4.26.0", + "@typescript-eslint/parser": "^4.26.0", + "async-mutex": "^0.3.2", + "babel-eslint": "^10.1.0", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.1", + "commander": "^8.3.0", + "dotenv": "^10.0.0", + "envalid": "^7.1.0", + "eslint": "^7.27.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-import": "^2.23.4", + "eslint-plugin-jsdoc": "^35.1.2", + "eslint-plugin-prefer-arrow": "^1.2.3", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-react": "^7.24.0", + "eslint-plugin-unicorn": "^32.0.1", + "ethereum-waffle": "^3.3.0", + "ethers": "^5.5.4", + "mocha": "^8.4.0", + "node-fetch": "^2.6.7", + "prom-client": "^14.0.1", + "rimraf": "^3.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.3.5" + }, + "dependencies": { + "ts-mocha": "^9.0.2" + } +} diff --git a/packages/integration-tests/test/deposit.spec.ts b/packages/integration-tests/test/deposit.spec.ts new file mode 100644 index 000000000000..80846c1425f4 --- /dev/null +++ b/packages/integration-tests/test/deposit.spec.ts @@ -0,0 +1,95 @@ +/* Imports: External */ +import { Contract, ContractFactory, utils, Wallet } from 'ethers' +import { awaitCondition } from '@eth-optimism/core-utils' + +/* Imports: Internal */ +import { DEPOSIT_FEED_ADDR } from './shared/constants' +import { defaultTransactionFactory } from './shared/utils' +import env from './shared/env' + +const depositFeedArtifact = require('../../contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json') +const counterArtifact = require('../artifacts/Counter.sol/Counter.json') +const multiDepositorArtifact = require('../artifacts/MultiDepositor.sol/MultiDepositor.json') + +describe('Deposits', () => { + let depositFeed: Contract + + before(() => { + depositFeed = new Contract( + DEPOSIT_FEED_ADDR, + depositFeedArtifact.abi, + ).connect(env.l1Wallet) + }) + + it('should deposit value', async () => { + const recipWallet = Wallet.createRandom().connect(env.l2Provider) + const tx = defaultTransactionFactory() + tx.value = utils.parseEther('1.337') + tx.to = recipWallet.address + const result = await depositFeed.depositTransaction( + tx.to, + tx.value, + '3000000', + false, + [], + { + value: tx.value, + }, + ) + await result.wait() + + await awaitCondition(async () => { + const bal = await recipWallet.getBalance() + return bal.eq(tx.value) + }) + }) + + it('should support multiple deposits in a single tx', async () => { + const recipWallet = Wallet.createRandom().connect(env.l2Provider) + const value = utils.parseEther('0.1') + const factory = new ContractFactory( + multiDepositorArtifact.abi, + multiDepositorArtifact.bytecode.object, + ).connect(env.l1Wallet) + const contract = await factory.deploy() + const tx = await contract.deposit(recipWallet.address, { + value, + }) + await tx.wait() + + await awaitCondition(async () => { + const bal = await recipWallet.getBalance() + return bal.eq('3000') + }) + }) + + it.skip('should deposit a contract creation', async () => { + const value = utils.parseEther('0.1') + const factory = new ContractFactory( + counterArtifact.abi, + counterArtifact.bytecode.object, + ) + const tx = await factory.getDeployTransaction() + const result = await depositFeed.depositTransaction( + `0x${'0'.repeat(40)}`, + '0', + '3000000', + true, + tx.data, + { + value: value, + }, + ) + await result.wait() + const l2Nonce = await env.l2Wallet.getTransactionCount() + const addr = utils.getContractAddress({ + from: env.l2Wallet.address, + nonce: l2Nonce, + }) + + await awaitCondition(async () => { + const code = await env.l2Provider.getCode(addr) + return code === counterArtifact.bytecode.object + }) + }) +}) diff --git a/packages/integration-tests/test/rpc.spec.ts b/packages/integration-tests/test/rpc.spec.ts new file mode 100644 index 000000000000..009f5a0e78e4 --- /dev/null +++ b/packages/integration-tests/test/rpc.spec.ts @@ -0,0 +1,48 @@ +/* Imports: External */ +import { ContractFactory, Wallet } from 'ethers' + +/* Imports: Internal */ +import { expect } from './shared/setup' +import { defaultTransactionFactory } from './shared/utils' +import env from './shared/env' + +const counterArtifact = require('../artifacts/Counter.sol/Counter.json') + +describe('RPCs', () => { + let wallet: Wallet + + before(async () => { + wallet = env.l2Wallet + }) + + it('eth_chainId', async () => { + const network = await env.l2Provider.getNetwork() + expect(network.chainId).to.equal(901) + }) + + describe('eth_sendRawTransaction', () => { + it('should correctly process a funds transfer', async () => { + const altWallet = await Wallet.createRandom().connect(env.l2Provider) + const tx = defaultTransactionFactory() + tx.to = altWallet.address + const nonce = await wallet.getTransactionCount() + const result = await wallet.sendTransaction(tx) + + expect(result.from).to.equal(wallet.address) + expect(result.nonce).to.equal(nonce) + expect(result.gasLimit.toNumber()).to.equal(tx.gasLimit) + expect(result.data).to.equal(tx.data) + expect(await altWallet.getBalance()).to.equal(tx.value) + }) + + it('should correctly process a contract creation', async () => { + const factory = new ContractFactory( + counterArtifact.abi, + counterArtifact.bytecode.object, + ).connect(wallet) + const counter = await factory.deploy() + await counter.deployed() + expect(await env.l2Provider.getCode(counter.address)).not.to.equal('0x') + }) + }) +}) diff --git a/packages/integration-tests/test/shared/constants.ts b/packages/integration-tests/test/shared/constants.ts new file mode 100644 index 000000000000..5e3b956088ba --- /dev/null +++ b/packages/integration-tests/test/shared/constants.ts @@ -0,0 +1 @@ +export const DEPOSIT_FEED_ADDR = '0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001' \ No newline at end of file diff --git a/packages/integration-tests/test/shared/env.ts b/packages/integration-tests/test/shared/env.ts new file mode 100644 index 000000000000..df6993f226a9 --- /dev/null +++ b/packages/integration-tests/test/shared/env.ts @@ -0,0 +1,59 @@ +/* Imports: External */ +import { Wallet, providers } from 'ethers' +import { bool, cleanEnv, num, str } from 'envalid' + +/* Imports: Internal */ +import { asL2Provider } from '@eth-optimism/sdk' +import dotenv from 'dotenv' + +dotenv.config() + +const procEnv = cleanEnv(process.env, { + L1_URL: str({default: 'http://localhost:8545'}), + L1_POLLING_INTERVAL: num({default: 10}), + + L2_URL: str({default: 'http://localhost:9545'}), + L2_POLLING_INTERVAL: num({default: 1}), + + PRIVATE_KEY: str({ + default: + 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', + }), + + MOCHA_TIMEOUT: num({ + default: 120_000, + }), + MOCHA_BAIL: bool({ + default: false, + }), +}) + +/// Helper class for instantiating a test environment with a funded account +export class OptimismEnv { + // The wallets + l1Wallet: Wallet + l2Wallet: Wallet + + // The providers + l1Provider: providers.JsonRpcProvider + l2Provider: providers.JsonRpcProvider + + constructor() { + const l1Provider = new providers.JsonRpcProvider(procEnv.L1_URL) + l1Provider.pollingInterval = procEnv.L1_POLLING_INTERVAL + + const l2Provider = new providers.JsonRpcProvider(procEnv.L2_URL) + l2Provider.pollingInterval = procEnv.L2_POLLING_INTERVAL + + const l1Wallet = new Wallet(procEnv.PRIVATE_KEY, l1Provider) + const l2Wallet = new Wallet(procEnv.PRIVATE_KEY, l2Provider) + + this.l1Wallet = l1Wallet + this.l2Wallet = l2Wallet + this.l1Provider = l1Provider + this.l2Provider = l2Provider + } +} + +const env = new OptimismEnv() +export default env \ No newline at end of file diff --git a/packages/integration-tests/test/shared/setup.ts b/packages/integration-tests/test/shared/setup.ts new file mode 100644 index 000000000000..282087e24374 --- /dev/null +++ b/packages/integration-tests/test/shared/setup.ts @@ -0,0 +1,10 @@ +/* External Imports */ +import chai = require('chai') +import chaiAsPromised from 'chai-as-promised' +import { solidity } from 'ethereum-waffle' + +chai.use(solidity) +chai.use(chaiAsPromised) +const expect = chai.expect + +export { expect } \ No newline at end of file diff --git a/packages/integration-tests/test/shared/utils.ts b/packages/integration-tests/test/shared/utils.ts new file mode 100644 index 000000000000..3db4bd67120c --- /dev/null +++ b/packages/integration-tests/test/shared/utils.ts @@ -0,0 +1,11 @@ +import { BigNumber } from 'ethers' + +export const defaultTransactionFactory = () => { + return { + to: '0x' + '1234'.repeat(10), + gasLimit: 8_000_000, + data: '0x', + value: BigNumber.from(0), + } +} + diff --git a/packages/integration-tests/tsconfig.json b/packages/integration-tests/tsconfig.json new file mode 100644 index 000000000000..3c305d96699e --- /dev/null +++ b/packages/integration-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "declaration": true, + "resolveJsonModule": true + }, + "include": [ + "./test", + "./artifacts/**/*.json", + "./tasks/**/*.ts", + "./package.json" + ] +} diff --git a/packages/integration-tests/yarn.lock b/packages/integration-tests/yarn.lock new file mode 100644 index 000000000000..a5de871a24ea --- /dev/null +++ b/packages/integration-tests/yarn.lock @@ -0,0 +1,9237 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.17.7": + version "7.17.7" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz" + integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ== + +"@babel/core@^7.12.16": + version "7.17.8" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz" + integrity sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.7" + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-module-transforms" "^7.17.7" + "@babel/helpers" "^7.17.8" + "@babel/parser" "^7.17.8" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + +"@babel/eslint-parser@^7.12.16": + version "7.17.0" + resolved "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz" + integrity sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA== + dependencies: + eslint-scope "^5.1.1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.0" + +"@babel/generator@^7.17.3", "@babel/generator@^7.17.7": + version "7.17.7" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz" + integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-compilation-targets@^7.17.7": + version "7.17.7" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz" + integrity sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w== + dependencies: + "@babel/compat-data" "^7.17.7" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.17.7": + version "7.17.7" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz" + integrity sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.17.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + +"@babel/helper-simple-access@^7.17.7": + version "7.17.7" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz" + integrity sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA== + dependencies: + "@babel/types" "^7.17.0" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helpers@^7.17.8": + version "7.17.8" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz" + integrity sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.17.8", "@babel/parser@^7.7.0": + version "7.17.8" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz" + integrity sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ== + +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.17.3", "@babel/traverse@^7.7.0": + version "7.17.3" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.7.0": + version "7.17.0" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.npmjs.org/@ensdomains/resolver/-/resolver-0.2.4.tgz" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + +"@es-joy/jsdoccomment@0.9.0-alpha.1": + version "0.9.0-alpha.1" + resolved "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.9.0-alpha.1.tgz" + integrity sha512-Clxxc0PwpISoYYBibA+1L2qFJ7gvFVhI2Hos87S06K+Q0cXdOhZQJNKWuaQGPAeHjZEuUB/YoWOfwjuF2wirqA== + dependencies: + comment-parser "1.1.6-beta.0" + esquery "^1.4.0" + jsdoc-type-pratt-parser "1.0.4" + +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@eth-optimism/contracts@0.5.20": + version "0.5.20" + resolved "https://registry.npmjs.org/@eth-optimism/contracts/-/contracts-0.5.20.tgz" + integrity sha512-HliboXKsiCFJdtiOlqJH2ZS+u9lkvXqCufpSnNCOrvxD4J3O8VkGUZib2Zelaz6srIX+23z9zM5JvqLYX/bubA== + dependencies: + "@eth-optimism/core-utils" "0.8.3" + "@ethersproject/abstract-provider" "^5.5.1" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/hardware-wallets" "^5.5.0" + +"@eth-optimism/core-utils@0.8.3": + version "0.8.3" + resolved "https://registry.npmjs.org/@eth-optimism/core-utils/-/core-utils-0.8.3.tgz" + integrity sha512-jM3dPAg9TinskLyH4w9KofEqgLWJsf5VrlC8a2/0zKNlZUJuVzE/ZYfcq243qqlJn1vb4QkBKjYVHKMu1Wjzjg== + dependencies: + "@ethersproject/abstract-provider" "^5.5.1" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/providers" "^5.5.3" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.1" + bufio "^1.0.7" + chai "^4.3.4" + ethers "^5.5.4" + +"@eth-optimism/sdk@1.0.4": + version "1.0.4" + resolved "https://registry.npmjs.org/@eth-optimism/sdk/-/sdk-1.0.4.tgz" + integrity sha512-bvnn4vHPADiq7I7JjXIGQq/OqTAf3k2u9PCQwc3xYZnfHeklanl/lL62JZtSI55rEugbXX/sRCIAp0TPdFTUTA== + dependencies: + "@eth-optimism/contracts" "0.5.20" + "@eth-optimism/core-utils" "0.8.3" + lodash "^4.17.21" + merkletreejs "^0.2.27" + rlp "^2.2.7" + +"@ethereum-waffle/chai@^3.4.4": + version "3.4.4" + resolved "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-3.4.4.tgz" + integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== + dependencies: + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.5.2" + +"@ethereum-waffle/compiler@^3.4.4": + version "3.4.4" + resolved "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz" + integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.4.4": + version "3.4.4" + resolved "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.4.4.tgz" + integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.4.4": + version "3.4.4" + resolved "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz" + integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + +"@ethereum-waffle/provider@^3.4.4": + version "3.4.4" + resolved "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.4.4.tgz" + integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== + dependencies: + "@ethereum-waffle/ens" "^3.4.4" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + +"@ethersproject/abi@5.6.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.6.0.tgz" + integrity sha512-AhVByTwdXCc2YQ20v300w6KVHle9g2OFc28ZAFCPnJyEpkv1xKXjZcSTgWOlv1i+0dqlgF8RCF2Rn2KC1t+1Vg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/abstract-provider@5.6.0", "@ethersproject/abstract-provider@^5.5.1", "@ethersproject/abstract-provider@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz" + integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + +"@ethersproject/abstract-signer@5.6.0", "@ethersproject/abstract-signer@^5.5.0", "@ethersproject/abstract-signer@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz" + integrity sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/address@5.6.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.0.tgz" + integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + +"@ethersproject/base64@5.6.0", "@ethersproject/base64@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.0.tgz" + integrity sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + +"@ethersproject/basex@5.6.0", "@ethersproject/basex@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.6.0.tgz" + integrity sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/bignumber@5.6.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.0.tgz" + integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + bn.js "^4.11.9" + +"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@^5.6.0": + version "5.6.1" + resolved "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.1.tgz" + integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/constants@5.6.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.0.tgz" + integrity sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + +"@ethersproject/contracts@5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.6.0.tgz" + integrity sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw== + dependencies: + "@ethersproject/abi" "^5.6.0" + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + +"@ethersproject/hardware-wallets@^5.5.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/hardware-wallets/-/hardware-wallets-5.6.0.tgz" + integrity sha512-jq/9osE7mfH6Ur4/N2/EdrgRuXacXlCzp5Irvyy8sWM3xMuzg2Git8czEFdFFTfLO6IBVxfEi1ANb+76tsa8BA== + dependencies: + "@ledgerhq/hw-app-eth" "5.27.2" + "@ledgerhq/hw-transport" "5.26.0" + "@ledgerhq/hw-transport-u2f" "5.26.0" + ethers "^5.6.0" + optionalDependencies: + "@ledgerhq/hw-transport-node-hid" "5.26.0" + +"@ethersproject/hash@5.6.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.0.tgz" + integrity sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/hdnode@5.6.0", "@ethersproject/hdnode@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.6.0.tgz" + integrity sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + +"@ethersproject/json-wallets@5.6.0", "@ethersproject/json-wallets@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz" + integrity sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.6.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.0.tgz" + integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== + dependencies: + "@ethersproject/bytes" "^5.6.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.6.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz" + integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== + +"@ethersproject/networks@5.6.1", "@ethersproject/networks@^5.6.0": + version "5.6.1" + resolved "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.1.tgz" + integrity sha512-b2rrupf3kCTcc3jr9xOWBuHylSFtbpJf79Ga7QR98ienU2UqGimPGEsYMgbI29KHJfA5Us89XwGVmxrlxmSrMg== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/pbkdf2@5.6.0", "@ethersproject/pbkdf2@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz" + integrity sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + +"@ethersproject/properties@5.6.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz" + integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/providers@5.6.2", "@ethersproject/providers@^5.5.3": + version "5.6.2" + resolved "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.2.tgz" + integrity sha512-6/EaFW/hNWz+224FXwl8+HdMRzVHt8DpPmu5MZaIQqx/K/ELnC9eY236SMV7mleCM3NnEArFwcAAxH5kUUgaRg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.6.0", "@ethersproject/random@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/random/-/random-5.6.0.tgz" + integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/rlp@5.6.0", "@ethersproject/rlp@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.0.tgz" + integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/sha2@5.6.0", "@ethersproject/sha2@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.6.0.tgz" + integrity sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.6.0", "@ethersproject/signing-key@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz" + integrity sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.6.0.tgz" + integrity sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/strings@5.6.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.0.tgz" + integrity sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/transactions@5.6.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.5.0", "@ethersproject/transactions@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.0.tgz" + integrity sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + +"@ethersproject/units@5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/units/-/units-5.6.0.tgz" + integrity sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/wallet@5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.6.0.tgz" + integrity sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/json-wallets" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + +"@ethersproject/web@5.6.0", "@ethersproject/web@^5.5.1", "@ethersproject/web@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.0.tgz" + integrity sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg== + dependencies: + "@ethersproject/base64" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/wordlists@5.6.0", "@ethersproject/wordlists@^5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.6.0.tgz" + integrity sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.5" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@ledgerhq/cryptoassets@^5.27.2": + version "5.53.0" + resolved "https://registry.npmjs.org/@ledgerhq/cryptoassets/-/cryptoassets-5.53.0.tgz" + integrity sha512-M3ibc3LRuHid5UtL7FI3IC6nMEppvly98QHFoSa7lJU0HDzQxY6zHec/SPM4uuJUC8sXoGVAiRJDkgny54damw== + dependencies: + invariant "2" + +"@ledgerhq/devices@^5.26.0", "@ledgerhq/devices@^5.51.1": + version "5.51.1" + resolved "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz" + integrity sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA== + dependencies: + "@ledgerhq/errors" "^5.50.0" + "@ledgerhq/logs" "^5.50.0" + rxjs "6" + semver "^7.3.5" + +"@ledgerhq/errors@^5.26.0", "@ledgerhq/errors@^5.50.0": + version "5.50.0" + resolved "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz" + integrity sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow== + +"@ledgerhq/hw-app-eth@5.27.2": + version "5.27.2" + resolved "https://registry.npmjs.org/@ledgerhq/hw-app-eth/-/hw-app-eth-5.27.2.tgz" + integrity sha512-llNdrE894cCN8j6yxJEUniciyLVcLmu5N0UmIJLOObztG+5rOF4bX54h4SreTWK+E10Z0CzHSeyE5Lz/tVcqqQ== + dependencies: + "@ledgerhq/cryptoassets" "^5.27.2" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + bignumber.js "^9.0.1" + rlp "^2.2.6" + +"@ledgerhq/hw-transport-node-hid-noevents@^5.26.0": + version "5.51.1" + resolved "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.51.1.tgz" + integrity sha512-9wFf1L8ZQplF7XOY2sQGEeOhpmBRzrn+4X43kghZ7FBDoltrcK+s/D7S+7ffg3j2OySyP6vIIIgloXylao5Scg== + dependencies: + "@ledgerhq/devices" "^5.51.1" + "@ledgerhq/errors" "^5.50.0" + "@ledgerhq/hw-transport" "^5.51.1" + "@ledgerhq/logs" "^5.50.0" + node-hid "2.1.1" + +"@ledgerhq/hw-transport-node-hid@5.26.0": + version "5.26.0" + resolved "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-5.26.0.tgz" + integrity sha512-qhaefZVZatJ6UuK8Wb6WSFNOLWc2mxcv/xgsfKi5HJCIr4bPF/ecIeN+7fRcEaycxj4XykY6Z4A7zDVulfFH4w== + dependencies: + "@ledgerhq/devices" "^5.26.0" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + "@ledgerhq/hw-transport-node-hid-noevents" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" + lodash "^4.17.20" + node-hid "1.3.0" + usb "^1.6.3" + +"@ledgerhq/hw-transport-u2f@5.26.0": + version "5.26.0" + resolved "https://registry.npmjs.org/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.26.0.tgz" + integrity sha512-QTxP1Rsh+WZ184LUOelYVLeaQl3++V3I2jFik+l9JZtakwEHjD0XqOT750xpYNL/vfHsy31Wlz+oicdxGzFk+w== + dependencies: + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" + u2f-api "0.2.7" + +"@ledgerhq/hw-transport@5.26.0": + version "5.26.0" + resolved "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.26.0.tgz" + integrity sha512-NFeJOJmyEfAX8uuIBTpocWHcz630sqPcXbu864Q+OCBm4EK5UOKV1h/pX7e0xgNIKY8zhJ/O4p4cIZp9tnXLHQ== + dependencies: + "@ledgerhq/devices" "^5.26.0" + "@ledgerhq/errors" "^5.26.0" + events "^3.2.0" + +"@ledgerhq/hw-transport@^5.26.0", "@ledgerhq/hw-transport@^5.51.1": + version "5.51.1" + resolved "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz" + integrity sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw== + dependencies: + "@ledgerhq/devices" "^5.51.1" + "@ledgerhq/errors" "^5.50.0" + events "^3.3.0" + +"@ledgerhq/logs@^5.26.0", "@ledgerhq/logs@^5.50.0": + version "5.50.0" + resolved "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz" + integrity sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.3.3.tgz" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.3.3.tgz" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + hosted-git-info "^2.6.0" + path-browserify "^1.0.0" + url "^0.11.0" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": + version "4.11.6" + resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + +"@types/chai-as-promised@^7.1.4": + version "7.1.5" + resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.2.18": + version "4.3.0" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz" + integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== + +"@types/glob@*": + version "7.2.0" + resolved "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/json-schema@^7.0.7": + version "7.0.11" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/minimatch@*": + version "3.0.5" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/mocha@^8.2.2": + version "8.2.3" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz" + integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== + +"@types/node-fetch@^2.5.5": + version "2.6.1" + resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz" + integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "17.0.23" + resolved "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz" + integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== + +"@types/node@^12.12.6": + version "12.20.47" + resolved "https://registry.npmjs.org/@types/node/-/node-12.20.47.tgz" + integrity sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg== + +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + version "2.4.4" + resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz" + integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA== + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + +"@types/rimraf@^3.0.0": + version "3.0.2" + resolved "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ== + dependencies: + "@types/glob" "*" + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@^4.26.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== + dependencies: + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@^4.26.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== + dependencies: + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + debug "^4.3.1" + +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.4.1: + version "8.7.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.11.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@4.1.1, ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.1: + version "3.1.2" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.7" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz" + integrity sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs= + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-includes@^3.1.4: + version "3.1.4" + resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz" + integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +array.prototype.flat@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +array.prototype.flatmap@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz" + integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-eventemitter@^0.2.2: + version "0.2.4" + resolved "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async-mutex@^0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz" + integrity sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA== + dependencies: + tslib "^2.3.1" + +async@2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/async/-/async-2.6.2.tgz" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^1.4.2: + version "1.5.2" + resolved "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: + version "2.6.3" + resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz" + integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz" + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= + dependencies: + precond "0.2" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bignumber.js@^9.0.0, bignumber.js@^9.0.1: + version "9.0.2" + resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz" + integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bintrees@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz" + integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ= + +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bluebird@^3.5.0, bluebird@^3.5.2: + version "3.7.2" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: + version "4.12.0" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +body-parser@1.19.2: + version "1.19.2" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz" + integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.9.7" + raw-body "2.4.3" + type-is "~1.6.18" + +body-parser@^1.16.0: + version "1.20.0" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz" + integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.10.3" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserslist@^4.17.5: + version "4.20.2" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz" + integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA== + dependencies: + caniuse-lite "^1.0.30001317" + electron-to-chromium "^1.4.84" + escalade "^3.1.1" + node-releases "^2.0.2" + picocolors "^1.0.0" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz" + integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0, buffer-from@^1.1.0: + version "1.1.2" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-reverse@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/buffer-reverse/-/buffer-reverse-1.0.1.tgz" + integrity sha1-SSg8jvpvkBvAH6MwTQYCeXGuL2A= + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bufferutil@^4.0.1: + version "4.0.6" + resolved "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz" + integrity sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw== + dependencies: + node-gyp-build "^4.3.0" + +bufio@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/bufio/-/bufio-1.0.7.tgz" + integrity sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A== + +builtin-modules@^3.0.0: + version "3.2.0" + resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz" + integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz" + integrity sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI= + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz" + integrity sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4= + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/cachedown/-/cachedown-1.0.0.tgz" + integrity sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU= + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001317: + version "1.0.30001325" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz" + integrity sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== + dependencies: + check-error "^1.0.2" + +chai@^4.3.4: + version "4.3.6" + resolved "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz" + integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= + dependencies: + functional-red-black-tree "^1.0.1" + +chokidar@3.5.1: + version "3.5.1" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + +chownr@^1.1.1, chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.1.1: + version "3.3.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz" + integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== + +cids@^0.7.1: + version "0.7.5" + resolved "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clean-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz" + integrity sha1-jffHquUf02h06PjQW5GAvBGj/tc= + dependencies: + escape-string-regexp "^1.0.5" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@2.1.2, clone@^2.0.0: + version "2.1.2" + resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +comment-parser@1.1.6-beta.0: + version "1.1.6-beta.0" + resolved "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.6-beta.0.tgz" + integrity sha512-q3cA8TSMyqW7wcPSYWzbO/rMahnXgzs4SLG/UIWXdEsnXTFPZkEkWAdNgPiHig2OzxgpPLOh4WwsmClDxndwHw== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.1: + version "1.6.2" + resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-hash@^2.5.2: + version "2.5.2" + resolved "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz" + integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== + dependencies: + cids "^0.7.1" + multicodec "^0.5.5" + multihashes "^0.4.15" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.5.1, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.2: + version "0.4.2" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cookiejar@^2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz" + integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-pure@^3.0.1: + version "3.21.1" + resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz" + integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.5" + resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.5.tgz" + integrity sha512-xqYAhQb4NhCJSRym03dwxpP1bYXpK3y7UN83Bo2WFi3x1Zmzn0SL/6xGoPr+gpt4WmNrgCCX3HPysvOwFOW36w== + dependencies: + node-fetch "2.6.1" + whatwg-fetch "2.0.4" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-browserify@3.12.0: + version "3.12.0" + resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +crypto-js@^3.1.9-1: + version "3.3.0" + resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz" + integrity sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q== + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/d/-/d-1.0.1.tgz" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.2.6: + version "3.2.6" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4.3.1: + version "4.3.1" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +debug@^3.1.0, debug@^3.2.7: + version "3.2.7" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.2.0, decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= + dependencies: + repeating "^2.0.0" + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^3.1.0: + version "3.5.0" + resolved "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +electron-to-chromium@^1.3.47, electron-to-chromium@^1.4.84: + version "1.4.104" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.104.tgz" + integrity sha512-2kjoAyiG7uMyGRM9mx25s3HAzmQG2ayuYXxsFmYugHSDcwxREgLtscZvbL1JcW9S/OemeQ3f/SG6JhDwpnCclQ== + +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +envalid@^7.1.0: + version "7.3.0" + resolved "https://registry.npmjs.org/envalid/-/envalid-7.3.0.tgz" + integrity sha512-RWAAXLU+s884YwbVQ+D8OYRIspo7hvF9zPTvjToVzqZknHwycAuGiiHG/XiI1UDY/PeYSlMwQvMUGb25n06iwA== + dependencies: + tslib "2.3.1" + +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.2" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.2.tgz" + integrity sha512-gfSBJoZdlL2xRiOCy0g8gLMryhoe1TlimjzU99L/31Z8QEGIhVQI+EWwt5lT+AuU9SnorVupXFqqOGqGfsyO6w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.59" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz" + integrity sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-config-prettier@^8.3.0: + version "8.5.0" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== + +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.7.3: + version "2.7.3" + resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz" + integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + +eslint-plugin-import@^2.23.4: + version "2.26.0" + resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz" + integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.3" + has "^1.0.3" + is-core-module "^2.8.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.values "^1.1.5" + resolve "^1.22.0" + tsconfig-paths "^3.14.1" + +eslint-plugin-jsdoc@^35.1.2: + version "35.5.1" + resolved "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.5.1.tgz" + integrity sha512-pPYPWtsykwVEue1tYEyoppBj4dgF7XicF67tLLLraY6RQYBq7qMKjUHji19+hfiTtYKKBD0YfeK8hgjPAE5viw== + dependencies: + "@es-joy/jsdoccomment" "0.9.0-alpha.1" + comment-parser "1.1.6-beta.0" + debug "^4.3.2" + esquery "^1.4.0" + jsdoc-type-pratt-parser "^1.0.4" + lodash "^4.17.21" + regextras "^0.8.0" + semver "^7.3.5" + spdx-expression-parse "^3.0.1" + +eslint-plugin-prefer-arrow@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz" + integrity sha512-J9I5PKCOJretVuiZRGvPQxCbllxGAV/viI20JO3LYblAodofBxyMnZAJ+WGeClHgANnSJberTNoFWWjrWKBuXQ== + +eslint-plugin-prettier@^3.4.0: + version "3.4.1" + resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz" + integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react@^7.24.0: + version "7.29.4" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz" + integrity sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ== + dependencies: + array-includes "^3.1.4" + array.prototype.flatmap "^1.2.5" + doctrine "^2.1.0" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.5" + object.fromentries "^2.0.5" + object.hasown "^1.1.0" + object.values "^1.1.5" + prop-types "^15.8.1" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.6" + +eslint-plugin-unicorn@^32.0.1: + version "32.0.1" + resolved "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-32.0.1.tgz" + integrity sha512-LaZ9utnXtOJjnoDkpm+nQsONUUmyRR0WD6PGROSdQRRW3LRmgK/ZP8wxjW+Ai+2uolKTtuJzLx2mvbIeIoLqpg== + dependencies: + ci-info "^3.1.1" + clean-regexp "^1.0.0" + eslint-template-visitor "^2.3.2" + eslint-utils "^2.1.0" + import-modules "^2.1.0" + is-builtin-module "^3.1.0" + lodash "^4.17.21" + pluralize "^8.0.0" + read-pkg-up "^7.0.1" + regexp-tree "^0.1.23" + reserved-words "^0.1.2" + safe-regex "^2.1.1" + semver "^7.3.5" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-template-visitor@^2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz" + integrity sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA== + dependencies: + "@babel/core" "^7.12.16" + "@babel/eslint-parser" "^7.12.16" + eslint-visitor-keys "^2.0.0" + esquery "^1.3.1" + multimap "^1.1.0" + +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@^7.27.0: + version "7.32.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.1.2" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.3.1, esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: + version "2.0.8" + resolved "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz" + integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz" + integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-3.0.0.tgz" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + dependencies: + buffer "^5.2.1" + elliptic "^6.4.0" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.0" + tweetnacl-util "^0.15.0" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz" + integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + dependencies: + async "^2.1.2" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.6.0" + through2 "^2.0.3" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz" + integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= + +ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-waffle@^3.3.0: + version "3.4.4" + resolved "https://registry.npmjs.org/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz" + integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== + dependencies: + "@ethereum-waffle/chai" "^3.4.4" + "@ethereum-waffle/compiler" "^3.4.4" + "@ethereum-waffle/mock-contract" "^3.4.4" + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz" + integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE= + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8: + version "0.6.8" + resolved "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.1" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + dependencies: + async "^2.0.1" + ethereum-common "0.2.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + dependencies: + async "^2.6.1" + ethashjs "~0.0.7" + ethereumjs-block "~2.2.2" + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.1.0" + flow-stoplight "^1.0.0" + level-mem "^3.0.1" + lru-cache "^5.1.1" + rlp "^2.2.2" + semaphore "^1.1.0" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0: + version "6.2.1" + resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0: + version "7.1.4" + resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz" + integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + core-js-pure "^3.0.1" + ethereumjs-account "^3.0.0" + ethereumjs-block "^2.2.2" + ethereumjs-blockchain "^4.0.3" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.2" + ethereumjs-util "^6.2.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + util.promisify "^1.0.0" + +ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + +ethereumjs-wallet@0.6.5: + version "0.6.5" + resolved "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== + dependencies: + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^6.0.0" + randombytes "^2.0.6" + safe-buffer "^5.1.2" + scryptsy "^1.2.1" + utf8 "^3.0.0" + uuid "^3.3.2" + +ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.4, ethers@^5.6.0: + version "5.6.2" + resolved "https://registry.npmjs.org/ethers/-/ethers-5.6.2.tgz" + integrity sha512-EzGCbns24/Yluu7+ToWnMca3SXJ1Jk1BvWB7CCmVNxyOeM4LLvw2OLuIHhlkhQk1dtOcj9UMsdkxUh8RiG1dxQ== + dependencies: + "@ethersproject/abi" "5.6.0" + "@ethersproject/abstract-provider" "5.6.0" + "@ethersproject/abstract-signer" "5.6.0" + "@ethersproject/address" "5.6.0" + "@ethersproject/base64" "5.6.0" + "@ethersproject/basex" "5.6.0" + "@ethersproject/bignumber" "5.6.0" + "@ethersproject/bytes" "5.6.1" + "@ethersproject/constants" "5.6.0" + "@ethersproject/contracts" "5.6.0" + "@ethersproject/hash" "5.6.0" + "@ethersproject/hdnode" "5.6.0" + "@ethersproject/json-wallets" "5.6.0" + "@ethersproject/keccak256" "5.6.0" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.1" + "@ethersproject/pbkdf2" "5.6.0" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.2" + "@ethersproject/random" "5.6.0" + "@ethersproject/rlp" "5.6.0" + "@ethersproject/sha2" "5.6.0" + "@ethersproject/signing-key" "5.6.0" + "@ethersproject/solidity" "5.6.0" + "@ethersproject/strings" "5.6.0" + "@ethersproject/transactions" "5.6.0" + "@ethersproject/units" "5.6.0" + "@ethersproject/wallet" "5.6.0" + "@ethersproject/web" "5.6.0" + "@ethersproject/wordlists" "5.6.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.3: + version "0.1.6" + resolved "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + +events@^3.0.0, events@^3.2.0, events@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + +express@^4.14.0: + version "4.17.3" + resolved "https://registry.npmjs.org/express/-/express-4.17.3.tgz" + integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.19.2" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.4.2" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.9.7" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.17.2" + serve-static "1.14.2" + setprototypeof "1.2.0" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz" + integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= + dependencies: + checkpoint-store "^1.1.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz" + integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= + dependencies: + node-fetch "~1.7.1" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz" + integrity sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A= + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.1.0: + version "3.2.5" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz" + integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= + +for-each@^0.3.3, for-each@~0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^4.0.2, fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.2.tgz" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + dependencies: + abstract-leveldown "3.0.0" + async "2.6.2" + bip39 "2.5.0" + cachedown "1.0.0" + clone "2.1.2" + debug "3.2.6" + encoding-down "5.0.4" + eth-sig-util "3.0.0" + ethereumjs-abi "0.6.8" + ethereumjs-account "3.0.0" + ethereumjs-block "2.2.2" + ethereumjs-common "1.5.0" + ethereumjs-tx "2.1.2" + ethereumjs-util "6.2.1" + ethereumjs-vm "4.2.0" + heap "0.2.6" + keccak "3.0.1" + level-sublevel "6.6.4" + levelup "3.1.1" + lodash "4.17.20" + lru-cache "5.1.1" + merkle-patricia-tree "3.0.0" + patch-package "6.2.2" + seedrandom "3.0.1" + source-map-support "0.5.12" + tmp "0.1.0" + web3-provider-engine "14.2.1" + websocket "1.0.32" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz" + integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= + +glob-parent@^5.1.2, glob-parent@~5.1.0: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.2, glob@^7.1.3, glob@~7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global@~4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/global/-/global-4.4.0.tgz" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.13.0" + resolved "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz" + integrity sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A== + dependencies: + type-fest "^0.20.2" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globby@^11.0.3: + version "11.1.0" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +got@9.6.0: + version "9.6.0" + resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +got@^7.1.0: + version "7.1.0" + resolved "https://registry.npmjs.org/got/-/got-7.1.0.tgz" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.2.10" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +heap@0.2.6: + version "0.2.6" + resolved "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz" + integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-modules@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz" + integrity sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@2, invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-builtin-module@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz" + integrity sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg== + dependencies: + builtin-modules "^3.0.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.2.0, is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz" + integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-object@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz" + integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-retry-allowed@^1.0.0: + version "1.2.0" + resolved "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + +is-shared-array-buffer@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^1.0.0, is-stream@^1.0.1: + version "1.1.0" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz" + integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== + dependencies: + argparse "^2.0.1" + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdoc-type-pratt-parser@1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.0.4.tgz" + integrity sha512-jzmW9gokeq9+bHPDR1nCeidMyFUikdZlbOhKzh9+/nJqB75XhpNKec1/UuxW5c4+O+Pi31Gc/dCboyfSm/pSpQ== + +jsdoc-type-pratt-parser@^1.0.4: + version "1.2.0" + resolved "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.2.0.tgz" + integrity sha512-4STjeF14jp4bqha44nKMY1OUI6d2/g6uclHWUCZ7B4DoLzaB5bmpTkQrpqU+vSVzMD0LsKAOskcnI3I3VfIpmg== + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + dependencies: + async "^2.0.1" + babel-preset-env "^1.7.0" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz" + integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz" + integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.2.1" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.2.2" + resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.2.tgz" + integrity sha512-HDAyJ4MNQBboGpUnHAVUNJs6X0lh058s6FuixsFGP7MgJYpD6Vasd6nzSG5iIfXu1zAYlHJ/zsOKNlrenTUBnw== + dependencies: + array-includes "^3.1.4" + object.assign "^4.1.2" + +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +keccak@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.npmjs.org/level-errors/-/level-errors-1.1.2.tgz" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz" + integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/level-post/-/level-post-1.0.7.tgz" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.4.tgz" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + dependencies: + bytewise "~1.1.0" + level-codec "^9.0.0" + level-errors "^2.0.0" + level-iterator-stream "^2.0.3" + ltgt "~2.1.1" + pull-defer "^0.2.2" + pull-level "^2.0.3" + pull-stream "^3.6.8" + typewiselite "~1.0.0" + xtend "~4.0.0" + +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz" + integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz" + integrity sha1-Zs0Md0rz1P7axTeU90LbVtqPCew= + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz" + integrity sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k= + +loose-envify@^1.0.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@5.1.1, lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz" + integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= + dependencies: + pseudomap "^1.0.1" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz" + integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz" + integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= + dependencies: + abstract-leveldown "~2.7.1" + functional-red-black-tree "^1.0.1" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + dependencies: + abstract-leveldown "~5.0.0" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + dependencies: + async "^2.6.1" + ethereumjs-util "^5.2.0" + level-mem "^3.0.1" + level-ws "^1.0.0" + readable-stream "^3.0.6" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + dependencies: + async "^1.4.2" + ethereumjs-util "^5.0.0" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkletreejs@^0.2.27: + version "0.2.31" + resolved "https://registry.npmjs.org/merkletreejs/-/merkletreejs-0.2.31.tgz" + integrity sha512-dnK2sE43OebmMe5Qnq1wXvvMIjZjm1u6CcB2KeW6cghlN4p21OpCUr2p56KTVf20KJItNChVsGnimcscp9f+yw== + dependencies: + bignumber.js "^9.0.1" + buffer-reverse "^1.0.1" + crypto-js "^3.1.9-1" + treeify "^1.1.0" + web3-utils "^1.3.4" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.0.4, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6, minimist@~1.2.5: + version "1.2.6" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*: + version "1.0.4" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mocha@^8.4.0: + version "8.4.0" + resolved "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz" + integrity sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.1" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.6" + growl "1.10.5" + he "1.2.0" + js-yaml "4.0.0" + log-symbols "4.0.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.20" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +mock-fs@^4.1.0: + version "4.14.0" + resolved "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz" + integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multicodec@^0.5.5: + version "0.5.7" + resolved "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz" + integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== + dependencies: + varint "^5.0.0" + +multicodec@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^0.4.15, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" + +multimap@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz" + integrity sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw== + +nan@^2.14.0: + version "2.15.0" + resolved "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + +nanoid@3.1.20: + version "3.1.20" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz" + integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-abi@^2.18.0, node-abi@^2.21.0, node-abi@^2.7.0: + version "2.30.1" + resolved "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz" + integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w== + dependencies: + semver "^5.4.1" + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-addon-api@^3.0.2: + version "3.2.1" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + +node-addon-api@^4.2.0: + version "4.3.0" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@~1.7.1: + version "1.7.3" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.4.0" + resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz" + integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== + +node-hid@1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/node-hid/-/node-hid-1.3.0.tgz" + integrity sha512-BA6G4V84kiNd1uAChub/Z/5s/xS3EHBCxotQ0nyYrUG65mXewUDHE1tWOSqA2dp3N+mV0Ffq9wo2AW9t4p/G7g== + dependencies: + bindings "^1.5.0" + nan "^2.14.0" + node-abi "^2.18.0" + prebuild-install "^5.3.4" + +node-hid@2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/node-hid/-/node-hid-2.1.1.tgz" + integrity sha512-Skzhqow7hyLZU93eIPthM9yjot9lszg9xrKxESleEs05V2NcbUptZc5HFqzjOkSmL0sFlZFr3kmvaYebx06wrw== + dependencies: + bindings "^1.5.0" + node-addon-api "^3.0.2" + prebuild-install "^6.0.0" + +node-releases@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz" + integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= + +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +npmlog@^4.0.1: + version "4.1.2" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.12.0, object-inspect@^1.9.0, object-inspect@~1.12.0: + version "1.12.0" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.entries@^1.1.5: + version "1.1.5" + resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz" + integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.fromentries@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz" + integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.getownpropertydescriptors@^2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz" + integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.hasown@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz" + integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz" + integrity sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY= + dependencies: + http-https "^1.0.0" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +open@^7.4.2: + version "7.4.2" + resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-headers@^2.0.0: + version "2.0.5" + resolved "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz" + integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^1.2.1" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +patch-package@^6.2.2: + version "6.4.7" + resolved "https://registry.npmjs.org/patch-package/-/patch-package-6.4.7.tgz" + integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: + version "3.1.2" + resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +prebuild-install@^5.3.4: + version "5.3.6" + resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz" + integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^2.7.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + which-pm-runs "^1.0.0" + +prebuild-install@^6.0.0: + version "6.1.4" + resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz" + integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^2.21.0" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + +precond@0.2: + version "0.2.3" + resolved "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz" + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.1.2: + version "2.6.2" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.npmjs.org/private/-/private-0.1.8.tgz" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +prom-client@^14.0.1: + version "14.0.1" + resolved "https://registry.npmjs.org/prom-client/-/prom-client-14.0.1.tgz" + integrity sha512-HxTArb6fkOntQHoRGvv4qd/BkorjliiuO2uSWC2KC17MUTKYttWdDoXX/vxOhQdkoECEM9BBH0pj2l8G8kev6w== + dependencies: + tdigest "^0.1.1" + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz" + integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.npmjs.org/pull-cat/-/pull-cat-1.1.11.tgz" + integrity sha1-tkLdElXaN2pwa220+pYvX9t0wxs= + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.3.tgz" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/pull-level/-/pull-level-2.0.4.tgz" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + dependencies: + level-post "^1.0.7" + pull-cat "^1.1.9" + pull-live "^1.0.1" + pull-pushable "^2.0.0" + pull-stream "^3.4.0" + pull-window "^2.1.4" + stream-to-pull-stream "^1.7.1" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/pull-live/-/pull-live-1.0.1.tgz" + integrity sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU= + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/pull-pushable/-/pull-pushable-2.2.0.tgz" + integrity sha1-Xy867UethpGfAbEqLpnW8b13ZYE= + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.6.14" + resolved "https://registry.npmjs.org/pull-stream/-/pull-stream-3.6.14.tgz" + integrity sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.npmjs.org/pull-window/-/pull-window-2.1.4.tgz" + integrity sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA= + dependencies: + looper "^2.0.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz" + integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.10.3: + version "6.10.3" + resolved "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + +qs@6.9.7: + version "6.9.7" + resolved "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" + integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.3: + version "2.4.3" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz" + integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== + dependencies: + bytes "3.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.15: + version "1.0.34" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp-tree@^0.1.23, regexp-tree@~0.1.1: + version "0.1.24" + resolved "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz" + integrity sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw== + +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz" + integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^3.1.0: + version "3.2.0" + resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regextras@^0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/regextras/-/regextras-0.8.0.tgz" + integrity sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ== + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +request@^2.79.0, request@^2.85.0: + version "2.88.2" + resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz" + integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= + +require-from-string@^2.0.0, require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +reserved-words@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz" + integrity sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.8.1, resolve@~1.22.0: + version "1.22.0" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.3: + version "2.0.0-next.3" + resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz" + integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz" + integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.2.8, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.6, rlp@^2.2.7: + version "2.2.7" + resolved "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +rxjs@6: + version "6.6.7" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +safe-regex@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz" + integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== + dependencies: + regexp-tree "~0.1.1" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= + dependencies: + pbkdf2 "^3.0.3" + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + +send@0.17.2: + version "0.17.2" + resolved "https://registry.npmjs.org/send/-/send-0.17.2.tgz" + integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "1.8.1" + mime "1.6.0" + ms "2.1.3" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + +serve-static@1.14.2: + version "1.14.2" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" + integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.2" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^2.7.0: + version "2.8.2" + resolved "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +solc@^0.4.20: + version "0.4.26" + resolved "https://registry.npmjs.org/solc/-/solc-0.4.26.tgz" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.npmjs.org/solc/-/solc-0.6.12.tgz" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.matchall@^4.0.6: + version "4.0.7" + resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz" + integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.4.1" + side-channel "^1.0.4" + +string.prototype.trim@~1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz" + integrity sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +swarm-js@^0.1.40: + version "0.1.40" + resolved "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz" + integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^7.1.0" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request "^1.0.1" + +table@^6.0.9: + version "6.8.0" + resolved "https://registry.npmjs.org/table/-/table-6.8.0.tgz" + integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tape@^4.6.3: + version "4.15.0" + resolved "https://registry.npmjs.org/tape/-/tape-4.15.0.tgz" + integrity sha512-SfRmG2I8QGGgJE/MCiLH8c11L5XxyUXxwK9xLRD0uiK5fehRkkSZGmR6Y1pxOt8vJ19m3sY+POTQpiaVv45/LQ== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.0" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.2.0" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.4" + minimist "~1.2.5" + object-inspect "~1.12.0" + resolve "~1.22.0" + resumer "~0.0.0" + string.prototype.trim "~1.2.5" + through "~2.3.8" + +tar-fs@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +tar@^4.0.2: + version "4.4.19" + resolved "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + +tdigest@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz" + integrity sha1-Ljyyw56kSeVdHmzZEReszKRYgCE= + dependencies: + bintrees "1.0.1" + +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz" + integrity sha1-Edpv9nDzRxpztiXKTz/c97t0gpE= + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +treeify@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz" + integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/ts-generator/-/ts-generator-0.1.1.tgz" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + +ts-mocha@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-9.0.2.tgz#c1ef0248874d04a0f26dd9bd8d88e617a8d82ab1" + integrity sha512-WyQjvnzwrrubl0JT7EC1yWmNpcsU3fOuBFfdps30zbmFBgKniSaSOyZMZx+Wq7kytUs5CY+pEbSYEbGfIKnXTw== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + +ts-node@^10.7.0: + version "10.7.0" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz" + integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" + yn "3.1.1" + +tsconfig-paths@^3.14.1, tsconfig-paths@^3.5.0: + version "3.14.1" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz" + integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@2.3.1, tslib@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + +tslib@^1.8.1, tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl-util@^0.15.0: + version "0.15.1" + resolved "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +tweetnacl@^1.0.0: + version "1.0.3" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.npmjs.org/type/-/type-1.2.0.tgz" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.6.0" + resolved "https://registry.npmjs.org/type/-/type-2.6.0.tgz" + integrity sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ== + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/typechain/-/typechain-3.0.0.tgz" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.1.1" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^4.3.5: + version "4.6.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz" + integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== + +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz" + integrity sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU= + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz" + integrity sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE= + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/typewiselite/-/typewiselite-1.0.0.tgz" + integrity sha1-yIgvobsQksBgBal/NO9chQjjZk4= + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz" + integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= + +u2f-api@0.2.7: + version "0.2.7" + resolved "https://registry.npmjs.org/u2f-api/-/u2f-api-0.2.7.tgz" + integrity sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg== + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +usb@^1.6.3: + version "1.9.2" + resolved "https://registry.npmjs.org/usb/-/usb-1.9.2.tgz" + integrity sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg== + dependencies: + node-addon-api "^4.2.0" + node-gyp-build "^4.3.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf-8-validate@^5.0.2: + version "5.0.9" + resolved "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz" + integrity sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0, utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz" + integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + for-each "^0.3.3" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.1" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@3.3.2: + version "3.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.11.tgz" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.11.tgz" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-utils "1.2.11" + +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-http "1.2.11" + web3-providers-ipc "1.2.11" + web3-providers-ws "1.2.11" + +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-core/-/web3-core-1.2.11.tgz" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-requestmanager "1.2.11" + web3-utils "1.2.11" + +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-utils "1.2.11" + +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-contract "1.2.11" + web3-utils "1.2.11" + +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.11.tgz" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-accounts "1.2.11" + web3-eth-contract "1.2.11" + web3-eth-ens "1.2.11" + web3-eth-iban "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-net/-/web3-net-1.2.11.tgz" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.11.tgz" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.11.tgz" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.11.tgz" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + +web3-utils@^1.0.0-beta.31, web3-utils@^1.3.4: + version "1.7.1" + resolved "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.1.tgz" + integrity sha512-fef0EsqMGJUgiHPdX+KN9okVWshbIumyJPmR+btnD1HgvoXijKEkuKBv0OmUqjbeqmLKP2/N9EiXKJel5+E1Dw== + dependencies: + bn.js "^4.11.9" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3@1.2.11: + version "1.2.11" + resolved "https://registry.npmjs.org/web3/-/web3-1.2.11.tgz" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + dependencies: + web3-bzz "1.2.11" + web3-core "1.2.11" + web3-eth "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-shh "1.2.11" + web3-utils "1.2.11" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.npmjs.org/websocket/-/websocket-1.0.32.tgz" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +websocket@^1.0.31: + version "1.0.34" + resolved "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +whatwg-fetch@2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + +which-pm-runs@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz" + integrity sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA== + +which@2.0.2, which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wide-align@^1.1.0: + version "1.1.5" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz" + integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +workerpool@6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz" + integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + +xhr-request-promise@^0.1.2: + version "0.1.3" + resolved "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz" + integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== + dependencies: + xhr-request "^1.1.0" + +xhr-request@^1.0.1, xhr-request@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: + version "2.6.0" + resolved "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz" + integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== + dependencies: + global "~4.4.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz" + integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz" + integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo= + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000000..f389a4990f71 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2017", + "sourceMap": true, + "esModuleInterop": true, + "composite": true, + "resolveJsonModule": true, + "declaration": true, + "noImplicitAny": false, + "removeComments": true, + "noLib": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "typeRoots": [ + "node_modules/@types" + ] + }, + "exclude": [ + "node_modules", + "dist" + ] +} From d7615e43250f4ab3314e406117b1798768c34e82 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 8 Apr 2022 13:01:14 -0700 Subject: [PATCH 465/585] opnode: Fix possible panic in sequencer batch creation (#342) Previously we assumed that every deposit would be included in the L2 block. However, the L2 execution engine removes depoists that are not valid. As such the number of deposits submitted to the execution engine could be greater than the number of transactions returned causing a panic. This fixes the issue by counting the number of deposits returned and using that to slice the payload transactions for batch submission. (Deposits are not submitted in batches and instead read directly from L1). This also does more sanity checks on the transactions included in the L2 block and rejects blocks with invalid deposit tx configurations. This is done prior to marking the payload canonical with the FCU. --- opnode/rollup/driver/step.go | 85 ++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 13 deletions(-) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 7a4cba672974..8388de90856f 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -26,6 +26,34 @@ type outputImpl struct { Config rollup.Config } +// isDepositTx checks an opaqueTx to determine if it is a Deposit Trransaction +// It has to return an error in the case the transaction is empty +func isDepositTx(opaqueTx l2.Data) (bool, error) { + if len(opaqueTx) == 0 { + return false, errors.New("empty transaction") + } + return opaqueTx[0] == types.DepositTxType, nil +} + +// lastDeposit finds the index of last deposit at the start of the transactions. +// It walks the transactions from the start until it finds a non-deposit tx. +// An error is returned if any looked at transaction cannot be decoded +func lastDeposit(txns []l2.Data) (int, error) { + var lastDeposit int + for i, tx := range txns { + deposit, err := isDepositTx(tx) + if err != nil { + return 0, fmt.Errorf("invalid transaction at idx %d", i) + } + if deposit { + lastDeposit = i + } else { + break + } + } + return lastDeposit, nil +} + func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) { d.log.Info("creating new block", "l2Head", l2Head) @@ -63,8 +91,6 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, } txns = append(txns, deposits...) - depositStart := len(txns) - attrs := &l2.PayloadAttributes{ Timestamp: hexutil.Uint64(l2Head.Time + d.Config.BlockTime), PrevRandao: l2.Bytes32(l1Info.MixDigest()), @@ -78,15 +104,16 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, FinalizedBlockHash: l2Finalized.Hash, } - payload, err := d.insertHeadBlock(ctx, fc, attrs, false) + payload, lastDeposit, err := d.insertHeadBlock(ctx, fc, attrs, false) if err != nil { return l2Head, nil, fmt.Errorf("failed to extend L2 chain: %v", err) } + batch := &derive.BatchData{ BatchV1: derive.BatchV1{ Epoch: rollup.Epoch(l1Info.NumberU64()), Timestamp: uint64(payload.Timestamp), - Transactions: payload.Transactions[depositStart:], + Transactions: payload.Transactions[lastDeposit+1:], }, } ref, err := l2.PayloadToBlockRef(payload, &d.Config.Genesis) @@ -185,7 +212,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S payload, reorg, err = d.verifySafeBlock(ctx, fc, attrs, lastSafeHead.ID()) } else { - payload, err = d.insertHeadBlock(ctx, fc, attrs, true) + payload, _, err = d.insertHeadBlock(ctx, fc, attrs, true) } if err != nil { return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) @@ -247,7 +274,7 @@ func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, d.log.Warn("Detected L2 reorg when verifying L2 safe head", "parent", parent, "prev_block", payload.BlockHash, "mismatch", err) fc.HeadBlockHash = parent.Hash fc.SafeBlockHash = parent.Hash - payload, err := d.insertHeadBlock(ctx, fc, attrs, true) + payload, _, err := d.insertHeadBlock(ctx, fc, attrs, true) return payload, true, err } // If the attributes match, just bump the safe head @@ -264,22 +291,54 @@ func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, // It first uses the given FC to start the block creation process and then after the payload is executed, // sets the FC to the same safe and finalized hashes, but updates the head hash to the new block. // If updateSafe is true, the head block is considered to be the safe head as well as the head. -func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, updateSafe bool) (*l2.ExecutionPayload, error) { +// It returns the payload, the count of deposits, and an error. +func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, updateSafe bool) (*l2.ExecutionPayload, int, error) { fcRes, err := d.l2.ForkchoiceUpdate(ctx, &fc, attrs) if err != nil { - return nil, fmt.Errorf("failed to create new block via forkchoice: %w", err) + return nil, 0, fmt.Errorf("failed to create new block via forkchoice: %w", err) } id := fcRes.PayloadID if id == nil { - return nil, errors.New("nil id in forkchoice result when expecting a valid ID") + return nil, 0, errors.New("nil id in forkchoice result when expecting a valid ID") } payload, err := d.l2.GetPayload(ctx, *id) if err != nil { - return nil, fmt.Errorf("failed to get execution payload: %w", err) + return nil, 0, fmt.Errorf("failed to get execution payload: %w", err) + } + // Sanity check payload before inserting it + if len(payload.Transactions) == 0 { + return nil, 0, errors.New("no transactions in returned payload") + } + if payload.Transactions[0][0] != types.DepositTxType { + return nil, 0, fmt.Errorf("first transaction was not deposit tx. Got %v", payload.Transactions[0][0]) + } + // Ensure that the deposits are first + lastDeposit, err := lastDeposit(payload.Transactions) + if err != nil { + return nil, 0, fmt.Errorf("failed to find last deposit: %w", err) } + // Ensure no deposits after last deposit + for i := lastDeposit + 1; i < len(payload.Transactions); i++ { + tx := payload.Transactions[i] + deposit, err := isDepositTx(tx) + if err != nil { + return nil, 0, fmt.Errorf("failed to decode transaction idx %d: %w", i, err) + } + if deposit { + d.log.Error("Produced an invalid block where the deposit txns are not all at the start of the block", "tx_idx", i, "lastDeposit", lastDeposit) + return nil, 0, fmt.Errorf("deposit tx (%d) after other tx in l2 block with prev deposit at idx %d", i, lastDeposit) + } + } + // If this is an unsafe block, it has deposits & transactions included from L2. + // Record if the execution engine dropped deposits. The verification process would see a mismatch + // between attributes and the block, but then execute the correct block. + if !updateSafe && lastDeposit+1 != len(attrs.Transactions) { + d.log.Error("Dropped deposits when executing L2 block") + } + err = d.l2.NewPayload(ctx, payload) if err != nil { - return nil, fmt.Errorf("failed to insert execution payload: %w", err) + return nil, 0, fmt.Errorf("failed to insert execution payload: %w", err) } fc.HeadBlockHash = payload.BlockHash if updateSafe { @@ -288,7 +347,7 @@ func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, d.log.Debug("Inserted L2 head block", "number", uint64(payload.BlockNumber), "hash", payload.BlockHash, "update_safe", updateSafe) _, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { - return nil, fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", err) + return nil, 0, fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", err) } - return payload, nil + return payload, lastDeposit, nil } From 72d67358486456894a00028bfe71d93df439900d Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 8 Apr 2022 14:31:59 -0700 Subject: [PATCH 466/585] opnode: Test Utilities (#319) * opnode: Deduplicate fake chain source The fake chain source is an easy way to create and L1 and L2 chains from a simple string defition. There were previously two implementations and now they are in a shared testutils package. * opnode: Dedicated wait functions This deduplicates wait for transactions on L1 and L2. * opnode: New e2e test system This splits out the initialization from the actual tests to eanble multiple e2e tests. Some of the config is still not as dedpulicated as I would like, but it is more centralized than it previously was. Aims to move the setup from the tests and enable easier e2e tests. * opnode: Silence FindSyncStartTest * opnode: Add test for missing batches This ensures the the sequencer follows the chain that is derived from L1 rather than what it sequenced in the case that it misses batch submission. * opnode: Pull out system config to default cfg This reduces duplication and makes tests easier to understand. * opnode: Address PR comments * opnode: Reduce flakiness in missing batch test The proper way to do this is to wait for a safe block, but the API is not yet ready for that. --- .../testutils}/fake_chain.go | 47 +- opnode/rollup/driver/state_test.go | 52 +- opnode/rollup/sync/start_test.go | 117 +--- opnode/test/geth.go | 87 ++- opnode/test/setup.go | 217 ++++++- opnode/test/system_test.go | 563 ++++++++---------- 6 files changed, 580 insertions(+), 503 deletions(-) rename opnode/{rollup/driver => internal/testutils}/fake_chain.go (80%) diff --git a/opnode/rollup/driver/fake_chain.go b/opnode/internal/testutils/fake_chain.go similarity index 80% rename from opnode/rollup/driver/fake_chain.go rename to opnode/internal/testutils/fake_chain.go index 374a56fea358..abbb17cfd341 100644 --- a/opnode/rollup/driver/fake_chain.go +++ b/opnode/internal/testutils/fake_chain.go @@ -1,4 +1,4 @@ -package driver +package testutils import ( "context" @@ -14,10 +14,10 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" ) -func fakeGenesis(l1 rune, l2 rune, l2offset int) rollup.Genesis { +func FakeGenesis(l1 rune, l2 rune, l1GenesisNumber int) rollup.Genesis { return rollup.Genesis{ - L1: fakeID(l1, 0), - L2: fakeID(l2, uint64(l2offset)), + L1: fakeID(l1, uint64(l1GenesisNumber)), + L2: fakeID(l2, 0), } } @@ -55,35 +55,35 @@ func chainL1(offset uint64, ids string) (out []eth.L1BlockRef) { return } -func chainL2(l1 []eth.L1BlockRef, ids string) (out []eth.L2BlockRef) { +func chainL2(offset int, l1 []eth.L1BlockRef, ids string) (out []eth.L2BlockRef) { var prevID rune for i, id := range ids { - out = append(out, fakeL2Block(id, prevID, l1[i].ID(), uint64(i))) + out = append(out, fakeL2Block(id, prevID, l1[i+int(offset)].ID(), uint64(i))) prevID = id } return } -func NewFakeChainSource(l1 []string, l2 []string, log log.Logger) *fakeChainSource { +func NewFakeChainSource(l1 []string, l2 []string, l1GenesisNumber int, log log.Logger) *FakeChainSource { var l1s [][]eth.L1BlockRef for _, l1string := range l1 { l1s = append(l1s, chainL1(0, l1string)) } var l2s [][]eth.L2BlockRef for i, l2string := range l2 { - l2s = append(l2s, chainL2(l1s[i], l2string)) + l2s = append(l2s, chainL2(l1GenesisNumber, l1s[i], l2string)) } - return &fakeChainSource{ + return &FakeChainSource{ l1s: l1s, l2s: l2s, log: log, } } -// fakeChainSource implements the ChainSource interface with the ability to control +// FakeChainSource implements the ChainSource interface with the ability to control // what the head block is of the L1 and L2 chains. In addition, it enables re-orgs // to easily be implemented -type fakeChainSource struct { +type FakeChainSource struct { l1reorg int // Index of the L1 chain to be operating on l2reorg int // Index of the L2 chain to be operating on l1head int // Head block of the L1 chain @@ -93,7 +93,7 @@ type fakeChainSource struct { log log.Logger } -func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID, max uint64) ([]eth.BlockID, error) { +func (m *FakeChainSource) L1Range(ctx context.Context, base eth.BlockID, max uint64) ([]eth.BlockID, error) { var out []eth.BlockID found := false for i, b := range m.l1s[m.l1reorg] { @@ -114,7 +114,7 @@ func (m *fakeChainSource) L1Range(ctx context.Context, base eth.BlockID, max uin return nil, ethereum.NotFound } -func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { +func (m *FakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { m.log.Trace("L1BlockRefByNumber", "l1Num", l1Num, "l1Head", m.l1head, "reorg", m.l1reorg) if l1Num > uint64(m.l1head) { return eth.L1BlockRef{}, ethereum.NotFound @@ -122,7 +122,7 @@ func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, l1Num uint64) return m.l1s[m.l1reorg][l1Num], nil } -func (m *fakeChainSource) L1BlockRefByHash(ctx context.Context, l1Hash common.Hash) (eth.L1BlockRef, error) { +func (m *FakeChainSource) L1BlockRefByHash(ctx context.Context, l1Hash common.Hash) (eth.L1BlockRef, error) { m.log.Trace("L1BlockRefByHash", "l1Hash", l1Hash, "l1Head", m.l1head, "reorg", m.l1reorg) for i, bl := range m.l1s[m.l1reorg] { if bl.Hash == l1Hash { @@ -132,7 +132,7 @@ func (m *fakeChainSource) L1BlockRefByHash(ctx context.Context, l1Hash common.Ha return eth.L1BlockRef{}, ethereum.NotFound } -func (m *fakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { +func (m *FakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { m.log.Trace("L1HeadBlockRef", "l1Head", m.l1head, "reorg", m.l1reorg) l := len(m.l1s[m.l1reorg]) if l == 0 { @@ -141,7 +141,7 @@ func (m *fakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, e return m.l1s[m.l1reorg][m.l1head], nil } -func (m *fakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { +func (m *FakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { m.log.Trace("L2BlockRefByNumber", "l2Num", l2Num, "l2Head", m.l2head, "reorg", m.l2reorg) if len(m.l2s[m.l2reorg]) == 0 { panic("bad test, no l2 chain") @@ -156,7 +156,7 @@ func (m *fakeChainSource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int return m.l2s[m.l2reorg][i], nil } -func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { +func (m *FakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { m.log.Trace("L2BlockRefByHash", "l2Hash", l2Hash, "l2Head", m.l2head, "reorg", m.l2reorg) for i, bl := range m.l2s[m.l2reorg] { if bl.Hash == l2Hash { @@ -166,7 +166,7 @@ func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Ha return eth.L2BlockRef{}, ethereum.NotFound } -func (m *fakeChainSource) ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) { +func (m *FakeChainSource) ForkchoiceUpdate(ctx context.Context, state *l2.ForkchoiceState, attr *l2.PayloadAttributes) (*l2.ForkchoiceUpdatedResult, error) { m.log.Trace("ForkchoiceUpdate", "newHead", state.HeadBlockHash, "l2Head", m.l2head, "reorg", m.l2reorg) m.l2reorg++ if m.l2reorg >= len(m.l2s) { @@ -181,10 +181,7 @@ func (m *fakeChainSource) ForkchoiceUpdate(ctx context.Context, state *l2.Forkch return nil, errors.New("unable to set new head") } -var _ L1Chain = (*fakeChainSource)(nil) -var _ L2Chain = (*fakeChainSource)(nil) - -func (m *fakeChainSource) reorgL1() { +func (m *FakeChainSource) ReorgL1() { m.log.Trace("Reorg L1", "new_reorg", m.l1reorg+1, "old_reorg", m.l1reorg) m.l1reorg++ if m.l1reorg >= len(m.l1s) { @@ -192,7 +189,7 @@ func (m *fakeChainSource) reorgL1() { } } -func (m *fakeChainSource) setL2Head(head int) eth.L2BlockRef { +func (m *FakeChainSource) SetL2Head(head int) eth.L2BlockRef { m.log.Trace("Set L2 head", "new_head", head, "old_head", m.l2head) m.l2head = head if m.l2head >= len(m.l2s[m.l2reorg]) { @@ -201,7 +198,7 @@ func (m *fakeChainSource) setL2Head(head int) eth.L2BlockRef { return m.l2s[m.l2reorg][m.l2head] } -func (m *fakeChainSource) advanceL1() eth.L1BlockRef { +func (m *FakeChainSource) AdvanceL1() eth.L1BlockRef { m.log.Trace("Advance L1", "new_head", m.l1head+1, "old_head", m.l1head) m.l1head++ if m.l1head >= len(m.l1s[m.l1reorg]) { @@ -210,7 +207,7 @@ func (m *fakeChainSource) advanceL1() eth.L1BlockRef { return m.l1s[m.l1reorg][m.l1head] } -func (m *fakeChainSource) l1Head() eth.L1BlockRef { +func (m *FakeChainSource) L1Head() eth.L1BlockRef { m.log.Trace("L1 Head", "head", m.l1head) return m.l1s[m.l1reorg][m.l1head] } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 118ac796be09..85179d4fee8a 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testutils" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" @@ -16,6 +17,9 @@ import ( "github.com/stretchr/testify/assert" ) +var _ L1Chain = (*testutils.FakeChainSource)(nil) +var _ L2Chain = (*testutils.FakeChainSource)(nil) + type testID string func (id testID) ID() eth.BlockID { @@ -66,30 +70,30 @@ type stateTestCaseStep struct { window []testID // l1act and l2act are ran at each step - l1act func(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) - l2act func(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) + l1act func(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) + l2act func(t *testing.T, expectedWindow []testID, s *state, src *testutils.FakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) reorg bool } -func advanceL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) { - l1Heads <- src.advanceL1() +func advanceL1(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) { + l1Heads <- src.AdvanceL1() } -func stutterL1(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) { - l1Heads <- src.l1Head() +func stutterL1(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) { + l1Heads <- src.L1Head() } -func stutterAdvance(t *testing.T, s *state, src *fakeChainSource, l1Heads chan eth.L1BlockRef) { - l1Heads <- src.l1Head() - l1Heads <- src.l1Head() - l1Heads <- src.l1Head() - l1Heads <- src.advanceL1() - l1Heads <- src.l1Head() - l1Heads <- src.l1Head() - l1Heads <- src.l1Head() +func stutterAdvance(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) { + l1Heads <- src.L1Head() + l1Heads <- src.L1Head() + l1Heads <- src.L1Head() + l1Heads <- src.AdvanceL1() + l1Heads <- src.L1Head() + l1Heads <- src.L1Head() + l1Heads <- src.L1Head() } -func stutterL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { +func stutterL2(t *testing.T, expectedWindow []testID, s *state, src *testutils.FakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { select { case <-outputIn: t.Error("Got a step when no step should have occurred (l1 only advance)") @@ -97,17 +101,17 @@ func stutterL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo } } -func advanceL2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { +func advanceL2(t *testing.T, expectedWindow []testID, s *state, src *testutils.FakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { args := <-outputIn assert.Equal(t, int(s.Config.SeqWindowSize), len(args.l1Window), "Invalid L1 window size") assert.Equal(t, len(expectedWindow), len(args.l1Window), "L1 Window size does not match expectedWindow") for i := range expectedWindow { assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match in advancing L2 in window element %d", i) } - outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} + outputReturn <- outputReturnArgs{l2Head: src.SetL2Head(int(args.l2Head.Number) + 1), err: nil} } -func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { +func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *testutils.FakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { args := <-outputIn assert.Equal(t, int(s.Config.SeqWindowSize), len(args.l1Window), "Invalid L1 window size") assert.Equal(t, len(expectedWindow), len(args.l1Window), "L1 Window size does not match expectedWindow") @@ -115,7 +119,7 @@ func reorg__L2(t *testing.T, expectedWindow []testID, s *state, src *fakeChainSo assert.Equal(t, expectedWindow[i].ID(), args.l1Window[i], "Window elements must match on reorg in window element %d", i) } - outputReturn <- outputReturnArgs{l2Head: src.setL2Head(int(args.l2Head.Number) + 1), err: nil} + outputReturn <- outputReturnArgs{l2Head: src.SetL2Head(int(args.l2Head.Number) + 1), err: nil} } type stateTestCase struct { @@ -129,7 +133,7 @@ type stateTestCase struct { func (tc *stateTestCase) Run(t *testing.T) { log := testlog.Logger(t, log.LvlError) - chainSource := NewFakeChainSource(tc.l1Chains, tc.l2Chains, log) + chainSource := testutils.NewFakeChainSource(tc.l1Chains, tc.l2Chains, 0, log) l1headsCh := make(chan eth.L1BlockRef, 10) // Unbuffered channels to force a sync point between the test and the state loop. outputIn := make(chan outputArgs) @@ -151,7 +155,7 @@ func (tc *stateTestCase) Run(t *testing.T) { for _, step := range tc.steps { if step.reorg { - chainSource.reorgL1() + chainSource.ReorgL1() } step.l1act(t, state, chainSource, l1headsCh) <-time.After(5 * time.Millisecond) @@ -170,7 +174,7 @@ func TestDriver(t *testing.T) { l1Chains: []string{"abcdefgh"}, l2Chains: []string{"ABCDEF"}, seqWindow: 2, - genesis: fakeGenesis('a', 'A', 0), + genesis: testutils.FakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ {l1act: stutterL1, l2act: stutterL2, l1head: "a:0", l2head: "A:0"}, {l1act: advanceL1, l2act: stutterL2, l1head: "b:1", l2head: "A:0", window: []testID{"a:0", "b:1"}}, @@ -186,7 +190,7 @@ func TestDriver(t *testing.T) { l1Chains: []string{"abcdefg", "abcwxyz"}, l2Chains: []string{"ABCDEF", "ABCWXY"}, seqWindow: 2, - genesis: fakeGenesis('a', 'A', 0), + genesis: testutils.FakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ {l1act: stutterL1, l2act: stutterL2, l1head: "a:0", l2head: "A:0"}, {l1act: advanceL1, l2act: stutterL2, l1head: "b:1", l2head: "A:0", window: []testID{"a:0", "b:1"}}, @@ -207,7 +211,7 @@ func TestDriver(t *testing.T) { l1Chains: []string{"abcdefgh"}, l2Chains: []string{"ABCDEF"}, seqWindow: 2, - genesis: fakeGenesis('a', 'A', 0), + genesis: testutils.FakeGenesis('a', 'A', 0), steps: []stateTestCaseStep{ {l1act: stutterL1, l2act: stutterL2, l1head: "a:0", l2head: "A:0"}, {l1act: advanceL1, l2act: stutterL2, l1head: "b:1", l2head: "A:0", window: []testID{"a:0", "b:1"}}, diff --git a/opnode/rollup/sync/start_test.go b/opnode/rollup/sync/start_test.go index 451e92e19228..946aca8467c7 100644 --- a/opnode/rollup/sync/start_test.go +++ b/opnode/rollup/sync/start_test.go @@ -5,110 +5,45 @@ import ( "testing" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testutils" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" ) -type fakeChainSource struct { - L1 []eth.L1BlockRef - L2 map[common.Hash]eth.L2BlockRef -} - -func (m *fakeChainSource) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { - return m.L1[len(m.L1)-1], nil -} - -func (m *fakeChainSource) L1BlockRefByNumber(ctx context.Context, number uint64) (eth.L1BlockRef, error) { - n := int(number) - if n >= len(m.L1) { - return eth.L1BlockRef{}, ethereum.NotFound - } - return m.L1[n], nil -} - -func (m *fakeChainSource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { - ref, ok := m.L2[l2Hash] - if !ok { - return eth.L2BlockRef{}, ethereum.NotFound - } - return ref, nil -} - -var _ L1Chain = (*fakeChainSource)(nil) -var _ L2Chain = (*fakeChainSource)(nil) - -func fakeID(id rune, num uint64) eth.BlockID { - var h common.Hash - copy(h[:], string(id)) - return eth.BlockID{Hash: h, Number: uint64(num)} -} - -func fakeL1Block(self rune, parent rune, num uint64) eth.L1BlockRef { - var parentID eth.BlockID - if num != 0 { - parentID = fakeID(parent, num-1) - } - id := fakeID(self, num) - return eth.L1BlockRef{Hash: id.Hash, Number: id.Number, ParentHash: parentID.Hash} -} - -func fakeL2Block(self rune, parent rune, l1parent eth.BlockID, num uint64) eth.L2BlockRef { - var parentID eth.BlockID - if num != 0 { - parentID = fakeID(parent, num-1) - } - id := fakeID(self, num) - return eth.L2BlockRef{Hash: id.Hash, Number: id.Number, ParentHash: parentID.Hash, L1Origin: l1parent} -} - -func (c *syncStartTestCase) generateFakeL2() (*fakeChainSource, eth.L2BlockRef, rollup.Genesis) { - var l1 []eth.L1BlockRef - var newl1 []eth.L1BlockRef - var prevID rune - for i, id := range c.L1 { - l1 = append(l1, fakeL1Block(id, prevID, uint64(i))) - // fmt.Printf("%v\t%v\n", l1[i].Self, l1[i].Parent) - prevID = id - } - prevID = rune(0) - for i, id := range c.NewL1 { - newl1 = append(newl1, fakeL1Block(id, prevID, uint64(i))) - // fmt.Printf("%v\t%v\n", newl1[i].Self, newl1[i].Parent) - prevID = id - } - - prevID = rune(0) - var head eth.L2BlockRef - m := make(map[common.Hash]eth.L2BlockRef) - for i, id := range c.L2 { - b := fakeL2Block(id, prevID, l1[i+int(c.GenesisL1Num)].ID(), uint64(i)+c.GenesisL2Num) - m[b.Hash] = b - // fmt.Printf("%v\t%v\t%v\n", b.Self, b.Parent, b.L1Origin) - prevID = id - head = b - } - genesis := rollup.Genesis{ - L1: fakeID(c.GenesisL1, c.GenesisL1Num), - L2: fakeID(c.GenesisL2, c.GenesisL2Num), +var _ L1Chain = (*testutils.FakeChainSource)(nil) +var _ L2Chain = (*testutils.FakeChainSource)(nil) + +// generateFakeL2 creates a fake L2 chain with the following conditions: +// - The L2 chain is based off of the L1 chain +// - The actual L1 chain is the New L1 chain +// - Both heads are at the tip of their respective chains +func (c *syncStartTestCase) generateFakeL2(t *testing.T) (*testutils.FakeChainSource, eth.L2BlockRef, rollup.Genesis) { + log := testlog.Logger(t, log.LvlError) + chain := testutils.NewFakeChainSource([]string{c.L1, c.NewL1}, []string{c.L2}, int(c.GenesisL1Num), log) + chain.SetL2Head(len(c.L2) - 1) + genesis := testutils.FakeGenesis(c.GenesisL1, c.GenesisL2, int(c.GenesisL1Num)) + head, err := chain.L2BlockRefByNumber(context.Background(), nil) + require.Nil(t, err) + chain.ReorgL1() + for i := 0; i < len(c.NewL1)-1; i++ { + chain.AdvanceL1() } - return &fakeChainSource{L1: newl1, L2: m}, head, genesis + return chain, head, genesis } type syncStartTestCase struct { Name string - L1 string // L1 Chain prior to a re-org or other change - L2 string // L2 Chain that follows from L1Chain - NewL1 string // New L1 chain - ReorgBase rune // Highest L1 block in the pre and post re-org L1 chian + L1 string // L1 Chain prior to a re-org or other change + L2 string // L2 Chain that follows from L1Chain + NewL1 string // New L1 chain GenesisL1 rune GenesisL1Num uint64 GenesisL2 rune - GenesisL2Num uint64 SeqWindowSize uint64 SafeL2Head rune @@ -121,9 +56,9 @@ func refToRune(r eth.BlockID) rune { } func (c *syncStartTestCase) Run(t *testing.T) { - msr, l2Head, genesis := c.generateFakeL2() + chain, l2Head, genesis := c.generateFakeL2(t) - unsafeL2Head, safeHead, err := FindL2Heads(context.TODO(), l2Head, c.SeqWindowSize, msr, msr, &genesis) + unsafeL2Head, safeHead, err := FindL2Heads(context.Background(), l2Head, c.SeqWindowSize, chain, chain, &genesis) if c.ExpectedErr != nil { require.Error(t, err, "Expecting an error in this test case") diff --git a/opnode/test/geth.go b/opnode/test/geth.go index c21318d3b5e8..30f069e354c7 100644 --- a/opnode/test/geth.go +++ b/opnode/test/geth.go @@ -1,17 +1,80 @@ package test import ( + "context" "crypto/ecdsa" + "fmt" + "math/big" + "strconv" + "strings" + "time" + rollupEth "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "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/ethclient" "github.com/ethereum/go-ethereum/node" hdwallet "github.com/miguelmota/go-ethereum-hdwallet" ) +func getGenesisInfo(client *ethclient.Client) (id rollupEth.BlockID, timestamp uint64) { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + block, err := client.BlockByNumber(ctx, common.Big0) + if err != nil { + panic(err) + } + return rollupEth.BlockID{Hash: block.Hash(), Number: block.NumberU64()}, block.Time() +} + +func initL1Geth(cfg *SystemConfig, wallet *hdwallet.Wallet, genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) { + signer := deriveAccount(wallet, cfg.CliqueSignerDerivationPath) + pk, err := wallet.PrivateKey(signer) + if err != nil { + return nil, nil, fmt.Errorf("failed to locate private key in wallet: %w", err) + } + + ethConfig := ðconfig.Config{ + NetworkId: cfg.L1ChainID.Uint64(), + Genesis: genesis, + } + nodeConfig := &node.Config{ + Name: "l1-geth", + WSHost: cfg.L1WsAddr, + WSPort: cfg.L1WsPort, + } + + return createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{pk}) +} + +func initL2Geth(name, addr string, l2ChainID *big.Int, genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) { + ethConfig := ðconfig.Config{ + NetworkId: l2ChainID.Uint64(), + Genesis: genesis, + } + // Parsing ws://127.0.0.1:9091 for "127.0.0.1" and "9091" + s := strings.Split(addr, ":") + _, host, ok := strings.Cut(s[1], "//") + if !ok { + return nil, nil, fmt.Errorf("could not find ws host in %s", addr) + } + port, err := strconv.ParseInt(s[2], 10, 32) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse port from address: %w", err) + } + nodeConfig := &node.Config{ + Name: fmt.Sprintf("l2-geth-%v", name), + WSHost: host, + WSPort: int(port), + } + return createGethNode(true, nodeConfig, ethConfig, nil) +} + // 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. @@ -24,8 +87,8 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri } keydir := n.KeyStoreDir() - scryptN := keystore.LightScryptN - scryptP := keystore.LightScryptP + scryptN := 2 + scryptP := 1 n.AccountManager().AddBackend(keystore.NewKeyStore(keydir, scryptN, scryptP)) ks := n.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) @@ -59,23 +122,3 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri return n, backend, nil } - -func l1Geth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { - wallet, err := hdwallet.NewFromMnemonic(cfg.mnemonic) - if err != nil { - return nil, nil, err - } - - signer := deriveAccount(wallet, cfg.cliqueSigners[0]) - pk, _ := wallet.PrivateKey(signer) - - return createGethNode(false, cfg.l1.nodeConfig, cfg.l1.ethConfig, []*ecdsa.PrivateKey{pk}) -} - -func l2Geth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { - return createGethNode(true, cfg.l2Verifier.nodeConfig, cfg.l2Verifier.ethConfig, nil) -} - -func l2SequencerGeth(cfg *systemConfig) (*node.Node, *eth.Ethereum, error) { - return createGethNode(true, cfg.l2Sequencer.nodeConfig, cfg.l2Sequencer.ethConfig, nil) -} diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 3d370f267f6b..42a94d8d5f2d 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -1,16 +1,22 @@ package test import ( + "context" "fmt" "math/big" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" + rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" @@ -34,23 +40,35 @@ func deriveAccount(w accounts.Wallet, path string) accounts.Account { return account } -// gethConfig is configuration for either and L1 or L2 geth node -type gethConfig struct { - nodeConfig *node.Config - ethConfig *ethconfig.Config +type SystemConfig struct { + Mnemonic string + Premine map[string]int // Derivation path -> amount in ETH (not wei) + CliqueSignerDerivationPath string + BatchSubmitterHDPath string + DepositContractAddress common.Address + L1InfoPredeployAddress common.Address + + L1WsAddr string + L1WsPort int + L1ChainID *big.Int + L2ChainID *big.Int + Nodes map[string]rollupNode.Config // Per node config. Don't use populate rollup.Config + Loggers map[string]log.Logger + RollupConfig rollup.Config // Shared rollup configs } -// systemConfig holds the information necessary to create a L1 <-> Rollup <-> L2 system -type systemConfig struct { - mnemonic string - l1 gethConfig - l2Verifier gethConfig - l2Sequencer gethConfig - premine map[string]int // Derivation path -> amount in ETH (not wei) - cliqueSigners []string // derivation path - depositContractAddress string - l1InfoPredeployAddress string - wallet *hdwallet.Wallet +type System struct { + cfg SystemConfig + + // Retain wallet + wallet *hdwallet.Wallet + + // Connections to running nodes + nodes map[string]*node.Node + backends map[string]*eth.Ethereum + Clients map[string]*ethclient.Client + RolupGenesis rollup.Genesis + rollupNodes map[string]*rollupNode.OpNode } func precompileAlloc() core.GenesisAlloc { @@ -79,20 +97,60 @@ func cliqueExtraData(w accounts.Wallet, signers []string) []byte { return append(ret, t...) } -// initializeGenesis creates a L1 and L2 genesis from the config and places them in l1 and l2 configurations -func initializeGenesis(cfg *systemConfig) { - wallet, err := hdwallet.NewFromMnemonic(cfg.mnemonic) +func (sys *System) Close() { + for _, node := range sys.rollupNodes { + node.Stop() + } + for _, node := range sys.nodes { + node.Close() + } +} + +func (cfg SystemConfig) start() (*System, error) { + sys := &System{ + cfg: cfg, + nodes: make(map[string]*node.Node), + backends: make(map[string]*eth.Ethereum), + Clients: make(map[string]*ethclient.Client), + rollupNodes: make(map[string]*rollupNode.OpNode), + } + didErrAfterStart := false + defer func() { + if didErrAfterStart { + for _, node := range sys.nodes { + node.Close() + } + for _, node := range sys.rollupNodes { + node.Stop() + } + } + }() + + // Wallet + wallet, err := hdwallet.NewFromMnemonic(cfg.Mnemonic) if err != nil { - panic(fmt.Errorf("Failed to create wallet: %w", err)) + return nil, fmt.Errorf("Failed to create wallet: %w", err) } + sys.wallet = wallet - eth := new(big.Int) - eth = eth.Exp(big.NewInt(10), big.NewInt(10), nil) + // Create the BSS and set it's config here because it needs to be derived from the accounts + bssPrivKey, err := wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: cfg.BatchSubmitterHDPath, + }, + }) + if err != nil { + return nil, err + } + submitterAddress := crypto.PubkeyToAddress(bssPrivKey.PublicKey) + + // Genesis + eth := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) l1Alloc := precompileAlloc() l2Alloc := precompileAlloc() - for path, amt := range cfg.premine { + for path, amt := range cfg.Premine { balance := big.NewInt(int64(amt)) balance.Mul(balance, eth) addr := deriveAddress(wallet, path) @@ -100,14 +158,14 @@ func initializeGenesis(cfg *systemConfig) { l2Alloc[addr] = core.GenesisAccount{Balance: balance} } - l1Alloc[common.HexToAddress(cfg.depositContractAddress)] = core.GenesisAccount{Code: common.FromHex(deposit.DepositDeployedBin), Balance: common.Big0} - l2Alloc[common.HexToAddress(cfg.l1InfoPredeployAddress)] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} + l1Alloc[cfg.DepositContractAddress] = core.GenesisAccount{Code: common.FromHex(deposit.DepositDeployedBin), Balance: common.Big0} + l2Alloc[cfg.L1InfoPredeployAddress] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} genesisTimestamp := uint64(time.Now().Unix()) l1Genesis := &core.Genesis{ Config: ¶ms.ChainConfig{ - ChainID: new(big.Int).SetUint64((cfg.l1.ethConfig.NetworkId)), + ChainID: cfg.L1ChainID, HomesteadBlock: common.Big0, EIP150Block: common.Big0, EIP155Block: common.Big0, @@ -125,7 +183,7 @@ func initializeGenesis(cfg *systemConfig) { }, Alloc: l1Alloc, Difficulty: common.Big1, - ExtraData: cliqueExtraData(wallet, cfg.cliqueSigners), + ExtraData: cliqueExtraData(wallet, []string{cfg.CliqueSignerDerivationPath}), GasLimit: 5000000, Nonce: 4660, Timestamp: genesisTimestamp, @@ -133,7 +191,7 @@ func initializeGenesis(cfg *systemConfig) { } l2Genesis := &core.Genesis{ Config: ¶ms.ChainConfig{ - ChainID: new(big.Int).SetUint64((cfg.l2Verifier.ethConfig.NetworkId)), + ChainID: cfg.L2ChainID, HomesteadBlock: common.Big0, EIP150Block: common.Big0, EIP155Block: common.Big0, @@ -156,8 +214,103 @@ func initializeGenesis(cfg *systemConfig) { BaseFee: big.NewInt(7), } - cfg.l1.ethConfig.Genesis = l1Genesis - cfg.l2Verifier.ethConfig.Genesis = l2Genesis - cfg.l2Sequencer.ethConfig.Genesis = l2Genesis - cfg.wallet = wallet + // Initialize nodes + l1Node, l1Backend, err := initL1Geth(&cfg, wallet, l1Genesis) + if err != nil { + return nil, err + } + sys.nodes["l1"] = l1Node + sys.backends["l1"] = l1Backend + for name, l2Cfg := range cfg.Nodes { + node, backend, err := initL2Geth(name, l2Cfg.L2EngineAddrs[0], cfg.L2ChainID, l2Genesis) + if err != nil { + return nil, err + } + sys.nodes[name] = node + sys.backends[name] = backend + } + + // Start + err = l1Node.Start() + if err != nil { + didErrAfterStart = true + return nil, err + } + err = l1Backend.StartMining(1) + if err != nil { + didErrAfterStart = true + return nil, err + } + for name, node := range sys.nodes { + if name == "l1" { + continue + } + err = node.Start() + if err != nil { + didErrAfterStart = true + return nil, err + } + } + + // Geth Clients + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + l1Client, err := ethclient.DialContext(ctx, fmt.Sprintf("ws://%s:%d", cfg.L1WsAddr, cfg.L1WsPort)) + if err != nil { + didErrAfterStart = true + return nil, err + } + sys.Clients["l1"] = l1Client + for name, node := range sys.nodes { + client, err := ethclient.DialContext(ctx, node.WSEndpoint()) + if err != nil { + didErrAfterStart = true + return nil, err + } + sys.Clients[name] = client + } + + // Rollup Genesis + l1GenesisID, _ := getGenesisInfo(l1Client) + var l2Client *ethclient.Client + for name, client := range sys.Clients { + if name != "l1" { + l2Client = client + break + } + } + l2GenesisID, l2GenesisTime := getGenesisInfo(l2Client) + + sys.RolupGenesis = rollup.Genesis{ + L1: l1GenesisID, + L2: l2GenesisID, + L2Time: l2GenesisTime, + } + + sys.cfg.RollupConfig.Genesis = sys.RolupGenesis + sys.cfg.RollupConfig.BatchSenderAddress = submitterAddress + + // Rollup nodes + for name, nodeConfig := range cfg.Nodes { + c := nodeConfig + c.Rollup = sys.cfg.RollupConfig + if c.Sequencer { + c.SubmitterPrivKey = bssPrivKey + } + + node, err := rollupNode.New(context.Background(), &c, cfg.Loggers[name], "") + if err != nil { + didErrAfterStart = true + return nil, err + } + err = node.Start(context.Background()) + if err != nil { + didErrAfterStart = true + return nil, err + } + sys.rollupNodes[name] = node + + } + + return sys, nil } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 7af570818ecc..791df57f7b9a 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -13,7 +13,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" @@ -26,150 +25,59 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" ) -func getGenesisInfo(client *ethclient.Client) (id eth.BlockID, timestamp uint64) { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - block, err := client.BlockByNumber(ctx, common.Big0) - if err != nil { - panic(err) - } - return eth.BlockID{Hash: block.Hash(), Number: block.NumberU64()}, block.Time() -} - -func endpoint(cfg *node.Config) string { - return fmt.Sprintf("ws://%v", cfg.WSEndpoint()) -} - -// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. -// All nodes are run in process (but are the full nodes, not mocked or stubbed). -func TestSystemE2E(t *testing.T) { - log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs +const ( + cliqueSignerHDPath = "m/44'/60'/0'/0/0" + transactorHDPath = "m/44'/60'/0'/0/1" + l2OutputHDPath = "m/44'/60'/0'/0/3" + bssHDPath = "m/44'/60'/0'/0/4" +) - const l2OutputHDPath = "m/44'/60'/0'/0/3" - const bssHDPath = "m/44'/60'/0'/0/4" - - // System Config - cfg := &systemConfig{ - mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness", - l1: gethConfig{ - nodeConfig: &node.Config{ - Name: "l1geth", - WSHost: "127.0.0.1", - WSPort: 9090, - }, - ethConfig: ðconfig.Config{ - NetworkId: 900, - }, - }, - l2Verifier: gethConfig{ - nodeConfig: &node.Config{ - Name: "l2gethVerify", - WSHost: "127.0.0.1", - WSPort: 9091, - }, - ethConfig: ðconfig.Config{ - NetworkId: 901, - }, - }, - l2Sequencer: gethConfig{ - nodeConfig: &node.Config{ - Name: "l2gethSeq", - WSHost: "127.0.0.1", - WSPort: 9092, - }, - ethConfig: ðconfig.Config{ - NetworkId: 901, - }, - }, - premine: map[string]int{ - "m/44'/60'/0'/0/0": 10000000, - "m/44'/60'/0'/0/1": 10000000, - "m/44'/60'/0'/0/2": 10000000, +func defaultSystemConfig(t *testing.T) SystemConfig { + return SystemConfig{ + Mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness", + Premine: map[string]int{ + cliqueSignerHDPath: 10000000, + transactorHDPath: 10000000, l2OutputHDPath: 10000000, bssHDPath: 10000000, }, - cliqueSigners: []string{"m/44'/60'/0'/0/0"}, - depositContractAddress: derive.DepositContractAddr.Hex(), - l1InfoPredeployAddress: derive.L1InfoPredeployAddr.Hex(), - } - // Create genesis & assign it to ethconfigs - initializeGenesis(cfg) - - // Start L1 - l1Node, l1Backend, err := l1Geth(cfg) - require.Nil(t, err) - defer l1Node.Close() - - err = l1Node.Start() - require.Nil(t, err) - - err = l1Backend.StartMining(1) - require.Nil(t, err) - - l1Client, err := ethclient.Dial(endpoint(cfg.l1.nodeConfig)) - require.Nil(t, err) - l1GenesisID, _ := getGenesisInfo(l1Client) - - // Start L2 - l2Node, _, err := l2Geth(cfg) - require.Nil(t, err) - defer l2Node.Close() - - err = l2Node.Start() - require.Nil(t, err) - - l2Client, err := ethclient.Dial(endpoint(cfg.l2Verifier.nodeConfig)) - require.Nil(t, err) - l2GenesisID, l2GenesisTime := getGenesisInfo(l2Client) - - // Start L2 - l2SequencerNode, _, err := l2SequencerGeth(cfg) - require.Nil(t, err) - defer l2SequencerNode.Close() - - err = l2SequencerNode.Start() - require.Nil(t, err) - - l2SequencerClient, err := ethclient.Dial(endpoint(cfg.l2Sequencer.nodeConfig)) - require.Nil(t, err) - - // BSS - bssPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: bssHDPath, + BatchSubmitterHDPath: bssHDPath, + CliqueSignerDerivationPath: cliqueSignerHDPath, + DepositContractAddress: derive.DepositContractAddr, + L1InfoPredeployAddress: derive.L1InfoPredeployAddr, + L1WsAddr: "127.0.0.1", + L1WsPort: 9090, + L1ChainID: big.NewInt(900), + L2ChainID: big.NewInt(901), + Nodes: map[string]rollupNode.Config{ + "verifier": { + L1NodeAddr: "ws://127.0.0.1:9090", + L2EngineAddrs: []string{"ws://127.0.0.1:9091"}, + L2NodeAddr: "ws://127.0.0.1:9091", + L1TrustRPC: false, + }, + "sequencer": { + L1NodeAddr: "ws://127.0.0.1:9090", + L2EngineAddrs: []string{"ws://127.0.0.1:9092"}, + L2NodeAddr: "ws://127.0.0.1:9092", + L1TrustRPC: false, + Sequencer: true, + // Submitter PrivKey is set in system start for rollup nodes where sequencer = true + RPCListenAddr: "127.0.0.1", + RPCListenPort: 9093, + }, }, - }) - require.Nil(t, err) - submitterAddress := crypto.PubkeyToAddress(bssPrivKey.PublicKey) - - // Account - ethPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: "m/44'/60'/0'/0/0", + Loggers: map[string]log.Logger{ + "verifier": testlog.Logger(t, log.LvlError), + "sequencer": testlog.Logger(t, log.LvlError), }, - }) - require.Nil(t, err) - - // Verifier Rollup Node - nodeCfg := &rollupNode.Config{ - L1NodeAddr: endpoint(cfg.l1.nodeConfig), - L2EngineAddrs: []string{endpoint(cfg.l2Verifier.nodeConfig)}, - L2NodeAddr: endpoint(cfg.l2Verifier.nodeConfig), - L1TrustRPC: false, // would be faster to enable, but we want to catch if the RPC is buggy - Rollup: rollup.Config{ - Genesis: rollup.Genesis{ - L1: l1GenesisID, - L2: l2GenesisID, - L2Time: l2GenesisTime, - }, + RollupConfig: rollup.Config{ BlockTime: 1, MaxSequencerDrift: 10, SeqWindowSize: 2, @@ -177,55 +85,75 @@ func TestSystemE2E(t *testing.T) { // TODO pick defaults FeeRecipientAddress: common.Address{0xff, 0x01}, BatchInboxAddress: common.Address{0xff, 0x02}, - BatchSenderAddress: submitterAddress, + // Batch Sender address is filled out in system start }, } - node, err := rollupNode.New(context.Background(), nodeCfg, testlog.Logger(t, log.LvlError), "") - require.Nil(t, err) +} - err = node.Start(context.Background()) - require.Nil(t, err) - defer node.Stop() - - // Sequencer Rollup Node - sequenceCfg := &rollupNode.Config{ - L1NodeAddr: endpoint(cfg.l1.nodeConfig), - L2EngineAddrs: []string{endpoint(cfg.l2Sequencer.nodeConfig)}, - L2NodeAddr: endpoint(cfg.l2Verifier.nodeConfig), - L1TrustRPC: true, // test RPC cache usage - Rollup: rollup.Config{ - Genesis: rollup.Genesis{ - L1: l1GenesisID, - L2: l2GenesisID, - L2Time: l2GenesisTime, - }, - BlockTime: 1, - MaxSequencerDrift: 10, - SeqWindowSize: 2, - L1ChainID: big.NewInt(900), - // TODO pick defaults - FeeRecipientAddress: common.Address{0xff, 0x01}, - BatchInboxAddress: common.Address{0xff, 0x02}, - BatchSenderAddress: submitterAddress, - }, - Sequencer: true, - SubmitterPrivKey: bssPrivKey, - RPCListenAddr: "127.0.0.1", - RPCListenPort: 9093, +func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time.Duration) (*types.Receipt, error) { + timeoutCh := time.After(timeout) + 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: + return nil, errors.New("timeout") + case <-time.After(100 * time.Millisecond): + } } - sequencer, err := rollupNode.New(context.Background(), sequenceCfg, testlog.Logger(t, log.LvlError), "") - require.Nil(t, err) +} - err = sequencer.Start(context.Background()) - require.Nil(t, err) - defer sequencer.Stop() +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() - rollupRPCClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", sequenceCfg.RPCListenAddr, sequenceCfg.RPCListenPort)) + 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, errors.New("timeout") + } + } + +} + +func TestL2OutputSubmitter(t *testing.T) { + log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs + + cfg := defaultSystemConfig(t) + + sys, err := cfg.start() + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + + rollupRPCClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPCListenAddr, cfg.Nodes["sequencer"].RPCListenPort)) require.Nil(t, err) rollupClient := rollupclient.NewRollupClient(rollupRPCClient) // Deploy StateRootOracle - l2OutputPrivKey, err := cfg.wallet.PrivateKey(accounts.Account{ + l2OutputPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ URL: accounts.URL{ Path: l2OutputHDPath, }, @@ -238,17 +166,13 @@ func TestSystemE2E(t *testing.T) { nonce, err := l1Client.NonceAt(ctx, l2OutputAddr, nil) require.Nil(t, err) - opts, err := bind.NewKeyedTransactorWithChainID( - l2OutputPrivKey, cfg.l1.ethConfig.Genesis.Config.ChainID, - ) + opts, err := bind.NewKeyedTransactorWithChainID(l2OutputPrivKey, cfg.L1ChainID) require.Nil(t, err) opts.Nonce = big.NewInt(int64(nonce)) - submissionFrequency := big.NewInt(10) // 10 seconds - l2BlockTime := big.NewInt(2) // 2 seconds - l2ooAddr, tx, l2OutputOracle, err := l2oo.DeployMockL2OutputOracle( - opts, l1Client, submissionFrequency, l2BlockTime, [32]byte{}, big.NewInt(0), - ) + submissionFrequency := big.NewInt(2) // 2 seconds + l2BlockTime := big.NewInt(1) // 1 seconds + l2ooAddr, tx, l2OutputOracle, err := l2oo.DeployMockL2OutputOracle(opts, l1Client, submissionFrequency, l2BlockTime, [32]byte{}, big.NewInt(0)) require.Nil(t, err) ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) @@ -261,16 +185,16 @@ func TestSystemE2E(t *testing.T) { // L2Output Submitter l2OutputSubmitter, err := l2os.NewL2OutputSubmitter(l2os.Config{ - L1EthRpc: endpoint(cfg.l1.nodeConfig), - L2EthRpc: endpoint(cfg.l2Verifier.nodeConfig), - RollupRpc: fmt.Sprintf("http://%s:%d", sequenceCfg.RPCListenAddr, sequenceCfg.RPCListenPort), + L1EthRpc: "ws://127.0.0.1:9090", + L2EthRpc: cfg.Nodes["sequencer"].L2NodeAddr, + RollupRpc: fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPCListenAddr, cfg.Nodes["sequencer"].RPCListenPort), L2OOAddress: l2ooAddr.String(), - PollInterval: 5 * time.Second, + PollInterval: 2 * time.Second, NumConfirmations: 1, - ResubmissionTimeout: 5 * time.Second, + ResubmissionTimeout: 3 * time.Second, SafeAbortNonceTooLowCount: 3, LogLevel: "error", - Mnemonic: cfg.mnemonic, + Mnemonic: cfg.Mnemonic, L2OutputHDPath: l2OutputHDPath, }, "") require.Nil(t, err) @@ -279,104 +203,8 @@ func TestSystemE2E(t *testing.T) { require.Nil(t, err) defer l2OutputSubmitter.Stop() - // Send Transaction & wait for success - contractAddr := common.HexToAddress(cfg.depositContractAddress) - fromAddr := common.HexToAddress("0x30ec912c5b1d14aa6d1cb9aa7a6682415c4f7eb0") - - // start balance - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - startBalance, err := l2Client.BalanceAt(ctx, fromAddr, nil) - require.Nil(t, err) - - // Contract - depositContract, err := deposit.NewDeposit(contractAddr, l1Client) - require.Nil(t, err) - - // Signer - ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - opts, err = bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], big.NewInt(int64(cfg.l1.ethConfig.NetworkId))) - require.Nil(t, err) - - // Setup for L1 Confirmation - watchChan := make(chan *deposit.DepositTransactionDeposited) - watcher, err := depositContract.WatchTransactionDeposited(&bind.WatchOpts{}, watchChan, []common.Address{fromAddr}, []common.Address{fromAddr}) - require.Nil(t, err, "with watcher") - defer watcher.Unsubscribe() - - // Setup for L2 Confirmation - headChan := make(chan *types.Header, 100) - l2HeadSub, err := l2Client.SubscribeNewHead(context.Background(), headChan) - require.Nil(t, err, "with l2 head sub") - defer l2HeadSub.Unsubscribe() - - // Finally send TX - mintAmount := big.NewInt(1_000_000_000_000) - opts.Value = mintAmount - l1DepTx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, big.NewInt(1_000_000), false, nil) - require.Nil(t, err, "with deposit tx") - - // Wait for tx to be mined on L1 (or timeout) - select { - case <-watchChan: - // continue - case err := <-watcher.Err(): - t.Fatalf("Failed on watcher channel: %v", err) - case <-time.After(5 * time.Second): - t.Fatal("Timeout waiting for L1 tx to succeed") - - } - - // Get the L1 Block of the tx - ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second) - defer cancel() - receipt, err := l1Client.TransactionReceipt(ctx, tx.Hash()) - require.Nil(t, err, "Could not get transaction receipt") - // TODO: Include fix for this. - waitNumber := new(big.Int).Add(receipt.BlockNumber, common.Big2) // sequence window effect - waitNumber = new(big.Int).Mul(waitNumber, common.Big2) - - // Wait (or timeout) for that block to show up on L2 - timeoutCh := time.After(6 * time.Second) -loop: - for { - select { - case head := <-headChan: - if head.Number.Cmp(waitNumber) >= 0 { - break loop - } - case err := <-l2HeadSub.Err(): - t.Fatalf("Error in l2 head subscription: %v", err) - case <-timeoutCh: - t.Fatal("Timeout waiting for l2 head") - } - } - - // Based on the L1 event log, compute the deposit-tx hash, and receive the receipt from the derived L2 deposit tx. - ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second) - defer cancel() - l1DepReceipt, err := l1Client.TransactionReceipt(ctx, l1DepTx.Hash()) - require.Nil(t, err, "Could not get L1 deposit receipt") - reconstructedDep, err := derive.UnmarshalLogEvent(l1DepReceipt.Logs[0]) - require.NoError(t, err) - l2DepTx := types.NewTx(reconstructedDep) - depHash := l2DepTx.Hash() - depositReceipt, err := l2Client.TransactionReceipt(context.Background(), depHash) - require.NoError(t, err) - require.Equal(t, depositReceipt.Status, types.ReceiptStatusSuccessful) - - // Confirm balance - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - endBalance, err := l2Client.BalanceAt(ctx, fromAddr, nil) - require.Nil(t, err) - - diff := new(big.Int) - diff = diff.Sub(endBalance, startBalance) - require.Equal(t, diff, mintAmount, "Did not get expected balance change") - // Wait for batch submitter to update L2 output oracle. - timeoutCh = time.After(15 * time.Second) + timeoutCh := time.After(15 * time.Second) for { l2ooTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{}) require.Nil(t, err) @@ -416,45 +244,162 @@ loop: } } +} + +// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. +// All nodes are run in process (but are the full nodes, not mocked or stubbed). +func TestSystemE2E(t *testing.T) { + log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs + + cfg := defaultSystemConfig(t) + + sys, err := cfg.start() + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + l2Seq := sys.Clients["sequencer"] + l2Verif := sys.Clients["verifier"] + + // Transactor Account + ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: "m/44'/60'/0'/0/0", + }, + }) + require.Nil(t, err) + + // Send Transaction & wait for success + fromAddr := common.HexToAddress("0x30ec912c5b1d14aa6d1cb9aa7a6682415c4f7eb0") + + // Find deposit contract + depositContract, err := deposit.NewDeposit(cfg.DepositContractAddress, l1Client) + require.Nil(t, err) + l1Node := sys.nodes["l1"] + + // Create signer + ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainID) + require.Nil(t, err) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + // Finally send TX + mintAmount := big.NewInt(1_000_000_000_000) + opts.Value = mintAmount + tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, big.NewInt(1_000_000), false, nil) + require.Nil(t, err, "with deposit tx") + + receipt, err := waitForTransaction(tx.Hash(), l1Client, 6*time.Second) + require.Nil(t, err, "Waiting for deposit tx on L1") + + reconstructedDep, err := derive.UnmarshalLogEvent(receipt.Logs[0]) + require.NoError(t, err, "Could not reconstruct L2 Deposit") + tx = types.NewTx(reconstructedDep) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Second) + require.NoError(t, err) + require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) + + // Confirm balance + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + endBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + diff := new(big.Int) + diff = diff.Sub(endBalance, startBalance) + require.Equal(t, diff, mintAmount, "Did not get expected balance change") + // Submit TX to L2 sequencer node toAddr := common.Address{0xff, 0xff} - tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(new(big.Int).SetUint64(cfg.l2Verifier.ethConfig.NetworkId)), &types.DynamicFeeTx{ - ChainID: big.NewInt(int64(cfg.l2Verifier.ethConfig.NetworkId)), - Nonce: 1, // guess + tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainID, + Nonce: 1, // Already have deposit To: &toAddr, Value: big.NewInt(1_000_000_000), GasTipCap: big.NewInt(10), GasFeeCap: big.NewInt(200), Gas: 21000, }) - err = l2SequencerClient.SendTransaction(context.Background(), tx) - require.Nil(t, err) + err = l2Seq.SendTransaction(context.Background(), tx) + require.Nil(t, err, "Sending L2 tx to sequencer") - var l2IncludedBlock *big.Int + _, err = waitForTransaction(tx.Hash(), l2Seq, 6*time.Second) + require.Nil(t, err, "Waiting for L2 tx on sequencer") - // Wait for tx to show up in chain (on sequencer) - timeoutCh = time.After(6 * time.Second) -lastLoop: - for { - select { - case <-timeoutCh: - t.Fatal("Timeout waiting for l2 transaction") - case <-time.After(200 * time.Millisecond): - } + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Second) + require.Nil(t, err, "Waiting for L2 tx on verifier") - receipt, err := l2Client.TransactionReceipt(context.Background(), tx.Hash()) - if receipt != nil && err == nil { - l2IncludedBlock = receipt.BlockNumber - break lastLoop - } else if err != nil && !errors.Is(err, ethereum.NotFound) { - require.Nil(t, err) - } - } - - verifBlock, err := l2Client.BlockByNumber(context.Background(), l2IncludedBlock) + // Verify blocks match after batch submission on verifiers and sequencers + verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber) require.Nil(t, err) - seqBlock, err := l2SequencerClient.BlockByNumber(context.Background(), l2IncludedBlock) + seqBlock, err := l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber) require.Nil(t, err) require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") } + +func TestMissingBatchE2E(t *testing.T) { + log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs + + cfg := defaultSystemConfig(t) + // Specifically set batch submitter balance to stop batches from being included + cfg.Premine[bssHDPath] = 0 + // Don't pollute log with expected "Error submitting batch" logs + cfg.Loggers["sequencer"] = testlog.Logger(t, log.LvlCrit) + + sys, err := cfg.start() + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l2Seq := sys.Clients["sequencer"] + l2Verif := sys.Clients["verifier"] + + // Transactor Account + ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: transactorHDPath, + }, + }) + require.Nil(t, err) + + // Submit TX to L2 sequencer node + toAddr := common.Address{0xff, 0xff} + tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainID, + Nonce: 0, + To: &toAddr, + Value: big.NewInt(1_000_000_000), + GasTipCap: big.NewInt(10), + GasFeeCap: big.NewInt(200), + Gas: 21000, + }) + err = l2Seq.SendTransaction(context.Background(), tx) + require.Nil(t, err, "Sending L2 tx to sequencer") + + // Let it show up on the unsafe chain + receipt, err := waitForTransaction(tx.Hash(), l2Seq, 6*time.Second) + require.Nil(t, err, "Waiting for L2 tx on sequencer") + + // Wait until the block it was first included in shows up in the safe chain on the verifier + _, err = waitForBlock(receipt.BlockNumber, l2Verif, 4*time.Second) + require.Nil(t, err, "Waiting for block on verifier") + + // Assert that the transaction is not found on the verifier + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + _, err = l2Verif.TransactionReceipt(ctx, tx.Hash()) + require.Equal(t, ethereum.NotFound, err, "Found transaction in verifier when it should not have been included") + + // Wait a short time for the L2 reorg to occur on the sequencer. + // The proper thing to do is to wait until the sequencer marks this block safe. + <-time.After(200 * time.Millisecond) + + // Assert that the reconciliation process did an L2 reorg on the sequencer to remove the invalid block + block, err := l2Seq.BlockByNumber(ctx, receipt.BlockNumber) + require.Nil(t, err, "Get block from sequencer") + require.NotEqual(t, block.Hash(), receipt.BlockHash, "L2 Sequencer did not reorg out transaction on it's safe chain") +} From 55a38681a0553c6058eb99d230e19dbd29926b10 Mon Sep 17 00:00:00 2001 From: norswap Date: Sat, 9 Apr 2022 00:14:15 +0200 Subject: [PATCH 467/585] Fix sync-start bug + improve sync-start comments (#355) Fix bug (L1 origin head with non-canonical ancestors) This happened in the scenario where `l2ahead == true` (L1 origin of start is ahead of know L1 head) and `start` had an ancestor whose L1 origin was known not to be canonical. Example: L1 head is at block X. `start` has an L1 origin with number X + 1 but its parent L2 block has an L1 origin with number X whose blockhash is not canonical. In this case, the algorithm still returned `start` as the unsafe L1 head, which is incorrect. This also touches a bunch of comments to generally improve understanbility. --- opnode/rollup/sync/start.go | 203 ++++++++++++++++++++++-------------- 1 file changed, 122 insertions(+), 81 deletions(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index d60079df97ce..d0d01e16f36a 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -1,39 +1,38 @@ // The sync package is responsible for reconciling L1 and L2. // +// The Ethereum chain is a DAG of blocks with the root block being the genesis block. At any given +// time, the head (or tip) of the chain can change if an offshoot/branch of the chain has a higher +// number. This is known as a re-organization of the canonical chain. Each block points to a parent +// block and the node is responsible for deciding which block is the head and thus the mapping from +// block number to canonical block. // -// The ethereum chain is a DAG of blocks with the root block being the genesis block. -// At any given time, the head (or tip) of the chain can change if an offshoot of the chain -// has a higher number. This is known as a re-organization of the canonical chain. -// Each block points to a parent block and the node is responsible for deciding which block is the head -// and thus the mapping from block number to canonical block. +// The Optimism (L2) chain has similar properties, but also retains references to the Ethereum (L1) +// chain. Each L2 block retains a reference to an L1 block (its "L1 origin", i.e. L1 block +// associated with the epoch that the L2 block belongs to) and to its parent L2 block. The L2 chain +// node must satisfy the following validity rules: // -// The optimism chain has similar properties, but also retains references to the ethereum chain. -// Each optimism block retains a reference to an L1 block and to its parent L2 block. -// The L2 chain node must satisfy the following validity rules -// 1. l2block.height == l2parent.block.height + 1 -// 2. l2block.l1Origin.height >= l2block.l2parent.l1Origin.height +// 1. l2block.number == l2block.l2parent.block.number + 1 +// 2. l2block.l1Origin.number >= l2block.l2parent.l1Origin.number // 3. l2block.l1Origin is in the canonical chain on L1 // 4. l1_rollup_genesis is an ancestor of l2block.l1Origin // +// During normal operation, both the L1 and L2 canonical chains can change, due to a re-organisation +// or due to an extension (new L1 or L2 block). // -// During normal operation, both the L1 and L2 canonical chains can change, due to a reorg -// or an extension (new block). -// - L1 reorg -// - L1 extension -// - L2 reorg -// - L2 extension +// When one of these changes occurs, the rollup node needs to determine what the new L2 head blocks +// should be. We track two L2 head blocks: // -// When one of these changes occurs, the rollup node needs to determine what the new L2 Heads should be. -// In a simple extension case, the L2 head remains the same, but in the case of a re-org on L1, it needs -// to find the unsafe and safe blocks. +// - The *unsafe L2 block*: This is the highest L2 block whose L1 origin is a plausible (1) +// extension of the canonical L1 chain (as known to the opnode). +// - The *safe L2 block*: This is the highest L2 block whose epoch's sequencing window is +// complete within the canonical L1 chain (as known to the opnode). // -// Unsafe Block: The highest L2 block. If the L1 Attributes is ahead of the L1 head, it is assumed to be valid, -// if not, it walks back until it finds the first L2 block whose L1 Origin is canonical in the L1 chain. -// Safe Block: The highest L2 block whose sequence window has not changed during a reorg. +// (1) Plausible meaning that the blockhash of the L2 block's L1 origin (as reported in the L1 +// Attributes deposit within the L2 block) is not canonical at another height in the L1 chain, +// and the same holds for all its ancestors. // -// The safe block can be found by walking back one sequence window from the "latest" L2 block. The latest L2 -// block is the first L2 block whose L1 Origin is canonical in L1. If the unsafe block is ahead of the L1 -// chain, the latest block and unsafe block are not the same. +// In particular, in the case of L1 extension, the L2 unsafe head will generally remain the same, +// but in the case of an L1 re-org, we need to search for the new safe and unsafe L2 block. package sync import ( @@ -41,7 +40,6 @@ import ( "errors" "fmt" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -62,96 +60,139 @@ var TooDeepReorgErr = errors.New("reorg is too deep") const MaxReorgDepth = 500 -// isCanonical returns true if the supplied block ID is canonical in the L1 chain. -// It will suppress ethereum.NotFound errors -func isCanonical(ctx context.Context, l1 L1Chain, block eth.BlockID) (bool, error) { - canonical, err := l1.L1BlockRefByNumber(ctx, block.Number) - if err != nil && !errors.Is(err, ethereum.NotFound) { - return false, err - } else if err != nil { - return false, nil +// isCanonical returns the following values: +// - `aheadOrCanonical: true if the supplied block is ahead of the known head of the L1 chain, +// or canonical in the L1 chain. +// - `canonical`: true if the block is canonical in the L1 chain. +func isAheadOrCanonical(ctx context.Context, l1 L1Chain, block eth.BlockID) (aheadOrCanonical bool, canonical bool, err error) { + if l1Head, err := l1.L1HeadBlockRef(ctx); err != nil { + return false, false, err + } else if block.Number > l1Head.Number { + return true, false, nil + } else if canonical, err := l1.L1BlockRefByNumber(ctx, block.Number); err != nil { + return false, false, err + } else { + canonical := canonical.Hash == block.Hash + return canonical, canonical, nil } - return canonical.Hash == block.Hash, nil } -// FindL2Heads walks back from the supplied L2 blocks and finds the unsafe and safe L2 blocks. -// Unsafe Block: The highest L2 block. If the L1 Attributes is ahead of the L1 head, it is assumed to be valid, -// if not, it walks back until it finds the first L2 block whose L1 Origin is canonical in the L1 chain. -// Safe Block: The highest L2 block whose sequence window has not changed during a reorg. +// FindL2Heads walks back from `start` (the previous unsafe L2 block) and finds the unsafe and safe +// L2 blocks. +// +// - The *unsafe L2 block*: This is the highest L2 block whose L1 origin is a plausible (1) +// extension of the canonical L1 chain (as known to the opnode). +// - The *safe L2 block*: This is the highest L2 block whose epoch's sequencing window is +// complete within the canonical L1 chain (as known to the opnode). +// +// (1) Plausible meaning that the blockhash of the L2 block's L1 origin (as reported in the L1 +// Attributes deposit within the L2 block) is not canonical at another height in the L1 chain, +// and the same holds for all its ancestors. func FindL2Heads(ctx context.Context, start eth.L2BlockRef, seqWindowSize uint64, l1 L1Chain, l2 L2Chain, genesis *rollup.Genesis) (unsafe eth.L2BlockRef, safe eth.L2BlockRef, err error) { + + // Loop 1. Walk the L2 chain backwards until we find an L2 block whose L1 origin is canonical. + + // Current L2 block. + n := start + + // Number of blocks between n and start. reorgDepth := 0 + + // Blockhash of L1 origin hash for the L2 block during the previous iteration, 0 for first + // iteration. When this changes as we walk the L2 chain backwards, it means we're seeing a different + // (earlier) epoch. var prevL1OriginHash common.Hash - // First check if the L1 Origin of the start block is ahead of the current L1 head - // If so, we assume that this should be the next unsafe head for the sequencing window - // We still need to walk back the safe head because we don't know where the reorg started. - l1Head, err := l1.L1HeadBlockRef(ctx) - if err != nil { - return eth.L2BlockRef{}, eth.L2BlockRef{}, err - } - l2Ahead := start.L1Origin.Number > l1Head.Number - var latest eth.L2BlockRef - // Walk L2 chain until we find the "latest" L2 block. This the first L2 block whose L1 Origin is canonical. - for n := start; ; { - // Check if l1Origin is canonical when we get to a new epoch + // The highest L2 ancestor of `start` (or `start` itself) whose ancestors are not (yet) known + // to have a non-canonical L1 origin. Empty if no such candidate is known yet. Guaranteed to be + // set after exiting from Loop 1. + var highestPlausibleCanonicalOrigin eth.L2BlockRef + + for { + // Check if l1Origin is canonical when we get to a new epoch. if prevL1OriginHash != n.L1Origin.Hash { - if ok, err := isCanonical(ctx, l1, n.L1Origin); err != nil { + prevL1OriginHash = n.L1Origin.Hash + + if plausible, canonical, err := isAheadOrCanonical(ctx, l1, n.L1Origin); err != nil { return eth.L2BlockRef{}, eth.L2BlockRef{}, err - } else if ok { - latest = n - break + } else if !plausible { + // L1 origin nor ahead of L1 head nor canonical, discard previous candidate and + // keep looking. + highestPlausibleCanonicalOrigin = eth.L2BlockRef{} + } else { + if highestPlausibleCanonicalOrigin == (eth.L2BlockRef{}) { + // No highest plausible candidate, make L2 block new candidate. + highestPlausibleCanonicalOrigin = n + } + if canonical { + break + } } - prevL1OriginHash = n.L1Origin.Hash } - // Don't walk past genesis. If we were at the L2 genesis, but could not find the L1 genesis - // pointed to from it, we are on the wrong L1 chain. + + // Don't walk past genesis. If we were at the L2 genesis, but could not find its L1 origin, + // the L2 chain is building on the wrong L1 branch. if n.Hash == genesis.L2.Hash || n.Number == genesis.L2.Number { return eth.L2BlockRef{}, eth.L2BlockRef{}, WrongChainErr } + // Pull L2 parent for next iteration n, err = l2.L2BlockRefByHash(ctx, n.ParentHash) if err != nil { - return eth.L2BlockRef{}, eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) + return eth.L2BlockRef{}, eth.L2BlockRef{}, + fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) } + reorgDepth++ if reorgDepth >= MaxReorgDepth { + // If the reorg depth is too large, something is fishy. + // This can legitimately happen if L1 goes down for a while. But in that case, + // restarting the L2 node with a bigger configured MaxReorgDepth is an acceptable + // stopgap solution. + // Currently this can also happen if the L2 node is down for a while, but in the future + // state sync should prevent this issue. return eth.L2BlockRef{}, eth.L2BlockRef{}, TooDeepReorgErr } } - depth := uint64(1) // SeqWindowSize is a length, but we are counting elements in the window. - prevL1OriginHash = latest.L1Origin.Hash - // Walk from the latest block back 1 Sequence Window of L1 Origins to determine the safe L2 block. - for n := latest; ; { - // Advance depth if new origin + + // Loop 2. Walk from the L1 origin of the `n` block (*) back to the L1 block that starts the + // sequencing window ending at that block. Instead of iterating on L1 blocks, we actually + // iterate on L2 blocks, because we want to find the safe L2 head, i.e. the highest L2 block + // whose L1 origin is the start of the sequencing window. + + // (*) `n` being at this stage the highest L2 block whose L1 origin is canonical. + + // Depth counter: we need to walk back `seqWindowSize` L1 blocks in order to find the start + // of the sequencing window. + depth := uint64(1) + + // Before entering the loop: `prevL1OriginHash == n.L1Origin.Hash` + // The original definitions of `n` and `prevL1OriginHash` still hold. + for { + // Advance depth if we change to a different (earlier) epoch. if n.L1Origin.Hash != prevL1OriginHash { depth++ prevL1OriginHash = n.L1Origin.Hash } - // Walked sufficiently far - if depth == seqWindowSize { - if l2Ahead { - return start, n, nil - } else { - return latest, n, nil - } + // Found an L2 block whose L1 origin is the start of the sequencing window. + if depth == seqWindowSize { + return highestPlausibleCanonicalOrigin, n, nil } + // Genesis is always safe. if n.Hash == genesis.L2.Hash || n.Number == genesis.L2.Number { - safe = eth.L2BlockRef{Hash: genesis.L2.Hash, Number: genesis.L2.Number, Time: genesis.L2Time, L1Origin: genesis.L1} - if l2Ahead { - return start, safe, nil - } else { - return latest, safe, nil - } - + safe = eth.L2BlockRef{Hash: genesis.L2.Hash, Number: genesis.L2.Number, + Time: genesis.L2Time, L1Origin: genesis.L1} + return highestPlausibleCanonicalOrigin, safe, nil } - // Pull L2 parent for next iteration + + // Pull L2 parent for next iteration. n, err = l2.L2BlockRefByHash(ctx, n.ParentHash) if err != nil { - return eth.L2BlockRef{}, eth.L2BlockRef{}, fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) + return eth.L2BlockRef{}, eth.L2BlockRef{}, + fmt.Errorf("failed to fetch L2 block by hash %v: %w", n.ParentHash, err) } } - } From ce0590497cf2e6941e9263e5002582076c626e5e Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Fri, 8 Apr 2022 16:13:07 -0700 Subject: [PATCH 468/585] feat: deposit tx js helpers (#352) * feat: js deposit tx Hardhat task now lists the tx hash * rollup: new deposit hashing * nice api! * fix: dockerfile --- package.json | 3 +- packages/contracts/helpers/index.ts | 216 ++++++++++++++++++++++++ packages/contracts/package.json | 5 + packages/contracts/tasks/deposits.ts | 51 +++++- packages/contracts/test/helpers.spec.ts | 54 ++++++ packages/contracts/yarn.lock | 48 ++++++ 6 files changed, 368 insertions(+), 9 deletions(-) create mode 100644 packages/contracts/helpers/index.ts create mode 100644 packages/contracts/test/helpers.spec.ts diff --git a/package.json b/package.json index 4a3c7f780241..3ba44a57c61f 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "lint:toc": "doctoc --title=\"**Table of Contents**\" ./specs ./meta" }, "dependencies": { - "@eth-optimism/core-utils": "^0.8.1" + "@eth-optimism/core-utils": "^0.8.1", + "@ethersproject/constants": "^5.6.0" } } diff --git a/packages/contracts/helpers/index.ts b/packages/contracts/helpers/index.ts new file mode 100644 index 000000000000..639f068d0830 --- /dev/null +++ b/packages/contracts/helpers/index.ts @@ -0,0 +1,216 @@ +import * as RLP from '@ethersproject/rlp' +import { BigNumber, BigNumberish } from '@ethersproject/bignumber' +import { getAddress } from '@ethersproject/address' +import { + hexConcat, + stripZeros, + zeroPad, + arrayify, + BytesLike, +} from '@ethersproject/bytes' +import { keccak256 } from '@ethersproject/keccak256' +import { Zero } from '@ethersproject/constants' +import { ContractReceipt, Event } from '@ethersproject/contracts' + +function formatNumber(value: BigNumberish, name: string): Uint8Array { + const result = stripZeros(BigNumber.from(value).toHexString()) + if (result.length > 32) { + throw new Error(`invalid length for ${name}`) + } + return result +} + +function handleNumber(value: string): BigNumber { + if (value === '0x') { + return Zero + } + return BigNumber.from(value) +} + +function handleAddress(value: string): string { + if (value === '0x') { + // @ts-ignore + return null + } + return getAddress(value) +} + +export enum SourceHashDomain { + UserDeposit = 0, + L1InfoDeposit = 1, +} + +interface DepositTxOpts { + sourceHash?: string + from: string + to: string | null + mint: BigNumberish + value: BigNumberish + gas: BigNumberish + data: string + domain?: SourceHashDomain + l1BlockHash?: string + logIndex?: BigNumberish + sequenceNumber?: BigNumberish +} + +interface DepostTxExtraOpts { + domain?: SourceHashDomain + l1BlockHash?: string + logIndex?: BigNumberish + sequenceNumber?: BigNumberish +} + +export class DepositTx { + public type = '0x7E' + private _sourceHash?: string + public from: string + public to: string | null + public mint: BigNumberish + public value: BigNumberish + public gas: BigNumberish + public data: BigNumberish + + public domain?: SourceHashDomain + public l1BlockHash?: string + public logIndex?: BigNumberish + public sequenceNumber?: BigNumberish + + constructor(opts: Partial = {}) { + this._sourceHash = opts.sourceHash + this.from = opts.from! + this.to = opts.to! + this.mint = opts.mint! + this.value = opts.value! + this.gas = opts.gas! + this.data = opts.data! + this.domain = opts.domain + this.l1BlockHash = opts.l1BlockHash + this.logIndex = opts.logIndex + this.sequenceNumber = opts.sequenceNumber + } + + hash() { + const encoded = this.encode() + return keccak256(encoded) + } + + sourceHash() { + if (!this._sourceHash) { + let marker: string + switch (this.domain) { + case SourceHashDomain.UserDeposit: + marker = BigNumber.from(this.logIndex).toHexString() + break + case SourceHashDomain.L1InfoDeposit: + marker = BigNumber.from(this.sequenceNumber).toHexString() + break + default: + throw new Error(`Unknown domain: ${this.domain}`) + } + + if (!this.l1BlockHash) { + throw new Error('Need l1BlockHash to compute sourceHash') + } + + const l1BlockHash = this.l1BlockHash + const input = hexConcat([l1BlockHash, zeroPad(marker, 32)]) + const depositIDHash = keccak256(input) + const domain = BigNumber.from(this.domain).toHexString() + const domainInput = hexConcat([zeroPad(domain, 32), depositIDHash]) + this._sourceHash = keccak256(domainInput) + } + return this._sourceHash + } + + encode() { + const fields: any = [ + this.sourceHash() || '0x', + getAddress(this.from) || '0x', + this.to != null ? getAddress(this.to) : '0x', + formatNumber(this.mint || 0, 'mint'), + formatNumber(this.value || 0, 'value'), + formatNumber(this.gas || 0, 'gas'), + this.data || '0x', + ] + + return hexConcat([this.type, RLP.encode(fields)]) + } + + decode(raw: BytesLike, extra: DepostTxExtraOpts = {}) { + const payload = arrayify(raw) + const transaction = RLP.decode(payload.slice(1)) + + this._sourceHash = transaction[0] + this.from = handleAddress(transaction[1]) + this.to = handleAddress(transaction[2]) + this.mint = handleNumber(transaction[3]) + this.value = handleNumber(transaction[4]) + this.gas = handleNumber(transaction[5]) + this.data = transaction[6] + + if ('l1BlockHash' in extra) { + this.l1BlockHash = extra.l1BlockHash + } + if ('domain' in extra) { + this.domain = extra.domain + } + if ('logIndex' in extra) { + this.logIndex = extra.logIndex + } + if ('sequenceNumber' in extra) { + this.sequenceNumber = extra.sequenceNumber + } + return this + } + + static decode(raw: BytesLike, extra?: DepostTxExtraOpts): DepositTx { + return new this().decode(raw, extra) + } + + fromL1Receipt(receipt: ContractReceipt, index: number): DepositTx { + if (!receipt.events) throw new Error('cannot parse receipt') + const event = receipt.events[index] + if (!event) { + throw new Error(`event index ${index} does not exist`) + } + return this.fromL1Event(event) + } + + static fromL1Receipt(receipt: ContractReceipt, index: number): DepositTx { + return new this({}).fromL1Receipt(receipt, index) + } + + fromL1Event(event: Event): DepositTx { + if (event.event !== 'TransactionDeposited') + throw new Error(`incorrect event type: ${event.event}`) + if (typeof event.args === 'undefined') throw new Error('no event args') + if (typeof event.args.from === 'undefined') + throw new Error('"from" undefined') + this.from = event.args.from + if (typeof event.args.isCreation === 'undefined') + throw new Error('"isCreation" undefined') + if (typeof event.args.to === 'undefined') throw new Error('"to" undefined') + this.to = event.args.isCreation ? null : event.args.to + if (typeof event.args.mint === 'undefined') + throw new Error('"mint" undefined') + this.mint = event.args.mint + if (typeof event.args.value === 'undefined') + throw new Error('"value" undefined') + this.value = event.args.value + if (typeof event.args.gasLimit === 'undefined') + throw new Error('"gasLimit" undefined') + this.gas = event.args.gasLimit + if (typeof event.args.data === 'undefined') + throw new Error('"data" undefined') + this.data = event.args.data + this.domain = SourceHashDomain.UserDeposit + this.l1BlockHash = event.blockHash + this.logIndex = event.logIndex + return this + } + + static fromL1Event(event: Event): DepositTx { + return new this({}).fromL1Event(event) + } +} diff --git a/packages/contracts/package.json b/packages/contracts/package.json index a74512a71bfb..39c775d64631 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -5,6 +5,11 @@ "main": "index.js", "license": "MIT", "dependencies": { + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/rlp": "^5.6.0", "hardhat": "^2.7.1", "rlp": "^2.2.7" }, diff --git a/packages/contracts/tasks/deposits.ts b/packages/contracts/tasks/deposits.ts index 7d194b685beb..eb7306a971b1 100644 --- a/packages/contracts/tasks/deposits.ts +++ b/packages/contracts/tasks/deposits.ts @@ -1,9 +1,15 @@ import { task, types } from 'hardhat/config' import { Contract, providers, utils, Wallet } from 'ethers' +import { Event } from '@ethersproject/contracts' import dotenv from 'dotenv' +import { DepositTx, SourceHashDomain } from '../helpers/index' dotenv.config() +async function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + task('deposit', 'Deposits funds onto L2.') .addParam( 'l1ProviderUrl', @@ -11,6 +17,12 @@ task('deposit', 'Deposits funds onto L2.') 'http://localhost:8545', types.string ) + .addParam( + 'l2ProviderUrl', + 'L2 provider URL.', + 'http://localhost:9545', + types.string + ) .addParam('to', 'Recipient address.', null, types.string) .addParam('amountEth', 'Amount in ETH to send.', null, types.string) .addOptionalParam( @@ -26,11 +38,18 @@ task('deposit', 'Deposits funds onto L2.') types.string ) .setAction(async (args) => { - const { l1ProviderUrl, to, amountEth, depositContractAddr, privateKey } = - args + const { + l1ProviderUrl, + l2ProviderUrl, + to, + amountEth, + depositContractAddr, + privateKey, + } = args const depositFeedArtifact = require('../artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json') const l1Provider = new providers.JsonRpcProvider(l1ProviderUrl) + const l2Provider = new providers.JsonRpcProvider(l2ProviderUrl) let l1Wallet: Wallet | providers.JsonRpcSigner if (privateKey) { @@ -52,7 +71,8 @@ task('deposit', 'Deposits funds onto L2.') ).connect(l1Wallet) const amountWei = utils.parseEther(amountEth) - console.log(`Depositing ${amountEth} ETH to ${to}...`) + const value = amountWei.add(utils.parseEther('0.01')) + console.log(`Depositing ${amountEth} ETH to ${to}`) // Below adds 0.01 ETH to account for gas. const tx = await depositFeed.depositTransaction( to, @@ -60,11 +80,26 @@ task('deposit', 'Deposits funds onto L2.') '3000000', false, [], - { - value: amountWei.add(utils.parseEther('0.01')), - } + { value } ) console.log(`Got TX hash ${tx.hash}. Waiting...`) - await tx.wait() - console.log('Done.') + const receipt = await tx.wait() + + // find the transaction deposited event and derive + // the deposit transaction from it + const event = receipt.events.find( + (e: Event) => e.event === 'TransactionDeposited' + ) + const l2tx = DepositTx.fromL1Event(event) + const hash = l2tx.hash() + console.log(`Waiting for L2 TX hash ${hash}`) + + while (true) { + const tx = await l2Provider.send('eth_getTransactionByHash', [hash]) + if (tx) { + console.log('Deposit success') + break + } + await sleep(500) + } }) diff --git a/packages/contracts/test/helpers.spec.ts b/packages/contracts/test/helpers.spec.ts new file mode 100644 index 000000000000..a8e0f5f1a843 --- /dev/null +++ b/packages/contracts/test/helpers.spec.ts @@ -0,0 +1,54 @@ +import { expect } from 'chai' +import { DepositTx, SourceHashDomain } from '../helpers' +import { BigNumber } from '@ethersproject/bignumber' + +describe('Helpers', () => { + describe('DepositTx', () => { + it('should serialize/deserialize and hash', () => { + // constants serialized using optimistic-geth + // TODO(tynes): more tests + const hash = + '0xf5f97d03e8be48a4b20ed70c9d8b11f1c851bf949bf602b7580985705bb09077' + const raw = + '0x7ef862a077fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd073594de3829a23df1479438622a08a116e8eb3f620bb594b7e390864a90b7b923c9f9310c6f98aafe43f707880e043da617250000880de0b6b3a7640000832dc6c080' + + const tx = new DepositTx({ + from: '0xDe3829A23DF1479438622a08a116E8Eb3f620BB5', + gas: '0x2dc6c0', + data: '0x', + to: '0xB7e390864a90b7b923C9f9310C6F98aafE43F707', + value: '0xde0b6b3a7640000', + domain: SourceHashDomain.UserDeposit, + l1BlockHash: + '0xd1a498e053451fc90bd8a597051a1039010c8e55e2659b940d3070b326e4f4c5', + logIndex: 0, + mint: '0xe043da617250000', + }) + + const sourceHash = tx.sourceHash() + expect(sourceHash).to.deep.eq( + '0x77fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd0735' + ) + + const encoded = tx.encode() + expect(encoded).to.deep.eq(raw) + const hashed = tx.hash() + expect(hashed).to.deep.eq(hash) + + const decoded = DepositTx.decode(raw, { + domain: SourceHashDomain.UserDeposit, + l1BlockHash: tx.l1BlockHash, + logIndex: tx.logIndex, + }) + expect(decoded.from).to.deep.eq(tx.from) + expect(decoded.gas).to.deep.eq(BigNumber.from(tx.gas)) + expect(decoded.data).to.deep.eq(tx.data) + expect(decoded.to).to.deep.eq(tx.to) + expect(decoded.value).to.deep.eq(BigNumber.from(tx.value)) + expect(decoded.domain).to.deep.eq(SourceHashDomain.UserDeposit) + expect(decoded.l1BlockHash).to.deep.eq(tx.l1BlockHash) + expect(decoded.logIndex).to.deep.eq(tx.logIndex) + expect(decoded.mint).to.deep.eq(BigNumber.from(tx.mint)) + }) + }) +}) diff --git a/packages/contracts/yarn.lock b/packages/contracts/yarn.lock index 416ab6d28565..0b8635d57e36 100644 --- a/packages/contracts/yarn.lock +++ b/packages/contracts/yarn.lock @@ -288,6 +288,17 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/rlp" "^5.5.0" +"@ethersproject/address@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" + integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/base64@5.5.0", "@ethersproject/base64@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" @@ -312,6 +323,15 @@ "@ethersproject/logger" "^5.5.0" bn.js "^4.11.9" +"@ethersproject/bignumber@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.0.tgz#116c81b075c57fa765a8f3822648cf718a8a0e26" + integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + bn.js "^4.11.9" + "@ethersproject/bytes@5.5.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" @@ -319,6 +339,13 @@ dependencies: "@ethersproject/logger" "^5.5.0" +"@ethersproject/bytes@^5.6.0", "@ethersproject/bytes@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" + integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/constants@5.5.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" @@ -401,11 +428,24 @@ "@ethersproject/bytes" "^5.5.0" js-sha3 "0.8.0" +"@ethersproject/keccak256@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.0.tgz#fea4bb47dbf8f131c2e1774a1cecbfeb9d606459" + integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== + dependencies: + "@ethersproject/bytes" "^5.6.0" + js-sha3 "0.8.0" + "@ethersproject/logger@5.5.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== +"@ethersproject/logger@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" + integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== + "@ethersproject/networks@5.5.1", "@ethersproject/networks@^5.5.0": version "5.5.1" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.1.tgz#b7f7b9fb88dec1ea48f739b7fb9621311aa8ce6c" @@ -469,6 +509,14 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" +"@ethersproject/rlp@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.0.tgz#55a7be01c6f5e64d6e6e7edb6061aa120962a717" + integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2@5.5.0", "@ethersproject/sha2@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" From 8afca466066f90ba7905d57be36db75df044d6a8 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 8 Apr 2022 17:18:40 -0600 Subject: [PATCH 469/585] devnet: Hardcode deposit feed bytecode (#359) --- Makefile | 3 +-- packages/contracts/tasks/deposits.ts | 2 +- packages/integration-tests/test/deposit.spec.ts | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 21552d596667..a8ec1641fbd5 100644 --- a/Makefile +++ b/Makefile @@ -36,11 +36,10 @@ devnet-clean: devnet-down .PHONY: devnet-clean devnet-up: - @test -f ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json @test -f ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json @test -f ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json @(cd ./ops && \ - DEPOSIT_FEED_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json | jq .deployedBytecode) \ + DEPOSIT_FEED_BYTECODE="0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" \ L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ WITHDRAWER_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json | jq .deployedBytecode) \ GENESIS_TIMESTAMP=$(shell date +%s) \ diff --git a/packages/contracts/tasks/deposits.ts b/packages/contracts/tasks/deposits.ts index eb7306a971b1..b34dbf2e6bb6 100644 --- a/packages/contracts/tasks/deposits.ts +++ b/packages/contracts/tasks/deposits.ts @@ -46,7 +46,7 @@ task('deposit', 'Deposits funds onto L2.') depositContractAddr, privateKey, } = args - const depositFeedArtifact = require('../artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json') + const depositFeedArtifact = require('../artifacts/contracts/L1/OptimismPortal.sol/OptimismPortal.json') const l1Provider = new providers.JsonRpcProvider(l1ProviderUrl) const l2Provider = new providers.JsonRpcProvider(l2ProviderUrl) diff --git a/packages/integration-tests/test/deposit.spec.ts b/packages/integration-tests/test/deposit.spec.ts index 80846c1425f4..ac21253b44e7 100644 --- a/packages/integration-tests/test/deposit.spec.ts +++ b/packages/integration-tests/test/deposit.spec.ts @@ -7,7 +7,7 @@ import { DEPOSIT_FEED_ADDR } from './shared/constants' import { defaultTransactionFactory } from './shared/utils' import env from './shared/env' -const depositFeedArtifact = require('../../contracts/artifacts/contracts/L1/DepositFeed.sol/DepositFeed.json') +const depositFeedArtifact = require('../../contracts/artifacts/contracts/L1/OptimismPortal.sol/OptimismPortal.json') const counterArtifact = require('../artifacts/Counter.sol/Counter.json') const multiDepositorArtifact = require('../artifacts/MultiDepositor.sol/MultiDepositor.json') From 21b2b4d03d41c27667a481941e76f03fedddd802 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 8 Apr 2022 16:19:42 -0700 Subject: [PATCH 470/585] opnode,l2os: Better lifecycle management (#358) * opnode: Properly wait for limit client to shut down We removed closing the semaphore channel because it would cause a panic as we did not wait for in flight requests (and new requests) to stop before closing the L1 source. * l2os: Change shutdown procedure This is now blocking, but also reuces the amount of error logs. * opnode: Shutdown rollup nodes before clients/geth nodes Also actually shuts down the L2 clients in the rollup node. * opnode: Properly shut everything down --- l2os/service.go | 33 +++++++++++++++------------------ opnode/l1/request_sema.go | 8 ++++++++ opnode/node/node.go | 28 +++++++++++++++++++++++++--- opnode/rollup/driver/state.go | 21 ++++++++++++--------- opnode/test/setup.go | 6 +++--- 5 files changed, 63 insertions(+), 33 deletions(-) diff --git a/l2os/service.go b/l2os/service.go index 71d413eadf89..d8cf0e58005c 100644 --- a/l2os/service.go +++ b/l2os/service.go @@ -59,27 +59,22 @@ type ServiceConfig struct { } type Service struct { - cfg ServiceConfig - ctx context.Context - cancel func() - + cfg ServiceConfig txMgr txmgr.TxManager - wg sync.WaitGroup + done chan struct{} + wg sync.WaitGroup } func NewService(cfg ServiceConfig) *Service { - ctx, cancel := context.WithCancel(cfg.Context) - txMgr := txmgr.NewSimpleTxManager( cfg.Driver.Name(), cfg.TxManagerConfig, cfg.L1Client, ) return &Service{ - cfg: cfg, - ctx: ctx, - cancel: cancel, - txMgr: txMgr, + cfg: cfg, + txMgr: txMgr, + done: make(chan struct{}), } } @@ -90,12 +85,14 @@ func (s *Service) Start() error { } func (s *Service) Stop() error { - s.cancel() + close(s.done) s.wg.Wait() return nil } func (s *Service) eventLoop() { + ctx, cancel := context.WithCancel(s.cfg.Context) + defer cancel() defer s.wg.Done() name := s.cfg.Driver.Name() @@ -106,7 +103,7 @@ func (s *Service) eventLoop() { // Determine the range of L2 blocks that the submitter has not // processed, and needs to take action on. log.Info(name + " fetching current block range") - start, end, err := s.cfg.Driver.GetBlockRange(s.ctx) + start, end, err := s.cfg.Driver.GetBlockRange(ctx) if err != nil { log.Error(name+" unable to get block range", "err", err) continue @@ -121,7 +118,7 @@ func (s *Service) eventLoop() { // Query for the submitter's current nonce. nonce64, err := s.cfg.L1Client.NonceAt( - s.ctx, s.cfg.Driver.WalletAddr(), nil, + ctx, s.cfg.Driver.WalletAddr(), nil, ) if err != nil { log.Error(name+" unable to get current nonce", @@ -131,7 +128,7 @@ func (s *Service) eventLoop() { nonce := new(big.Int).SetUint64(nonce64) tx, err := s.cfg.Driver.CraftTx( - s.ctx, start, end, nonce, + ctx, start, end, nonce, ) if err != nil { log.Error(name+" unable to craft tx", @@ -151,7 +148,7 @@ func (s *Service) eventLoop() { // Wait until one of our submitted transactions confirms. If no // receipt is received it's likely our gas price was too low. receipt, err := s.txMgr.Send( - s.ctx, updateGasPrice, s.cfg.Driver.SendTransaction, + ctx, updateGasPrice, s.cfg.Driver.SendTransaction, ) if err != nil { log.Error(name+" unable to publish tx", "err", err) @@ -162,8 +159,8 @@ func (s *Service) eventLoop() { log.Info(name+" tx successfully published", "tx_hash", receipt.TxHash) - case err := <-s.ctx.Done(): - log.Error(name+" service shutting down", "err", err) + case <-s.done: + log.Info(name + " service shutting down") return } } diff --git a/opnode/l1/request_sema.go b/opnode/l1/request_sema.go index 960bdc31c54a..af8e81e9a50c 100644 --- a/opnode/l1/request_sema.go +++ b/opnode/l1/request_sema.go @@ -2,6 +2,7 @@ package l1 import ( "context" + "sync" "github.com/ethereum/go-ethereum/rpc" ) @@ -9,6 +10,7 @@ import ( type limitClient struct { c RPCClient sema chan struct{} + wg sync.WaitGroup } // LimitRPC limits concurrent RPC requests (excluding subscriptions) to a given number by wrapping the client with a semaphore. @@ -21,12 +23,16 @@ func LimitRPC(c RPCClient, concurrentRequests int) RPCClient { } func (lc *limitClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + lc.wg.Add(1) + defer lc.wg.Done() lc.sema <- struct{}{} defer func() { <-lc.sema }() return lc.c.BatchCallContext(ctx, b) } func (lc *limitClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + lc.wg.Add(1) + defer lc.wg.Done() lc.sema <- struct{}{} defer func() { <-lc.sema }() return lc.c.CallContext(ctx, result, method, args...) @@ -38,5 +44,7 @@ func (lc *limitClient) EthSubscribe(ctx context.Context, channel interface{}, ar } func (lc *limitClient) Close() { + lc.wg.Wait() + close(lc.sema) lc.c.Close() } diff --git a/opnode/node/node.go b/opnode/node/node.go index be66a7bc8aff..4834d559c290 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -3,6 +3,7 @@ package node import ( "context" "fmt" + "sync" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/backoff" @@ -24,8 +25,10 @@ type OpNode struct { log log.Logger l1Source *l1.Source // Source to fetch data from (also implements the Downloader interface) l2Engines []*driver.Driver // engines to keep synced + l2Nodes []*rpc.Client // L2 Execution Engines to close at shutdown server *rpcServer done chan struct{} + wg sync.WaitGroup } func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) (*rpc.Client, error) { @@ -67,15 +70,26 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* var l2Engines []*driver.Driver genesis := cfg.Rollup.Genesis + var l2Nodes []*rpc.Client + closeNodes := func() { + for _, n := range l2Nodes { + n.Close() + } + } + for i, addr := range cfg.L2EngineAddrs { l2Node, err := dialRPCClientWithBackoff(ctx, log, addr) if err != nil { + closeNodes() return nil, err } + l2Nodes = append(l2Nodes, l2Node) + // TODO: we may need to authenticate the connection with L2 // backend.SetHeader() client, err := l2.NewSource(l2Node, &genesis, log.New("engine_client", i)) if err != nil { + closeNodes() return nil, err } @@ -107,6 +121,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* l2Engines: l2Engines, server: server, done: make(chan struct{}), + l2Nodes: l2Nodes, } return n, nil @@ -170,8 +185,9 @@ func (c *OpNode) Start(ctx context.Context) error { } c.log.Info("Start-up complete!") - + c.wg.Add(1) go func() { + defer c.wg.Done() for { select { case l1Head := <-l1Heads: @@ -183,12 +199,17 @@ func (c *OpNode) Start(ctx context.Context) error { for _, f := range unsub { f() } - // close L1 data source - c.l1Source.Close() // close L2 engines for _, eng := range c.l2Engines { eng.Close() } + // close L2 nodes + for _, n := range c.l2Nodes { + n.Close() + } + // close L1 data source + c.l1Source.Close() + return } } @@ -200,5 +221,6 @@ func (c *OpNode) Stop() { if c.done != nil { close(c.done) } + c.wg.Wait() c.server.Stop() } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index c1cb7a73cf4d..73b5d5f41503 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -4,7 +4,7 @@ import ( "context" "errors" "fmt" - "sync/atomic" + gosync "sync" "time" "github.com/ethereum/go-ethereum" @@ -39,7 +39,7 @@ type state struct { log log.Logger done chan struct{} - closed uint32 // non-zero when closed + wg gosync.WaitGroup } func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, submitter BatchSubmitter, sequencer bool) *state { @@ -96,12 +96,14 @@ func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error s.l1Head = l1Head s.l1Heads = l1Heads + s.wg.Add(1) go s.loop() return nil } func (s *state) Close() error { close(s.done) + s.wg.Wait() return nil } @@ -213,7 +215,7 @@ func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, uint64, e // createNewL2Block builds a L2 block on top of the L2 Head (unsafe) func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { - nextOrigin, maxL2Time, err := s.findNextL1Origin(context.Background()) + nextOrigin, maxL2Time, err := s.findNextL1Origin(ctx) if err != nil { s.log.Error("Error finding next L1 Origin", "err", err) return eth.L1BlockRef{}, err @@ -242,7 +244,7 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { return eth.L1BlockRef{}, nil } // Actually create the new block - newUnsafeL2Head, batch, err := s.output.createNewBlock(context.Background(), s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, nextOrigin) + newUnsafeL2Head, batch, err := s.output.createNewBlock(ctx, s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, nextOrigin) if err != nil { s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", nextOrigin) return eth.L1BlockRef{}, err @@ -250,11 +252,11 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { // State update s.l2Head = newUnsafeL2Head s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin, "txs", len(batch.Transactions), "time", s.l2Head.Time) - //Submit batch + // Submit batch in separate thread + s.wg.Add(1) go func() { + defer s.wg.Done() _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches - // Note: This can cause problems as the log can run after the batch submitter / driver is shut down. - // This is tracked in issue #308 if err != nil { s.log.Error("Error submitting batch", "err", err) } @@ -308,8 +310,10 @@ func (s *state) handleEpoch(ctx context.Context) (bool, error) { // loop is the event loop that responds to L1 changes and internal timers to produce L2 blocks. func (s *state) loop() { + defer s.wg.Done() s.log.Info("State loop started") - ctx := context.Background() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() var l2BlockCreation <-chan time.Time if s.sequencer { l2BlockCreationTicker := time.NewTicker(time.Duration(s.Config.BlockTime) * time.Second) @@ -341,7 +345,6 @@ func (s *state) loop() { for { select { case <-s.done: - atomic.AddUint32(&s.closed, 1) return case <-l2BlockCreation: s.log.Trace("L2 Creation Ticker") diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 42a94d8d5f2d..bb5b37dd6e73 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -117,12 +117,12 @@ func (cfg SystemConfig) start() (*System, error) { didErrAfterStart := false defer func() { if didErrAfterStart { - for _, node := range sys.nodes { - node.Close() - } for _, node := range sys.rollupNodes { node.Stop() } + for _, node := range sys.nodes { + node.Close() + } } }() From 08741745a2d78e75ea104d8f4e8919f041d6b510 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Fri, 8 Apr 2022 20:52:54 -0400 Subject: [PATCH 471/585] style: clean up and comments for state.go (#356) --- opnode/rollup/driver/state.go | 205 +++++++++++++++++++--------------- opnode/rollup/driver/step.go | 42 +++++-- 2 files changed, 147 insertions(+), 100 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 73b5d5f41503..474a278a90ee 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -117,11 +117,16 @@ func (s *state) l1WindowBufEnd() eth.BlockID { } func (s *state) handleNewL1Block(ctx context.Context, newL1Head eth.L1BlockRef) error { + // We don't need to do anything if the head hasn't changed. if s.l1Head.Hash == newL1Head.Hash { - log.Trace("Received L1 head signal that is the same as the current head", "l1Head", newL1Head) + s.log.Trace("Received L1 head signal that is the same as the current head", "l1Head", newL1Head) return nil } + // We got a new L1 block whose parent hash is the same as the current L1 head. Means we're + // dealing with a linear extension (new block is the immediate child of the old one). We + // handle this by simply adding the new block to the window of blocks that we're considering + // when extending the L2 chain. if s.l1Head.Hash == newL1Head.ParentHash { s.log.Trace("Linear extension", "l1Head", newL1Head) s.l1Head = newL1Head @@ -130,7 +135,8 @@ func (s *state) handleNewL1Block(ctx context.Context, newL1Head eth.L1BlockRef) } return nil } - // New L1 Head is not the same as the current head or a single step linear extension. + + // New L1 block is not the same as the current head or a single step linear extension. // This could either be a long L1 extension, or a reorg. Both can be handled the same way. s.log.Warn("L1 Head signal indicates an L1 re-org", "old_l1_head", s.l1Head, "new_l1_head_parent", newL1Head.ParentHash, "new_l1_head", newL1Head) unsafeL2Head, safeL2Head, err := sync.FindL2Heads(ctx, s.l2Head, s.Config.SeqWindowSize, s.l1, s.l2, &s.Config.Genesis) @@ -161,98 +167,81 @@ func (s *state) handleNewL1Block(ctx context.Context, newL1Head eth.L1BlockRef) return nil } -// findNextL1Origin determines what the next L1 Origin should be. +// findL1Origin determines what the next L1 Origin should be. // The L1 Origin is either the L2 Head's Origin, or the following L1 block // if the next L2 block's time is greater than or equal to the L2 Head's Origin. -// Also return the max timestamp (incl.) that we can build a L2 block at using the returned origin. -func (s *state) findNextL1Origin(ctx context.Context) (eth.L1BlockRef, uint64, error) { +func (s *state) findL1Origin(ctx context.Context) (eth.L1BlockRef, error) { // If we are at the head block, don't do a lookup. - // Don't do a timestamp check either as we are unable to get the next block even if we wanted to. if s.l2Head.L1Origin.Hash == s.l1Head.Hash { - return s.l1Head, s.l1Head.Time + s.Config.MaxSequencerDrift, nil + return s.l1Head, nil } - // Grab the block ref + // Grab a reference to the current L1 origin block. currentOrigin, err := s.l1.L1BlockRefByHash(ctx, s.l2Head.L1Origin.Hash) if err != nil { - return eth.L1BlockRef{}, 0, err + return eth.L1BlockRef{}, err } + // Attempt to find the next L1 origin block, where the next origin is the immediate child of + // the current origin block. nextOrigin, err := s.l1.L1BlockRefByNumber(ctx, currentOrigin.Number+1) if errors.Is(err, ethereum.NotFound) { - // no new L1 origin found, keep the current one - s.log.Info("No new L1 origin, staying with current one", "l2Head", s.l2Head, "l1Origin", currentOrigin) - return currentOrigin, currentOrigin.Time + s.Config.MaxSequencerDrift, nil - } - - nextL2Time := s.l2Head.Time + s.Config.BlockTime - - // If we can, start building on the next L1 origin - if nextL2Time >= nextOrigin.Time { // TODO: this is where we can add confirmation distance, instead of eagerly building on the very latest L1 block - s.log.Info("Advancing L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) - return nextOrigin, nextOrigin.Time + s.Config.MaxSequencerDrift, nil + return currentOrigin, nil } - // If there is no more slack left (including the sequencer drift), then we will have to start building on the next L1 origin - maxL2Time := currentOrigin.Time + s.Config.MaxSequencerDrift - if nextL2Time >= maxL2Time { // the maxL2Time is an excl. bound on the current epoch. - // If we are not matching the L1 origin (due to a large gap between L1 blocks), then we stay with the current origin. - // This matches the `next_l1_timestamp - l2_block_time` part of the `new_head_l2_timestamp`, the batches will still be valid. - if nextL2Time < nextOrigin.Time { - s.log.Warn("Ran out of slack with current epoch, but the next L1 block is still ahead in time, thus we continue the epoch", - "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) - return currentOrigin, nextOrigin.Time, nil - } - // The L1 chain continues, and eventually the sequencer will be forced onto the chain with deposits from L1 - s.log.Warn("Forced to advance to new L1 Origin", "l2Head", s.l2Head, "previous_l1Origin", s.l2Head.L1Origin, "l1Origin", nextOrigin) - return nextOrigin, nextOrigin.Time + s.Config.MaxSequencerDrift, nil + // If the next L2 block time is greater than the next origin block's time, we can choose to + // start building on top of the next origin. Sequencer implementation has some leeway here and + // could decide to continue to build on top of the previous origin until the Sequencer runs out + // of slack. For simplicity, we implement our Sequencer to always start building on the latest + // L1 block when we can. + // TODO: Can add confirmation depth here if we want. + if s.l2Head.Time+s.Config.BlockTime >= nextOrigin.Time { + return nextOrigin, nil } - // If we have a next - s.log.Info("Next L1 Origin is the same as the previous", "l2Head", s.l2Head, "l1Origin", currentOrigin) - return currentOrigin, currentOrigin.Time + s.Config.MaxSequencerDrift, nil + return currentOrigin, nil } -// createNewL2Block builds a L2 block on top of the L2 Head (unsafe) -func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { - nextOrigin, maxL2Time, err := s.findNextL1Origin(ctx) +// createNewL2Block builds a L2 block on top of the L2 Head (unsafe). Used by Sequencer nodes to +// construct new L2 blocks. Verifier nodes will use handleEpoch instead. +func (s *state) createNewL2Block(ctx context.Context) error { + // Figure out which L1 origin block we're going to be building on top of. + l1Origin, err := s.findL1Origin(ctx) if err != nil { s.log.Error("Error finding next L1 Origin", "err", err) - return eth.L1BlockRef{}, err + return err + } + + // Rollup is configured to not start producing blocks until a specific L1 block has been + // reached. Don't produce any blocks until we're at that genesis block. + if l1Origin.Number <= s.Config.Genesis.L1.Number { + s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis") + return nil } + + // Should never happen. Sequencer will halt if we get into this situation somehow. nextL2Time := s.l2Head.Time + s.Config.BlockTime - // If we are behind the L1 origin that we should be using then we broke the invariant - if nextL2Time < nextOrigin.Time { + if nextL2Time < l1Origin.Time { s.log.Error("Cannot build L2 block for time before L1 origin", - "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) - return eth.L1BlockRef{}, fmt.Errorf("cannot build L2 block on top %s for time %d before L1 origin %s at time %d", - s.l2Head, nextL2Time, nextOrigin, nextOrigin.Time) + "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", l1Origin, "l1OriginTime", l1Origin.Time) + return fmt.Errorf("cannot build L2 block on top %s for time %d before L1 origin %s at time %d", + s.l2Head, nextL2Time, l1Origin, l1Origin.Time) } - // If the L1 origin changed this block, then we are in the first block of the epoch - isFirstEpochBlock := s.l2Head.L1Origin.Number != nextOrigin.Number - - // We create at least 1 block per epoch. After that we have to enforce the max timestamp. - if !isFirstEpochBlock && nextL2Time >= maxL2Time { - s.log.Warn("Skipping block production because we have no slack left to sequence more blocks on the L1 origin", - "l2Head", s.l2Head, "nextL2Time", nextL2Time, "l1Origin", nextOrigin, "l1OriginTime", nextOrigin.Time) - return eth.L1BlockRef{}, nil - } - // Don't produce blocks until past the rollup-genesis block of the L1 chain - if nextOrigin.Number <= s.Config.Genesis.L1.Number { - s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis") - return eth.L1BlockRef{}, nil - } - // Actually create the new block - newUnsafeL2Head, batch, err := s.output.createNewBlock(ctx, s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, nextOrigin) + // Actually create the new block. + newUnsafeL2Head, batch, err := s.output.createNewBlock(ctx, s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, l1Origin) if err != nil { - s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", nextOrigin) - return eth.L1BlockRef{}, err + s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", l1Origin) + return err } - // State update + + // Update our L2 head block based on the new unsafe block we just generated. s.l2Head = newUnsafeL2Head s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin, "txs", len(batch.Transactions), "time", s.l2Head.Time) - // Submit batch in separate thread + + // Submit batch to L1. Right now this is part of the Sequencer loop inside of the rollup node + // but it's much cleaner to have it in a separate service. Will be removed from this loop + // before Bedrock goes into production. s.wg.Add(1) go func() { defer s.wg.Done() @@ -261,7 +250,8 @@ func (s *state) createNewL2Block(ctx context.Context) (eth.L1BlockRef, error) { s.log.Error("Error submitting batch", "err", err) } }() - return nextOrigin, nil + + return nil } // handleEpoch attempts to insert a full L2 epoch on top of the L2 Safe Head. @@ -312,53 +302,71 @@ func (s *state) handleEpoch(ctx context.Context) (bool, error) { func (s *state) loop() { defer s.wg.Done() s.log.Info("State loop started") + ctx, cancel := context.WithCancel(context.Background()) defer cancel() - var l2BlockCreation <-chan time.Time + + // Start a ticker to produce L2 blocks at a constant rate. Ticker will only run if we're + // running in Sequencer mode. + var l2BlockCreationTickerCh <-chan time.Time if s.sequencer { l2BlockCreationTicker := time.NewTicker(time.Duration(s.Config.BlockTime) * time.Second) defer l2BlockCreationTicker.Stop() - l2BlockCreation = l2BlockCreationTicker.C + l2BlockCreationTickerCh = l2BlockCreationTicker.C } - stepRequest := make(chan struct{}, 1) - l2BlockCreationReq := make(chan struct{}, 1) + // stepReqCh is used to request that the driver attempts to step forward by one L1 block. + stepReqCh := make(chan struct{}, 1) + + // l2BlockCreationReqCh is used to request that the driver create a new L2 block. Only used if + // we're running in Sequencer mode, because otherwise we'll be deriving our blocks via the + // stepping process. + l2BlockCreationReqCh := make(chan struct{}, 1) - createBlock := func() { + // reqL2BlockCreation requests that a block be created. Won't deadlock if the channel is full. + reqL2BlockCreation := func() { select { - case l2BlockCreationReq <- struct{}{}: + case l2BlockCreationReqCh <- struct{}{}: // Don't deadlock if the channel is already full default: } } - requestStep := func() { + // reqStep requests that a driver stpe be taken. Won't deadlock if the channel is full. + // TODO: Rename step request + reqStep := func() { select { - case stepRequest <- struct{}{}: + case stepReqCh <- struct{}{}: // Don't deadlock if the channel is already full default: } } - requestStep() + // We call reqStep right away to finish syncing to the tip of the chain if we're behind. + // reqStep will also be triggered when the L1 head moves forward or if there was a reorg on the + // L1 chain that we need to handle. + reqStep() for { select { - case <-s.done: - return - case <-l2BlockCreation: + case <-l2BlockCreationTickerCh: s.log.Trace("L2 Creation Ticker") - createBlock() - case <-l2BlockCreationReq: + reqL2BlockCreation() + + case <-l2BlockCreationReqCh: ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - nextOrigin, err := s.createNewL2Block(ctx) + err := s.createNewL2Block(ctx) cancel() if err != nil { s.log.Error("Error creating new L2 block", "err", err) } - if nextOrigin.Time > s.l2Head.Time+s.Config.BlockTime { + + // We need to catch up to the next origin as quickly as possible. We can do this by + // requesting a new block ASAP instead of waiting for the next tick. + // TODO: If we want to consider confirmations, need to consider here too. + if s.l1Head.Number > s.l2Head.L1Origin.Number { s.log.Trace("Asking for a second L2 block asap", "l2Head", s.l2Head) - createBlock() + reqL2BlockCreation() } case newL1Head := <-s.l1Heads: @@ -368,31 +376,48 @@ func (s *state) loop() { if err != nil { s.log.Error("Error in handling new L1 Head", "err", err) } - // Run step if we are able to + + // The block number of the L1 origin for the L2 safe head is at least SeqWindowSize + // behind the L1 head. We can therefore attempt to shift the safe head forward by at + // least one L1 block. If the node is holding on to unsafe blocks, this may trigger a + // reorg on L2 in the case that safe (published) data conflicts with local unsafe + // block data. if s.l1Head.Number-s.l2SafeHead.L1Origin.Number >= s.Config.SeqWindowSize { s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2SafeHead.L1Origin) - requestStep() + reqStep() } - case <-stepRequest: + + case <-stepReqCh: ctx, cancel := context.WithTimeout(ctx, 10*time.Second) reorg, err := s.handleEpoch(ctx) cancel() if err != nil { s.log.Error("Error in handling epoch", "err", err) } + if reorg { s.log.Warn("Got reorg") + + // If we're in sequencer mode and experiencing a reorg, we should request a new + // block ASAP. Not strictly necessary but means we'll recover from the reorg much + // faster than if we waited for the next tick. if s.sequencer { - createBlock() + reqL2BlockCreation() } } - // Immediately run next step if we have enough blocks. + // The block number of the L1 origin for the L2 safe head is at least SeqWindowSize + // behind the L1 head. We can therefore attempt to shift the safe head forward by at + // least one L1 block. If the node is holding on to unsafe blocks, this may trigger a + // reorg on L2 in the case that safe (published) data conflicts with local unsafe + // block data. if s.l1Head.Number-s.l2SafeHead.L1Origin.Number >= s.Config.SeqWindowSize { s.log.Trace("Requesting next step", "l1Head", s.l1Head, "l2Head", s.l2Head, "l1Origin", s.l2SafeHead.L1Origin) - requestStep() + reqStep() } + + case <-s.done: + return } } - } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 8388de90856f..44aa3487d7a6 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -57,33 +57,38 @@ func lastDeposit(txns []l2.Data) (int, error) { func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) { d.log.Info("creating new block", "l2Head", l2Head) - // If the L1 origin changed this block, then we are in the first block of the epoch - firstEpochBlock := l2Head.L1Origin.Number != l1Origin.Number - fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() var l1Info derive.L1Info var receipts types.Receipts var err error - // Include deposits if this is the first block of an epoch - if firstEpochBlock { + + // If the L1 origin changed this block, then we are in the first block of the epoch. In this + // case we need to fetch all transaction receipts from the L1 origin block so we can scan for + // user deposits. + if l2Head.L1Origin.Number != l1Origin.Number { l1Info, _, receipts, err = d.dl.Fetch(fetchCtx, l1Origin.Hash) } else { l1Info, err = d.dl.InfoByHash(fetchCtx, l1Origin.Hash) - // don't fetch receipts if we do not process deposits } if err != nil { return l2Head, nil, fmt.Errorf("failed to fetch L1 block info of %s: %v", l1Origin, err) } + // Start building the list of transactions to include in the new block. + var txns []l2.Data + + // First transaction in every block is always the L1 info transaction. seqNumber := l2Head.Number + 1 - l2SafeHead.Number l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info) if err != nil { return l2Head, nil, err } - var txns []l2.Data txns = append(txns, l1InfoTx) + + // Next we append user deposits. If we're not the first block in an epoch, then receipts will + // be empty and no deposits will be derived. deposits, err := derive.DeriveDeposits(receipts) d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Head, "l1Origin", l1Origin) if err != nil { @@ -91,24 +96,41 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, } txns = append(txns, deposits...) + // If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce + // empty blocks (other than the L1 info deposit and any user deposits). We handle this by + // setting NoTxPool to true, which will cause the Sequencer to not include any transactions + // from the transaction pool. + nextL2Time := l2Head.Time + d.Config.BlockTime + shouldProduceEmptyBlock := nextL2Time >= l1Origin.Time+d.Config.MaxSequencerDrift + + // Put together our payload attributes. attrs := &l2.PayloadAttributes{ - Timestamp: hexutil.Uint64(l2Head.Time + d.Config.BlockTime), + Timestamp: hexutil.Uint64(nextL2Time), PrevRandao: l2.Bytes32(l1Info.MixDigest()), SuggestedFeeRecipient: d.Config.FeeRecipientAddress, Transactions: txns, - NoTxPool: false, + NoTxPool: shouldProduceEmptyBlock, } + + // And construct our fork choice state. This is our current fork choice state and will be + // updated as a result of executing the block based on the attributes described above. fc := l2.ForkchoiceState{ HeadBlockHash: l2Head.Hash, SafeBlockHash: l2SafeHead.Hash, FinalizedBlockHash: l2Finalized.Hash, } + // Actually execute the block and add it to the head of the chain. payload, lastDeposit, err := d.insertHeadBlock(ctx, fc, attrs, false) if err != nil { return l2Head, nil, fmt.Errorf("failed to extend L2 chain: %v", err) } + // Generate an L2 block ref from the payload. + ref, err := l2.PayloadToBlockRef(payload, &d.Config.Genesis) + + // Derive relevant batch data so we can submit this block to L1. + // TODO: Can this be removed when batch submission is separated? batch := &derive.BatchData{ BatchV1: derive.BatchV1{ Epoch: rollup.Epoch(l1Info.NumberU64()), @@ -116,7 +138,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, Transactions: payload.Transactions[lastDeposit+1:], }, } - ref, err := l2.PayloadToBlockRef(payload, &d.Config.Genesis) + return ref, batch, err } From da8b3e2210cf5c8dbabdd46bb7a2ddc29b950aed Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 8 Apr 2022 21:28:01 -0700 Subject: [PATCH 472/585] opnode: Parameterize deposit contract address (#361) The contract can be deployed to any address. It is set in the rollup config file. --- opnode/rollup/derive/invert_test.go | 4 +++- opnode/rollup/derive/payload_attributes.go | 17 ++++++++--------- opnode/rollup/derive/payload_attributes_test.go | 4 ++-- opnode/rollup/driver/step.go | 8 ++++---- opnode/rollup/types.go | 5 +++++ opnode/test/system_test.go | 6 +++++- ops/rollup.json | 4 +++- 7 files changed, 30 insertions(+), 18 deletions(-) diff --git a/opnode/rollup/derive/invert_test.go b/opnode/rollup/derive/invert_test.go index 8ee321f6e649..8da007d01507 100644 --- a/opnode/rollup/derive/invert_test.go +++ b/opnode/rollup/derive/invert_test.go @@ -103,6 +103,8 @@ type infoTest struct { mkInfo func(rng *rand.Rand) *l1MockInfo } +var MockDepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") + func TestParseL1InfoDepositTxData(t *testing.T) { // Go 1.18 will have native fuzzing for us to use, until then, we cover just the below cases cases := []infoTest{ @@ -123,7 +125,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { for i, testCase := range cases { t.Run(testCase.name, func(t *testing.T) { info := testCase.mkInfo(rand.New(rand.NewSource(int64(1234 + i)))) - depTx := L1InfoDeposit(123, info) + depTx := L1InfoDeposit(123, info, MockDepositContractAddr) nr, time, baseFee, h, err := L1InfoDepositTxData(depTx.Data) assert.NoError(t, err, "expected valid deposit info") assert.Equal(t, nr, info.num) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 793540c7f319..2b3b5405524b 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -19,7 +19,6 @@ import ( var ( DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint256,bool,bytes)" DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) - DepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") L1InfoFuncSignature = "setL1BlockValues(uint256,uint256,uint256,bytes32)" L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] L1InfoPredeployAddr = common.HexToAddress("0x4200000000000000000000000000000000000015") @@ -169,7 +168,7 @@ type L1Info interface { // L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block, // and the L2 block-height difference with the start of the epoch. -func L1InfoDeposit(seqNumber uint64, block L1Info) *types.DepositTx { +func L1InfoDeposit(seqNumber uint64, block L1Info, depositContractAddr common.Address) *types.DepositTx { data := make([]byte, 4+8+8+32+32) offset := 0 copy(data[offset:4], L1InfoFuncBytes4) @@ -189,7 +188,7 @@ func L1InfoDeposit(seqNumber uint64, block L1Info) *types.DepositTx { return &types.DepositTx{ SourceHash: source.SourceHash(), - From: DepositContractAddr, + From: depositContractAddr, To: &L1InfoPredeployAddr, Mint: nil, Value: big.NewInt(0), @@ -199,7 +198,7 @@ func L1InfoDeposit(seqNumber uint64, block L1Info) *types.DepositTx { } // UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block -func UserDeposits(receipts []*types.Receipt) ([]*types.DepositTx, error) { +func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]*types.DepositTx, error) { var out []*types.DepositTx for _, rec := range receipts { @@ -207,7 +206,7 @@ func UserDeposits(receipts []*types.Receipt) ([]*types.DepositTx, error) { continue } for _, log := range rec.Logs { - if log.Address == DepositContractAddr { + if log.Address == depositContractAddr { dep, err := UnmarshalLogEvent(log) if err != nil { return nil, fmt.Errorf("malformatted L1 deposit log: %v", err) @@ -330,8 +329,8 @@ func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, nextL } // L1InfoDepositBytes returns a serialized L1-info attributes transaction. -func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info) (hexutil.Bytes, error) { - l1Tx := types.NewTx(L1InfoDeposit(seqNumber, l1Info)) +func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info, depositContractAddress common.Address) (hexutil.Bytes, error) { + l1Tx := types.NewTx(L1InfoDeposit(seqNumber, l1Info, depositContractAddress)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { return nil, fmt.Errorf("failed to encode L1 info tx") @@ -339,8 +338,8 @@ func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info) (hexutil.Bytes, error) return opaqueL1Tx, nil } -func DeriveDeposits(receipts []*types.Receipt) ([]hexutil.Bytes, error) { - userDeposits, err := UserDeposits(receipts) +func DeriveDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]hexutil.Bytes, error) { + userDeposits, err := UserDeposits(receipts, depositContractAddr) if err != nil { return nil, fmt.Errorf("failed to derive user deposits: %v", err) } diff --git a/opnode/rollup/derive/payload_attributes_test.go b/opnode/rollup/derive/payload_attributes_test.go index cdae082dee46..e8d632a7f118 100644 --- a/opnode/rollup/derive/payload_attributes_test.go +++ b/opnode/rollup/derive/payload_attributes_test.go @@ -93,7 +93,7 @@ func GenerateDepositLog(deposit *types.DepositTx) *types.Log { data = append(data, make([]byte, 32-(len(data)%32))...) } - return GenerateLog(DepositContractAddr, topics, data) + return GenerateLog(MockDepositContractAddr, topics, data) } // Generates an EVM log entry with the given topics and data. @@ -204,7 +204,7 @@ func TestDeriveUserDeposits(t *testing.T) { TransactionIndex: uint(txIndex), }) } - got, err := UserDeposits(receipts) + got, err := UserDeposits(receipts, MockDepositContractAddr) assert.NoError(t, err) assert.Equal(t, len(got), len(expectedDeposits)) for d, depTx := range got { diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 44aa3487d7a6..f2c3e6b8c0bf 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -81,7 +81,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, // First transaction in every block is always the L1 info transaction. seqNumber := l2Head.Number + 1 - l2SafeHead.Number - l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info) + l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info, d.Config.DepositContractAddress) if err != nil { return l2Head, nil, err } @@ -89,7 +89,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, // Next we append user deposits. If we're not the first block in an epoch, then receipts will // be empty and no deposits will be derived. - deposits, err := derive.DeriveDeposits(receipts) + deposits, err := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress) d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Head, "l1Origin", l1Origin) if err != nil { return l2Head, nil, fmt.Errorf("failed to derive deposits: %v", err) @@ -175,7 +175,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to get L1 timestamp of next L1 block: %v", err) } - deposits, err := derive.DeriveDeposits(receipts) + deposits, err := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to derive deposits: %w", err) } @@ -210,7 +210,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S var reorg bool for i, batch := range batches { var txns []l2.Data - l1InfoTx, err := derive.L1InfoDepositBytes(uint64(i), l1Info) + l1InfoTx, err := derive.L1InfoDepositBytes(uint64(i), l1Info, d.Config.DepositContractAddress) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to create l1InfoTx: %w", err) } diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go index 6551e58716b5..36dcf6b42410 100644 --- a/opnode/rollup/types.go +++ b/opnode/rollup/types.go @@ -44,6 +44,8 @@ type Config struct { BatchInboxAddress common.Address `json:"batch_inbox_address"` // Acceptable batch-sender address BatchSenderAddress common.Address `json:"batch_sender_address"` + // L1 Deposit Contract Address + DepositContractAddress common.Address `json:"deposit_contract_address"` } // Check verifies that the given configuration makes sense @@ -63,6 +65,9 @@ func (cfg *Config) Check() error { if cfg.Genesis.L2.Hash == cfg.Genesis.L1.Hash { return errors.New("achievement get! rollup inception: L1 and L2 genesis cannot be the same") } + if cfg.DepositContractAddress == (common.Address{}) { + return errors.New("did not provide deposit contract address ") + } return nil } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 791df57f7b9a..13e7ea30c8ec 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -31,6 +31,9 @@ import ( "github.com/stretchr/testify/require" ) +// Temporary until the contract is deployed properly instead of as a pre-deploy to a specific address +var MockDepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") + const ( cliqueSignerHDPath = "m/44'/60'/0'/0/0" transactorHDPath = "m/44'/60'/0'/0/1" @@ -49,7 +52,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { }, BatchSubmitterHDPath: bssHDPath, CliqueSignerDerivationPath: cliqueSignerHDPath, - DepositContractAddress: derive.DepositContractAddr, + DepositContractAddress: MockDepositContractAddr, L1InfoPredeployAddress: derive.L1InfoPredeployAddr, L1WsAddr: "127.0.0.1", L1WsPort: 9090, @@ -86,6 +89,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { FeeRecipientAddress: common.Address{0xff, 0x01}, BatchInboxAddress: common.Address{0xff, 0x02}, // Batch Sender address is filled out in system start + DepositContractAddress: MockDepositContractAddr, }, } } diff --git a/ops/rollup.json b/ops/rollup.json index 805c578cfb99..7285c0391d78 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -23,5 +23,7 @@ "batch_inbox_address": "0xff00000000000000000000000000000000000002", - "batch_sender_address": "0xde3829a23df1479438622a08a116e8eb3f620bb5" + "batch_sender_address": "0xde3829a23df1479438622a08a116e8eb3f620bb5", + + "deposit_contract_address": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001" } From 215c721f43d43b9a69505abc8432e0c54afa914b Mon Sep 17 00:00:00 2001 From: Murphy Law Date: Mon, 11 Apr 2022 12:09:42 -0400 Subject: [PATCH 473/585] opnode/test: Add reverted deposit with mint test --- opnode/test/system_test.go | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 13e7ea30c8ec..a1583741115d 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -343,7 +343,67 @@ func TestSystemE2E(t *testing.T) { seqBlock, err := l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber) require.Nil(t, err) require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") +} + +func TestMintOnRevertedDeposit(t *testing.T) { + log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs + + cfg := defaultSystemConfig(t) + + sys, err := cfg.start() + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + l2Verif := sys.Clients["verifier"] + // Find deposit contract + depositContract, err := deposit.NewDeposit(cfg.DepositContractAddress, l1Client) + require.Nil(t, err) + l1Node := sys.nodes["l1"] + + // create signer + ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainID) + 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) + + toAddr := common.Address{0xff, 0xff} + mintAmount := big.NewInt(9_000_000) + opts.Value = mintAmount + value := new(big.Int).Mul(common.Big2, startBalance) // triger a revert by transferring more than we have available + tx, err := depositContract.DepositTransaction(opts, toAddr, value, big.NewInt(1_000_000), false, nil) + require.Nil(t, err, "with deposit tx") + + receipt, err := waitForTransaction(tx.Hash(), l1Client, 6*time.Second) + require.Nil(t, err, "Waiting for deposit tx on L1") + + reconstructedDep, err := derive.UnmarshalLogEvent(receipt.Logs[0]) + require.NoError(t, err, "Could not reconstruct L2 Deposit") + tx = types.NewTx(reconstructedDep) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Second) + require.NoError(t, err) + require.Equal(t, receipt.Status, 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") } func TestMissingBatchE2E(t *testing.T) { From eac35bbe1ca2b42cab0008e9a8c853f6adaa3188 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Mon, 11 Apr 2022 11:53:24 -0700 Subject: [PATCH 474/585] fix(ci): use Foundry GHA (#367) Nightly Foundry releases are kept around for 3 days. This means we cannot be pinning the download link on CI to a specific commit. Instead, we use the Foundry Toolchain GHA which always uses the latest nightly version. --- .github/workflows/devnet-ci.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/devnet-ci.yml b/.github/workflows/devnet-ci.yml index 22a119dfad42..b10a9afda6c4 100644 --- a/.github/workflows/devnet-ci.yml +++ b/.github/workflows/devnet-ci.yml @@ -23,12 +23,10 @@ jobs: node-version: '14' cache: 'yarn' - - run: | - curl -L -o /tmp/foundry.tgz https://github.com/gakonst/foundry/releases/download/nightly-9c2469488c6872e5d17198555f7d8e1a80173151/foundry_nightly_linux_amd64.tar.gz - tar -xzvf /tmp/foundry.tgz - mv forge /usr/local/bin - mv cast /usr/local/bin - name: Install forge + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly - run: cd packages/contracts && yarn install && yarn build - run: cd packages/integration-tests && yarn install && yarn build:contracts @@ -36,4 +34,4 @@ jobs: - run: make devnet-up name: Bring up the stack - - run: sleep 10 && docker ps && make integration-tests \ No newline at end of file + - run: sleep 10 && docker ps && make integration-tests From cddfc7cdbf9c51ad3d1214fa4dbf9d25b7710edc Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 11 Apr 2022 21:19:38 +0200 Subject: [PATCH 475/585] opnode/test: check nonce increment in deposit fail --- opnode/test/system_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index a1583741115d..65db1a61c72b 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -373,10 +373,15 @@ func TestMintOnRevertedDeposit(t *testing.T) { 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 - value := new(big.Int).Mul(common.Big2, startBalance) // triger a revert by transferring more than we have available + value := new(big.Int).Mul(common.Big2, startBalance) // trigger a revert by transferring more than we have available tx, err := depositContract.DepositTransaction(opts, toAddr, value, big.NewInt(1_000_000), false, nil) require.Nil(t, err, "with deposit tx") @@ -404,6 +409,12 @@ func TestMintOnRevertedDeposit(t *testing.T) { 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) { From 273c8abddee294dc61bedf6b077c0b21fb9984e3 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 11 Apr 2022 13:20:57 -0600 Subject: [PATCH 476/585] integration-tests: End-to-end withdrawal test (#362) Includes several fixes to make this work: - Modifies the devnet to deploy the L1 contracts rather than include them in genesis. - Changes the deployment of L2OutputOracle to support a custom start timestamp. - Updates UserDeposits to properly filter out non-TransactionDeposited events. - Updates the L2 output submitter to post the current L1 block with each output rather than the L2 checkpoint block - Updates the opnode API to allow all vhosts and CORS domains. --- .github/workflows/devnet-ci.yml | 7 +- .gitignore | 3 +- Makefile | 68 +- go.mod | 2 +- go.sum | 5 - l2os/Makefile | 19 +- l2os/bindings/l2oo/l2_output_oracle.go | 850 ++++++++++++++++++ l2os/bindings/l2oo/mock_l2_output_oracle.go | 471 ---------- l2os/drivers/l2output/driver.go | 15 +- l2os/flags/flags.go | 2 +- opnode/cmd/main.go | 2 +- opnode/node/server.go | 8 +- opnode/rollup/derive/payload_attributes.go | 2 +- opnode/test/system_test.go | 12 +- ops/Dockerfile.l1 | 10 - ops/Dockerfile.l2 | 11 - ops/Dockerfile.l2os | 23 + ops/Dockerfile.opnode | 8 +- ops/devnet-up.sh | 146 +++ ops/docker-compose.yml | 36 +- ops/entrypoint.sh | 6 +- ops/genesis-l1.json | 7 +- ops/genesis-l2.json | 7 + ops/l2os-entrypoint.sh | 14 + ops/opnode-entrypoint.sh | 30 - ops/test-integration.sh | 17 + packages/contracts/.eslintrc.js | 1 + packages/contracts/.gitignore | 1 + .../contracts/contracts/L1/L2OutputOracle.sol | 8 +- .../L1/libraries/Lib_WithdrawalVerifier.sol | 2 +- .../contracts/test/L2OutputOracle.t.sol | 1 + .../contracts/test/WithdrawalsRelay.t.sol | 1 + .../deploy/000-L2OutputOracle.deploy.ts | 35 + .../deploy/001-OptimismPortal.deploy.ts | 20 + packages/contracts/hardhat.config.ts | 16 +- packages/contracts/package.json | 1 + packages/contracts/yarn.lock | 413 ++++++++- .../contracts/MultiDepositor.sol | 6 +- packages/integration-tests/package.json | 3 +- .../test/000_withdrawals.spec.ts | 212 +++++ .../integration-tests/test/deposit.spec.ts | 18 +- packages/integration-tests/test/rpc.spec.ts | 4 +- .../test/shared/constants.ts | 2 +- packages/integration-tests/test/shared/env.ts | 60 +- packages/integration-tests/yarn.lock | 147 ++- 45 files changed, 2093 insertions(+), 639 deletions(-) create mode 100644 l2os/bindings/l2oo/l2_output_oracle.go delete mode 100644 l2os/bindings/l2oo/mock_l2_output_oracle.go create mode 100644 ops/Dockerfile.l2os create mode 100644 ops/devnet-up.sh create mode 100644 ops/l2os-entrypoint.sh create mode 100644 ops/test-integration.sh create mode 100644 packages/contracts/deploy/000-L2OutputOracle.deploy.ts create mode 100644 packages/contracts/deploy/001-OptimismPortal.deploy.ts create mode 100644 packages/integration-tests/test/000_withdrawals.spec.ts diff --git a/.github/workflows/devnet-ci.yml b/.github/workflows/devnet-ci.yml index b10a9afda6c4..686c4fd7faa6 100644 --- a/.github/workflows/devnet-ci.yml +++ b/.github/workflows/devnet-ci.yml @@ -28,10 +28,11 @@ jobs: with: version: nightly - - run: cd packages/contracts && yarn install && yarn build - - run: cd packages/integration-tests && yarn install && yarn build:contracts + - run: make build-ts + name: Build TS - run: make devnet-up name: Bring up the stack - - run: sleep 10 && docker ps && make integration-tests + - run: make test-integration + name: Run integration tests diff --git a/.gitignore b/.gitignore index 6a916fac28bc..49732cb8a1e3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ bin integration-tests/cache/ integration-tests/artifacts/ -**/*.env \ No newline at end of file +**/*.env +.devnet \ No newline at end of file diff --git a/Makefile b/Makefile index a8ec1641fbd5..1edf093b2c9b 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,15 @@ COMPOSEFLAGS=-d ITESTS_L2_HOST=http://localhost:9545 -build: submodules opnode contracts +build: submodules opnode contracts integration-tests .PHONY: build +build-go: submodules opnode l2os +.PHONY: build-go + +build-ts: submodules contracts integration-tests +.PHONY: build-ts + submodules: # CI will checkout submodules on its own (and fails on these commands) if [ -z "$$GITHUB_ENV" ]; then \ @@ -20,46 +26,44 @@ contracts: cd ./packages/contracts && yarn install && yarn build .PHONY: contracts -test: - cd ./opnode && make test - cd ./packages/contracts && yarn test -.PHONY: test +integration-tests: + cd ./packages/integration-tests && yarn install && yarn build:contracts +.PHONY: integration-tests clean: rm -rf ./bin .PHONY: clean -devnet-clean: devnet-down - cd ./ops && docker-compose rm - docker volume rm ops_l1_data - docker volume rm ops_l2_data -.PHONY: devnet-clean - devnet-up: - @test -f ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json - @test -f ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json - @(cd ./ops && \ - DEPOSIT_FEED_BYTECODE="0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" \ - L1_BLOCK_INFO_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json | jq .deployedBytecode) \ - WITHDRAWER_BYTECODE=$(shell cat ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json | jq .deployedBytecode) \ - GENESIS_TIMESTAMP=$(shell date +%s) \ - BUILDKIT_PROGRESS=plain DOCKER_BUILDKIT=1 docker-compose up --build $(COMPOSEFLAGS)) + @bash ./ops/devnet-up.sh .PHONY: devnet-up devnet-down: - @(cd ./ops && docker-compose down -v) + @(cd ./ops && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose stop) .PHONY: devnet-stop -integration-tests: - curl \ - --fail \ - --retry 10 \ - --retry-delay 2 \ - --retry-connrefused \ - -X POST \ - -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ - $(ITESTS_L2_HOST) +devnet-clean: + rm -rf ./packages/contracts/deployments/devnetL1 + rm -rf ./.devnet + cd ./ops && docker-compose down + docker volume rm ops_l1_data + docker volume rm ops_l2_data +.PHONY: devnet-clean + +test-unit: + cd ./opnode && make test + cd ./packages/contracts && yarn test +.PHONY: test-unit + +test-integration: + bash ./ops/test-integration.sh \ + ./packages/contracts/deployments/devnetL1 +.PHONY: test-integration + +devnet-genesis: + bash ./ops/devnet-genesis.sh +.PHONY: devnet-genesis - cd packages/integration-tests && yarn test -.PHONY: integration-tests \ No newline at end of file +l2os: + go build -o ./bin/l2os ./l2os/cmd/l2os +.PHONY: l2os \ No newline at end of file diff --git a/go.mod b/go.mod index 7b9090e86f69..d26de76b3072 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum-optimism/optimistic-specs -go 1.17 +go 1.18 require ( github.com/ethereum/go-ethereum v1.10.16 diff --git a/go.sum b/go.sum index 37f415f0bddb..dcdda4cae799 100644 --- a/go.sum +++ b/go.sum @@ -87,7 +87,6 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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= @@ -468,7 +467,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -527,7 +525,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v 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.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -581,11 +578,9 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= diff --git a/l2os/Makefile b/l2os/Makefile index 5642d8c1eb28..52f3d11c8b11 100644 --- a/l2os/Makefile +++ b/l2os/Makefile @@ -7,7 +7,7 @@ LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) LDFLAGSSTRING +=-X main.Version=$(VERSION) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" -MOCK_L2_OUTPUT_ORACLE_SOL := ../packages/contracts/contracts/L1/MockL2OutputOracle.sol +L2_OUTPUT_ORACLE_SOL := ../packages/contracts/contracts/L1/L2OutputOracle.sol l2os: env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/l2os @@ -21,20 +21,21 @@ test: lint: golangci-lint run -E asciicheck,goimports,misspell ./... -bindings: bindings-mock-l2-output-oracle +bindings: bindings-l2-output-oracle -bindings-mock-l2-output-oracle: +bindings-l2-output-oracle: $(eval temp := $(shell mktemp -d)) solc \ - --abi $(MOCK_L2_OUTPUT_ORACLE_SOL) \ - --bin $(MOCK_L2_OUTPUT_ORACLE_SOL) \ + --abi $(L2_OUTPUT_ORACLE_SOL) \ + --bin $(L2_OUTPUT_ORACLE_SOL) \ + --allow-paths ../ \ -o $(temp) abigen \ - --abi $(temp)/MockL2OutputOracle.abi \ - --bin $(temp)/MockL2OutputOracle.bin \ + --abi $(temp)/L2OutputOracle.abi \ + --bin $(temp)/L2OutputOracle.bin \ --pkg l2oo \ - --type MockL2OutputOracle \ - --out ./bindings/l2oo/mock_l2_output_oracle.go + --type L2OutputOracle \ + --out ./bindings/l2oo/l2_output_oracle.go .PHONY: \ diff --git a/l2os/bindings/l2oo/l2_output_oracle.go b/l2os/bindings/l2oo/l2_output_oracle.go new file mode 100644 index 000000000000..f3342fb55586 --- /dev/null +++ b/l2os/bindings/l2oo/l2_output_oracle.go @@ -0,0 +1,850 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package l2oo + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. +var L2OutputOracleMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620012db380380620012db83398181016040528101906200003891906200025f565b620000586200004c620000b360201b60201c565b620000bb60201b60201c565b84608081815250508360a081815250508260026000428152602001908152602001600020819055508160c08181525050426001819055504260e08181525050620000a881620000bb60201b60201c565b5050505050620002e7565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b620001998162000184565b8114620001a557600080fd5b50565b600081519050620001b9816200018e565b92915050565b6000819050919050565b620001d481620001bf565b8114620001e057600080fd5b50565b600081519050620001f481620001c9565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022782620001fa565b9050919050565b62000239816200021a565b81146200024557600080fd5b50565b60008151905062000259816200022e565b92915050565b600080600080600060a086880312156200027e576200027d6200017f565b5b60006200028e88828901620001a8565b9550506020620002a188828901620001a8565b9450506040620002b488828901620001e3565b9350506060620002c788828901620001a8565b9250506080620002da8882890162000248565b9150509295509295909350565b60805160a05160c05160e051610f9762000344600039600081816102b30152818161033701526106af01526000818161036b01526106d3015260008181610316015261066e01526000818161058a01526106f70152610f976000f3fe6080604052600436106100a75760003560e01c806393991af31161006457806393991af31461019d578063a25ae557146101c8578063c5095d6814610205578063c90ec2da14610230578063e1a41bcf1461025b578063f2fde38b14610286576100a7565b806302e51345146100ac5780630c1952d3146100e95780632518810414610114578063357e951f14610130578063715018a61461015b5780638da5cb5b14610172575b600080fd5b3480156100b857600080fd5b506100d360048036038101906100ce9190610917565b6102af565b6040516100e09190610953565b60405180910390f35b3480156100f557600080fd5b506100fe610393565b60405161010b9190610953565b60405180910390f35b61012e600480360381019061012991906109a4565b610399565b005b34801561013c57600080fd5b50610145610586565b6040516101529190610953565b60405180910390f35b34801561016757600080fd5b506101706105bb565b005b34801561017e57600080fd5b50610187610643565b6040516101949190610a4c565b60405180910390f35b3480156101a957600080fd5b506101b261066c565b6040516101bf9190610953565b60405180910390f35b3480156101d457600080fd5b506101ef60048036038101906101ea9190610917565b610690565b6040516101fc9190610a76565b60405180910390f35b34801561021157600080fd5b5061021a6106ad565b6040516102279190610953565b60405180910390f35b34801561023c57600080fd5b506102456106d1565b6040516102529190610953565b60405180910390f35b34801561026757600080fd5b506102706106f5565b60405161027d9190610953565b60405180910390f35b34801561029257600080fd5b506102ad60048036038101906102a89190610abd565b610719565b005b60007f0000000000000000000000000000000000000000000000000000000000000000821015610314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030b90610b6d565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161036657610365610b8d565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6103a1610810565b73ffffffffffffffffffffffffffffffffffffffff166103bf610643565b73ffffffffffffffffffffffffffffffffffffffff1614610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040c90610c08565b60405180910390fd5b428310610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e90610c9a565b60405180910390fd5b61045f610586565b83146104a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049790610d2c565b60405180910390fd5b6000801b84036104e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104dc90610d98565b60405180910390fd5b6000801b82146105335781814014610532576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052990610e2a565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546105b69190610e79565b905090565b6105c3610810565b73ffffffffffffffffffffffffffffffffffffffff166105e1610643565b73ffffffffffffffffffffffffffffffffffffffff1614610637576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062e90610c08565b60405180910390fd5b6106416000610818565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610721610810565b73ffffffffffffffffffffffffffffffffffffffff1661073f610643565b73ffffffffffffffffffffffffffffffffffffffff1614610795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078c90610c08565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610804576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fb90610f41565b60405180910390fd5b61080d81610818565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6108f4816108e1565b81146108ff57600080fd5b50565b600081359050610911816108eb565b92915050565b60006020828403121561092d5761092c6108dc565b5b600061093b84828501610902565b91505092915050565b61094d816108e1565b82525050565b60006020820190506109686000830184610944565b92915050565b6000819050919050565b6109818161096e565b811461098c57600080fd5b50565b60008135905061099e81610978565b92915050565b600080600080608085870312156109be576109bd6108dc565b5b60006109cc8782880161098f565b94505060206109dd87828801610902565b93505060406109ee8782880161098f565b92505060606109ff87828801610902565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a3682610a0b565b9050919050565b610a4681610a2b565b82525050565b6000602082019050610a616000830184610a3d565b92915050565b610a708161096e565b82525050565b6000602082019050610a8b6000830184610a67565b92915050565b610a9a81610a2b565b8114610aa557600080fd5b50565b600081359050610ab781610a91565b92915050565b600060208284031215610ad357610ad26108dc565b5b6000610ae184828501610aa8565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610b57602983610aea565b9150610b6282610afb565b604082019050919050565b60006020820190508181036000830152610b8681610b4a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610bf2602083610aea565b9150610bfd82610bbc565b602082019050919050565b60006020820190508181036000830152610c2181610be5565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610c84602183610aea565b9150610c8f82610c28565b604082019050919050565b60006020820190508181036000830152610cb381610c77565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610d16602e83610aea565b9150610d2182610cba565b604082019050919050565b60006020820190508181036000830152610d4581610d09565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610d82601d83610aea565b9150610d8d82610d4c565b602082019050919050565b60006020820190508181036000830152610db181610d75565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610e14603983610aea565b9150610e1f82610db8565b604082019050919050565b60006020820190508181036000830152610e4381610e07565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e84826108e1565b9150610e8f836108e1565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ec457610ec3610e4a565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610f2b602683610aea565b9150610f3682610ecf565b604082019050919050565b60006020820190508181036000830152610f5a81610f1e565b905091905056fea264697066735822122084b8f35610306af12a2673f370ec439475d79fd28e3748169a331e30b3d14e6b64736f6c634300080d0033", +} + +// L2OutputOracleABI is the input ABI used to generate the binding from. +// Deprecated: Use L2OutputOracleMetaData.ABI instead. +var L2OutputOracleABI = L2OutputOracleMetaData.ABI + +// L2OutputOracleBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use L2OutputOracleMetaData.Bin instead. +var L2OutputOracleBin = L2OutputOracleMetaData.Bin + +// DeployL2OutputOracle deploys a new Ethereum contract, binding an instance of L2OutputOracle to it. +func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionInterval *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int, sequencer common.Address) (common.Address, *types.Transaction, *L2OutputOracle, error) { + parsed, err := L2OutputOracleMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L2OutputOracleBin), backend, _submissionInterval, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks, sequencer) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &L2OutputOracle{L2OutputOracleCaller: L2OutputOracleCaller{contract: contract}, L2OutputOracleTransactor: L2OutputOracleTransactor{contract: contract}, L2OutputOracleFilterer: L2OutputOracleFilterer{contract: contract}}, nil +} + +// L2OutputOracle is an auto generated Go binding around an Ethereum contract. +type L2OutputOracle struct { + L2OutputOracleCaller // Read-only binding to the contract + L2OutputOracleTransactor // Write-only binding to the contract + L2OutputOracleFilterer // Log filterer for contract events +} + +// L2OutputOracleCaller is an auto generated read-only Go binding around an Ethereum contract. +type L2OutputOracleCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L2OutputOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. +type L2OutputOracleTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L2OutputOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type L2OutputOracleFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L2OutputOracleSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type L2OutputOracleSession struct { + Contract *L2OutputOracle // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// L2OutputOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type L2OutputOracleCallerSession struct { + Contract *L2OutputOracleCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// L2OutputOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type L2OutputOracleTransactorSession struct { + Contract *L2OutputOracleTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// L2OutputOracleRaw is an auto generated low-level Go binding around an Ethereum contract. +type L2OutputOracleRaw struct { + Contract *L2OutputOracle // Generic contract binding to access the raw methods on +} + +// L2OutputOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type L2OutputOracleCallerRaw struct { + Contract *L2OutputOracleCaller // Generic read-only contract binding to access the raw methods on +} + +// L2OutputOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type L2OutputOracleTransactorRaw struct { + Contract *L2OutputOracleTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewL2OutputOracle creates a new instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracle(address common.Address, backend bind.ContractBackend) (*L2OutputOracle, error) { + contract, err := bindL2OutputOracle(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &L2OutputOracle{L2OutputOracleCaller: L2OutputOracleCaller{contract: contract}, L2OutputOracleTransactor: L2OutputOracleTransactor{contract: contract}, L2OutputOracleFilterer: L2OutputOracleFilterer{contract: contract}}, nil +} + +// NewL2OutputOracleCaller creates a new read-only instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracleCaller(address common.Address, caller bind.ContractCaller) (*L2OutputOracleCaller, error) { + contract, err := bindL2OutputOracle(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &L2OutputOracleCaller{contract: contract}, nil +} + +// NewL2OutputOracleTransactor creates a new write-only instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*L2OutputOracleTransactor, error) { + contract, err := bindL2OutputOracle(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &L2OutputOracleTransactor{contract: contract}, nil +} + +// NewL2OutputOracleFilterer creates a new log filterer instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*L2OutputOracleFilterer, error) { + contract, err := bindL2OutputOracle(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &L2OutputOracleFilterer{contract: contract}, nil +} + +// bindL2OutputOracle binds a generic wrapper to an already deployed contract. +func bindL2OutputOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(L2OutputOracleABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_L2OutputOracle *L2OutputOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L2OutputOracle.Contract.L2OutputOracleCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_L2OutputOracle *L2OutputOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L2OutputOracle.Contract.L2OutputOracleTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_L2OutputOracle *L2OutputOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L2OutputOracle.Contract.L2OutputOracleTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_L2OutputOracle *L2OutputOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L2OutputOracle.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L2OutputOracle.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L2OutputOracle.Contract.contract.Transact(opts, method, params...) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "historicalTotalBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) HistoricalTotalBlocks() (*big.Int, error) { + return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) HistoricalTotalBlocks() (*big.Int, error) { + return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "l2BlockTime") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) L2BlockTime() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) L2BlockTime() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) LatestBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "latestBlockTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) LatestBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) LatestBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) NextTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "nextTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) NextTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts) +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) NextTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_L2OutputOracle *L2OutputOracleCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_L2OutputOracle *L2OutputOracleSession) Owner() (common.Address, error) { + return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_L2OutputOracle *L2OutputOracleCallerSession) Owner() (common.Address, error) { + return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) StartingBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "startingBlockTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) StartingBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) StartingBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. +// +// Solidity: function submissionInterval() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) SubmissionInterval(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "submissionInterval") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. +// +// Solidity: function submissionInterval() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) SubmissionInterval() (*big.Int, error) { + return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) +} + +// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. +// +// Solidity: function submissionInterval() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) SubmissionInterval() (*big.Int, error) { + return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() +func (_L2OutputOracle *L2OutputOracleTransactor) AppendL2Output(opts *bind.TransactOpts, _l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "appendL2Output", _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() +func (_L2OutputOracle *L2OutputOracleSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { + return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { + return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_L2OutputOracle *L2OutputOracleTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_L2OutputOracle *L2OutputOracleSession) RenounceOwnership() (*types.Transaction, error) { + return _L2OutputOracle.Contract.RenounceOwnership(&_L2OutputOracle.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _L2OutputOracle.Contract.RenounceOwnership(&_L2OutputOracle.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_L2OutputOracle *L2OutputOracleTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_L2OutputOracle *L2OutputOracleSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.Contract.TransferOwnership(&_L2OutputOracle.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.Contract.TransferOwnership(&_L2OutputOracle.TransactOpts, newOwner) +} + +// L2OutputOracleOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the L2OutputOracle contract. +type L2OutputOracleOwnershipTransferredIterator struct { + Event *L2OutputOracleOwnershipTransferred // 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 *L2OutputOracleOwnershipTransferredIterator) 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(L2OutputOracleOwnershipTransferred) + 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(L2OutputOracleOwnershipTransferred) + 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 *L2OutputOracleOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *L2OutputOracleOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// L2OutputOracleOwnershipTransferred represents a OwnershipTransferred event raised by the L2OutputOracle contract. +type L2OutputOracleOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*L2OutputOracleOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &L2OutputOracleOwnershipTransferredIterator{contract: _L2OutputOracle.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *L2OutputOracleOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(L2OutputOracleOwnershipTransferred) + if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_L2OutputOracle *L2OutputOracleFilterer) ParseOwnershipTransferred(log types.Log) (*L2OutputOracleOwnershipTransferred, error) { + event := new(L2OutputOracleOwnershipTransferred) + if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// L2OutputOracleL2OutputAppendedIterator is returned from FilterL2OutputAppended and is used to iterate over the raw logs and unpacked data for L2OutputAppended events raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputAppendedIterator struct { + Event *L2OutputOracleL2OutputAppended // 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 *L2OutputOracleL2OutputAppendedIterator) 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(L2OutputOracleL2OutputAppended) + 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(L2OutputOracleL2OutputAppended) + 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 *L2OutputOracleL2OutputAppendedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *L2OutputOracleL2OutputAppendedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// L2OutputOracleL2OutputAppended represents a L2OutputAppended event raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputAppended struct { + L2Output [32]byte + L2timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterL2OutputAppended is a free log retrieval operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputAppendedIterator, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) + if err != nil { + return nil, err + } + return &L2OutputOracleL2OutputAppendedIterator{contract: _L2OutputOracle.contract, event: "l2OutputAppended", logs: logs, sub: sub}, nil +} + +// WatchL2OutputAppended is a free log subscription operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputAppended, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) + 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(L2OutputOracleL2OutputAppended) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", 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 +} + +// ParseL2OutputAppended is a log parse operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.Log) (*L2OutputOracleL2OutputAppended, error) { + event := new(L2OutputOracleL2OutputAppended) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/l2os/bindings/l2oo/mock_l2_output_oracle.go b/l2os/bindings/l2oo/mock_l2_output_oracle.go deleted file mode 100644 index 36bc186f56c4..000000000000 --- a/l2os/bindings/l2oo/mock_l2_output_oracle.go +++ /dev/null @@ -1,471 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package l2oo - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "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/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// MockL2OutputOracleMetaData contains all meta data concerning the MockL2OutputOracle contract. -var MockL2OutputOracleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionFrequency\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"l2Outputs\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionFrequency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5060405161098f38038061098f833981810160405281019061003291906100e7565b83600081905550826001819055508160026000428152602001908152602001600020819055508060038190555042600481905550426005819055505050505061014e565b600080fd5b6000819050919050565b61008e8161007b565b811461009957600080fd5b50565b6000815190506100ab81610085565b92915050565b6000819050919050565b6100c4816100b1565b81146100cf57600080fd5b50565b6000815190506100e1816100bb565b92915050565b6000806000806080858703121561010157610100610076565b5b600061010f8782880161009c565b94505060206101208782880161009c565b9350506040610131878288016100d2565b92505060606101428782880161009c565b91505092959194509250565b6108328061015d6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806393991af31161006657806393991af314610134578063b210dc2114610152578063b71d13e214610170578063c5095d681461018c578063c90ec2da146101aa57610093565b806302be8bfe1461009857806302e51345146100c85780630c1952d3146100f8578063357e951f14610116575b600080fd5b6100b260048036038101906100ad91906103b9565b6101c8565b6040516100bf91906103ff565b60405180910390f35b6100e260048036038101906100dd91906103b9565b6101e0565b6040516100ef9190610429565b60405180910390f35b610100610256565b60405161010d9190610429565b60405180910390f35b61011e61025c565b60405161012b9190610429565b60405180910390f35b61013c610272565b6040516101499190610429565b60405180910390f35b61015a610278565b6040516101679190610429565b60405180910390f35b61018a60048036038101906101859190610470565b61027e565b005b610194610372565b6040516101a19190610429565b60405180910390f35b6101b2610378565b6040516101bf9190610429565b60405180910390f35b60026020528060005260406000206000915090505481565b6000600554821015610227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021e90610533565b60405180910390fd5b600154600554836102389190610582565b61024291906105e5565b60035461024f9190610616565b9050919050565b60045481565b6000805460045461026d9190610616565b905090565b60015481565b60005481565b8042116102c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b7906106de565b60405180910390fd5b6000801b821415610306576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102fd9061074a565b60405180910390fd5b61030e61025c565b811461034f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610346906107dc565b60405180910390fd5b816002600083815260200190815260200160002081905550806004819055505050565b60055481565b60035481565b600080fd5b6000819050919050565b61039681610383565b81146103a157600080fd5b50565b6000813590506103b38161038d565b92915050565b6000602082840312156103cf576103ce61037e565b5b60006103dd848285016103a4565b91505092915050565b6000819050919050565b6103f9816103e6565b82525050565b600060208201905061041460008301846103f0565b92915050565b61042381610383565b82525050565b600060208201905061043e600083018461041a565b92915050565b61044d816103e6565b811461045857600080fd5b50565b60008135905061046a81610444565b92915050565b600080604083850312156104875761048661037e565b5b60006104958582860161045b565b92505060206104a6858286016103a4565b9150509250929050565b600082825260208201905092915050565b7f74696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b600061051d6029836104b0565b9150610528826104c1565b604082019050919050565b6000602082019050818103600083015261054c81610510565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061058d82610383565b915061059883610383565b9250828210156105ab576105aa610553565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006105f082610383565b91506105fb83610383565b92508261060b5761060a6105b6565b5b828204905092915050565b600061062182610383565b915061062c83610383565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561066157610660610553565b5b828201905092915050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b60006106c86021836104b0565b91506106d38261066c565b604082019050919050565b600060208201905081810360008301526106f7816106bb565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610734601d836104b0565b915061073f826106fe565b602082019050919050565b6000602082019050818103600083015261076381610727565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b60006107c6602e836104b0565b91506107d18261076a565b604082019050919050565b600060208201905081810360008301526107f5816107b9565b905091905056fea2646970667358221220af714f0befbe4567f9ca655b787c21715645bed1c576fe2c2b7649d5dfe0af1564736f6c634300080b0033", -} - -// MockL2OutputOracleABI is the input ABI used to generate the binding from. -// Deprecated: Use MockL2OutputOracleMetaData.ABI instead. -var MockL2OutputOracleABI = MockL2OutputOracleMetaData.ABI - -// MockL2OutputOracleBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use MockL2OutputOracleMetaData.Bin instead. -var MockL2OutputOracleBin = MockL2OutputOracleMetaData.Bin - -// DeployMockL2OutputOracle deploys a new Ethereum contract, binding an instance of MockL2OutputOracle to it. -func DeployMockL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionFrequency *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int) (common.Address, *types.Transaction, *MockL2OutputOracle, error) { - parsed, err := MockL2OutputOracleMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MockL2OutputOracleBin), backend, _submissionFrequency, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &MockL2OutputOracle{MockL2OutputOracleCaller: MockL2OutputOracleCaller{contract: contract}, MockL2OutputOracleTransactor: MockL2OutputOracleTransactor{contract: contract}, MockL2OutputOracleFilterer: MockL2OutputOracleFilterer{contract: contract}}, nil -} - -// MockL2OutputOracle is an auto generated Go binding around an Ethereum contract. -type MockL2OutputOracle struct { - MockL2OutputOracleCaller // Read-only binding to the contract - MockL2OutputOracleTransactor // Write-only binding to the contract - MockL2OutputOracleFilterer // Log filterer for contract events -} - -// MockL2OutputOracleCaller is an auto generated read-only Go binding around an Ethereum contract. -type MockL2OutputOracleCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// MockL2OutputOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. -type MockL2OutputOracleTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// MockL2OutputOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type MockL2OutputOracleFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// MockL2OutputOracleSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type MockL2OutputOracleSession struct { - Contract *MockL2OutputOracle // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// MockL2OutputOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type MockL2OutputOracleCallerSession struct { - Contract *MockL2OutputOracleCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// MockL2OutputOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type MockL2OutputOracleTransactorSession struct { - Contract *MockL2OutputOracleTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// MockL2OutputOracleRaw is an auto generated low-level Go binding around an Ethereum contract. -type MockL2OutputOracleRaw struct { - Contract *MockL2OutputOracle // Generic contract binding to access the raw methods on -} - -// MockL2OutputOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type MockL2OutputOracleCallerRaw struct { - Contract *MockL2OutputOracleCaller // Generic read-only contract binding to access the raw methods on -} - -// MockL2OutputOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type MockL2OutputOracleTransactorRaw struct { - Contract *MockL2OutputOracleTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewMockL2OutputOracle creates a new instance of MockL2OutputOracle, bound to a specific deployed contract. -func NewMockL2OutputOracle(address common.Address, backend bind.ContractBackend) (*MockL2OutputOracle, error) { - contract, err := bindMockL2OutputOracle(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &MockL2OutputOracle{MockL2OutputOracleCaller: MockL2OutputOracleCaller{contract: contract}, MockL2OutputOracleTransactor: MockL2OutputOracleTransactor{contract: contract}, MockL2OutputOracleFilterer: MockL2OutputOracleFilterer{contract: contract}}, nil -} - -// NewMockL2OutputOracleCaller creates a new read-only instance of MockL2OutputOracle, bound to a specific deployed contract. -func NewMockL2OutputOracleCaller(address common.Address, caller bind.ContractCaller) (*MockL2OutputOracleCaller, error) { - contract, err := bindMockL2OutputOracle(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &MockL2OutputOracleCaller{contract: contract}, nil -} - -// NewMockL2OutputOracleTransactor creates a new write-only instance of MockL2OutputOracle, bound to a specific deployed contract. -func NewMockL2OutputOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*MockL2OutputOracleTransactor, error) { - contract, err := bindMockL2OutputOracle(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &MockL2OutputOracleTransactor{contract: contract}, nil -} - -// NewMockL2OutputOracleFilterer creates a new log filterer instance of MockL2OutputOracle, bound to a specific deployed contract. -func NewMockL2OutputOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*MockL2OutputOracleFilterer, error) { - contract, err := bindMockL2OutputOracle(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &MockL2OutputOracleFilterer{contract: contract}, nil -} - -// bindMockL2OutputOracle binds a generic wrapper to an already deployed contract. -func bindMockL2OutputOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(MockL2OutputOracleABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_MockL2OutputOracle *MockL2OutputOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _MockL2OutputOracle.Contract.MockL2OutputOracleCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_MockL2OutputOracle *MockL2OutputOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _MockL2OutputOracle.Contract.MockL2OutputOracleTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_MockL2OutputOracle *MockL2OutputOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _MockL2OutputOracle.Contract.MockL2OutputOracleTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_MockL2OutputOracle *MockL2OutputOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _MockL2OutputOracle.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_MockL2OutputOracle *MockL2OutputOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _MockL2OutputOracle.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_MockL2OutputOracle *MockL2OutputOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _MockL2OutputOracle.Contract.contract.Transact(opts, method, params...) -} - -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. -// -// Solidity: function computeL2BlockNumber(uint256 _timestamp) view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _timestamp *big.Int) (*big.Int, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _timestamp) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. -// -// Solidity: function computeL2BlockNumber(uint256 _timestamp) view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleSession) ComputeL2BlockNumber(_timestamp *big.Int) (*big.Int, error) { - return _MockL2OutputOracle.Contract.ComputeL2BlockNumber(&_MockL2OutputOracle.CallOpts, _timestamp) -} - -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. -// -// Solidity: function computeL2BlockNumber(uint256 _timestamp) view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) ComputeL2BlockNumber(_timestamp *big.Int) (*big.Int, error) { - return _MockL2OutputOracle.Contract.ComputeL2BlockNumber(&_MockL2OutputOracle.CallOpts, _timestamp) -} - -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. -// -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "historicalTotalBlocks") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. -// -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleSession) HistoricalTotalBlocks() (*big.Int, error) { - return _MockL2OutputOracle.Contract.HistoricalTotalBlocks(&_MockL2OutputOracle.CallOpts) -} - -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. -// -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) HistoricalTotalBlocks() (*big.Int, error) { - return _MockL2OutputOracle.Contract.HistoricalTotalBlocks(&_MockL2OutputOracle.CallOpts) -} - -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. -// -// Solidity: function l2BlockTime() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "l2BlockTime") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. -// -// Solidity: function l2BlockTime() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleSession) L2BlockTime() (*big.Int, error) { - return _MockL2OutputOracle.Contract.L2BlockTime(&_MockL2OutputOracle.CallOpts) -} - -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. -// -// Solidity: function l2BlockTime() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) L2BlockTime() (*big.Int, error) { - return _MockL2OutputOracle.Contract.L2BlockTime(&_MockL2OutputOracle.CallOpts) -} - -// L2Outputs is a free data retrieval call binding the contract method 0x02be8bfe. -// -// Solidity: function l2Outputs(uint256 ) view returns(bytes32) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) L2Outputs(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "l2Outputs", arg0) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// L2Outputs is a free data retrieval call binding the contract method 0x02be8bfe. -// -// Solidity: function l2Outputs(uint256 ) view returns(bytes32) -func (_MockL2OutputOracle *MockL2OutputOracleSession) L2Outputs(arg0 *big.Int) ([32]byte, error) { - return _MockL2OutputOracle.Contract.L2Outputs(&_MockL2OutputOracle.CallOpts, arg0) -} - -// L2Outputs is a free data retrieval call binding the contract method 0x02be8bfe. -// -// Solidity: function l2Outputs(uint256 ) view returns(bytes32) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) L2Outputs(arg0 *big.Int) ([32]byte, error) { - return _MockL2OutputOracle.Contract.L2Outputs(&_MockL2OutputOracle.CallOpts, arg0) -} - -// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. -// -// Solidity: function latestBlockTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) LatestBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "latestBlockTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. -// -// Solidity: function latestBlockTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleSession) LatestBlockTimestamp() (*big.Int, error) { - return _MockL2OutputOracle.Contract.LatestBlockTimestamp(&_MockL2OutputOracle.CallOpts) -} - -// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. -// -// Solidity: function latestBlockTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) LatestBlockTimestamp() (*big.Int, error) { - return _MockL2OutputOracle.Contract.LatestBlockTimestamp(&_MockL2OutputOracle.CallOpts) -} - -// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. -// -// Solidity: function nextTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) NextTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "nextTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. -// -// Solidity: function nextTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleSession) NextTimestamp() (*big.Int, error) { - return _MockL2OutputOracle.Contract.NextTimestamp(&_MockL2OutputOracle.CallOpts) -} - -// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. -// -// Solidity: function nextTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) NextTimestamp() (*big.Int, error) { - return _MockL2OutputOracle.Contract.NextTimestamp(&_MockL2OutputOracle.CallOpts) -} - -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) StartingBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "startingBlockTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleSession) StartingBlockTimestamp() (*big.Int, error) { - return _MockL2OutputOracle.Contract.StartingBlockTimestamp(&_MockL2OutputOracle.CallOpts) -} - -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) StartingBlockTimestamp() (*big.Int, error) { - return _MockL2OutputOracle.Contract.StartingBlockTimestamp(&_MockL2OutputOracle.CallOpts) -} - -// SubmissionFrequency is a free data retrieval call binding the contract method 0xb210dc21. -// -// Solidity: function submissionFrequency() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCaller) SubmissionFrequency(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _MockL2OutputOracle.contract.Call(opts, &out, "submissionFrequency") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// SubmissionFrequency is a free data retrieval call binding the contract method 0xb210dc21. -// -// Solidity: function submissionFrequency() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleSession) SubmissionFrequency() (*big.Int, error) { - return _MockL2OutputOracle.Contract.SubmissionFrequency(&_MockL2OutputOracle.CallOpts) -} - -// SubmissionFrequency is a free data retrieval call binding the contract method 0xb210dc21. -// -// Solidity: function submissionFrequency() view returns(uint256) -func (_MockL2OutputOracle *MockL2OutputOracleCallerSession) SubmissionFrequency() (*big.Int, error) { - return _MockL2OutputOracle.Contract.SubmissionFrequency(&_MockL2OutputOracle.CallOpts) -} - -// AppendL2Output is a paid mutator transaction binding the contract method 0xb71d13e2. -// -// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _timestamp) returns() -func (_MockL2OutputOracle *MockL2OutputOracleTransactor) AppendL2Output(opts *bind.TransactOpts, _l2Output [32]byte, _timestamp *big.Int) (*types.Transaction, error) { - return _MockL2OutputOracle.contract.Transact(opts, "appendL2Output", _l2Output, _timestamp) -} - -// AppendL2Output is a paid mutator transaction binding the contract method 0xb71d13e2. -// -// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _timestamp) returns() -func (_MockL2OutputOracle *MockL2OutputOracleSession) AppendL2Output(_l2Output [32]byte, _timestamp *big.Int) (*types.Transaction, error) { - return _MockL2OutputOracle.Contract.AppendL2Output(&_MockL2OutputOracle.TransactOpts, _l2Output, _timestamp) -} - -// AppendL2Output is a paid mutator transaction binding the contract method 0xb71d13e2. -// -// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _timestamp) returns() -func (_MockL2OutputOracle *MockL2OutputOracleTransactorSession) AppendL2Output(_l2Output [32]byte, _timestamp *big.Int) (*types.Transaction, error) { - return _MockL2OutputOracle.Contract.AppendL2Output(&_MockL2OutputOracle.TransactOpts, _l2Output, _timestamp) -} diff --git a/l2os/drivers/l2output/driver.go b/l2os/drivers/l2output/driver.go index d22983d8d955..f98f9c789341 100644 --- a/l2os/drivers/l2output/driver.go +++ b/l2os/drivers/l2output/driver.go @@ -34,13 +34,13 @@ type Config struct { type Driver struct { cfg Config - l2ooContract *l2oo.MockL2OutputOracle + l2ooContract *l2oo.L2OutputOracle rawL2ooContract *bind.BoundContract walletAddr common.Address } func NewDriver(cfg Config) (*Driver, error) { - l2ooContract, err := l2oo.NewMockL2OutputOracle( + l2ooContract, err := l2oo.NewL2OutputOracle( cfg.L2OOAddr, cfg.L1Client, ) if err != nil { @@ -48,7 +48,7 @@ func NewDriver(cfg Config) (*Driver, error) { } parsed, err := abi.JSON(strings.NewReader( - l2oo.MockL2OutputOracleMetaData.ABI, + l2oo.L2OutputOracleMetaData.ABI, )) if err != nil { return nil, err @@ -196,7 +196,12 @@ func (d *Driver) CraftTx( numElements := new(big.Int).Sub(start, end).Uint64() log.Info(name+" checkpoint constructed", "start", start, "end", end, - "nonce", nonce, "blocks_committed", numElements) + "nonce", nonce, "blocks_committed", numElements, "checkpoint_block", nextCheckpointBlock) + + header, err := d.cfg.L1Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, fmt.Errorf("error resolving checkpoint block: %v", err) + } opts, err := bind.NewKeyedTransactorWithChainID( d.cfg.PrivKey, d.cfg.ChainID, @@ -208,7 +213,7 @@ func (d *Driver) CraftTx( opts.Nonce = nonce opts.NoSend = true - return d.l2ooContract.AppendL2Output(opts, l2OutputRoot, timestamp) + return d.l2ooContract.AppendL2Output(opts, l2OutputRoot, timestamp, header.Hash(), header.Number) } // UpdateGasPrice signs an otherwise identical txn to the one provided but with diff --git a/l2os/flags/flags.go b/l2os/flags/flags.go index 9db9631e585c..e7afc7743904 100644 --- a/l2os/flags/flags.go +++ b/l2os/flags/flags.go @@ -4,7 +4,7 @@ import ( "github.com/urfave/cli" ) -const envVarPrefix = "BATCH_SUBMITTER_" +const envVarPrefix = "OUTPUT_SUBMITTER_" func prefixEnvVar(name string) string { return envVarPrefix + name diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 29967fc455df..8b082b0c7fb2 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -81,7 +81,7 @@ func RollupNodeMain(ctx *cli.Context) error { log.Info("Starting rollup node") if err := n.Start(context.Background()); err != nil { - log.Error("Unable to start L2 Output Submitter", "error", err) + log.Error("Unable to start rollup node", "error", err) return err } defer n.Stop() diff --git a/opnode/node/server.go b/opnode/node/server.go index 667dcafc92ad..49624778c911 100644 --- a/opnode/node/server.go +++ b/opnode/node/server.go @@ -6,7 +6,6 @@ import ( "fmt" "net" "net/http" - "strings" "github.com/ethereum/go-ethereum" @@ -52,8 +51,11 @@ func (s *rpcServer) Start() error { return err } - host := strings.Split(s.endpoint, ":")[0] - nodeHandler := node.NewHTTPHandlerStack(srv, nil, []string{host}, nil) + // The CORS and VHosts arguments below must be set in order for + // other services to connect to the opnode. VHosts in particular + // defaults to localhost, which will prevent containers from + // calling into the opnode without an "invalid host" error. + nodeHandler := node.NewHTTPHandlerStack(srv, []string{"*"}, []string{"*"}, nil) mux := http.NewServeMux() mux.Handle("/", nodeHandler) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 2b3b5405524b..161e9e10dedf 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -206,7 +206,7 @@ func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) continue } for _, log := range rec.Logs { - if log.Address == depositContractAddr { + if log.Address == depositContractAddr && len(log.Topics) > 0 && log.Topics[0] == DepositEventABIHash { dep, err := UnmarshalLogEvent(log) if err != nil { return nil, fmt.Errorf("malformatted L1 deposit log: %v", err) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 13e7ea30c8ec..8bb4fc6901b5 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -176,7 +176,15 @@ func TestL2OutputSubmitter(t *testing.T) { submissionFrequency := big.NewInt(2) // 2 seconds l2BlockTime := big.NewInt(1) // 1 seconds - l2ooAddr, tx, l2OutputOracle, err := l2oo.DeployMockL2OutputOracle(opts, l1Client, submissionFrequency, l2BlockTime, [32]byte{}, big.NewInt(0)) + l2ooAddr, tx, l2OutputOracle, err := l2oo.DeployL2OutputOracle( + opts, + l1Client, + submissionFrequency, + l2BlockTime, + [32]byte{}, + big.NewInt(0), + l2OutputAddr, + ) require.Nil(t, err) ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) @@ -217,7 +225,7 @@ func TestL2OutputSubmitter(t *testing.T) { // timestamp set in the contract constructor. if l2ooTimestamp.Cmp(initialSroTimestamp) > 0 { // Retrieve the l2 output committed at this updated timestamp. - committedL2Output, err := l2OutputOracle.L2Outputs(&bind.CallOpts{}, l2ooTimestamp) + committedL2Output, err := l2OutputOracle.GetL2Output(&bind.CallOpts{}, l2ooTimestamp) require.Nil(t, err) // Compute the committed L2 output's L2 block number. diff --git a/ops/Dockerfile.l1 b/ops/Dockerfile.l1 index 4ce0bd5b6d17..dd44a832494c 100644 --- a/ops/Dockerfile.l1 +++ b/ops/Dockerfile.l1 @@ -1,18 +1,8 @@ FROM ethereum/client-go:v1.10.16 -ARG DEPOSIT_FEED_BYTECODE="" -ARG GENESIS_TIMESTAMP="" - RUN apk add --no-cache jq COPY entrypoint.sh /entrypoint.sh -COPY genesis-l1.json /genesis.json - -RUN cat /genesis.json | \ - jq ". | .alloc.deaddeaddeaddeaddeaddeaddeaddeaddead0001.code = \"$DEPOSIT_FEED_BYTECODE\"" | \ - jq ". | .timestamp = \"$GENESIS_TIMESTAMP\"" | \ - tee /genesis-with-bytecode.json && \ - mv /genesis-with-bytecode.json /genesis.json VOLUME ["/db"] diff --git a/ops/Dockerfile.l2 b/ops/Dockerfile.l2 index dd47af40fbbc..8f73abb81efb 100644 --- a/ops/Dockerfile.l2 +++ b/ops/Dockerfile.l2 @@ -1,19 +1,8 @@ FROM ethereumoptimism/reference-optimistic-geth:latest -ARG L1_BLOCK_INFO_BYTECODE="" -ARG WITHDRAWER_BYTECODE="" -ARG GENESIS_TIMESTAMP="" - RUN apk add --no-cache jq COPY entrypoint.sh /entrypoint.sh -COPY genesis-l2.json /genesis.json - -RUN cat /genesis.json | jq ". | .alloc.\"4200000000000000000000000000000000000014\".code = \"$L1_BLOCK_INFO_BYTECODE\"" \ - | jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$WITHDRAWER_BYTECODE\"" \ - | jq ". | .timestamp = \"$GENESIS_TIMESTAMP\"" \ - | tee /genesis-with-bytecode.json && \ - mv /genesis-with-bytecode.json /genesis.json VOLUME ["/db"] diff --git a/ops/Dockerfile.l2os b/ops/Dockerfile.l2os new file mode 100644 index 000000000000..7626cc48416b --- /dev/null +++ b/ops/Dockerfile.l2os @@ -0,0 +1,23 @@ +FROM golang:1.18.0-alpine3.15 as builder + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +COPY Makefile /app/Makefile +COPY go.mod /app/go.mod +COPY go.sum /app/go.sum + +WORKDIR /app +COPY ./ops/l2os-entrypoint.sh /app/l2os-entrypoint.sh + +COPY ./l2os /app/l2os +COPY ./opnode /app/opnode +RUN make l2os + +FROM alpine:3.15 + +RUN apk add --no-cache curl jq + +COPY --from=builder /app/bin/l2os /usr/local/bin +COPY --from=builder /app/l2os-entrypoint.sh /l2os-entrypoint.sh + +ENTRYPOINT ["/bin/sh", "/l2os-entrypoint.sh"] diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode index ec12ff50b173..832a960c883f 100644 --- a/ops/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -7,18 +7,12 @@ COPY go.mod /app/go.mod COPY go.sum /app/go.sum WORKDIR /app -COPY ./ops/opnode-entrypoint.sh /app/opnode-entrypoint.sh -COPY ./ops/rollup.json /app/rollup.json - COPY ./opnode /app/opnode RUN make opnode FROM alpine:3.15 -RUN apk add --no-cache curl jq - COPY --from=builder /app/bin/op /usr/local/bin -COPY --from=builder /app/opnode-entrypoint.sh /opnode-entrypoint.sh -COPY --from=builder /app/rollup.json /rollup.json +COPY ./ops/opnode-entrypoint.sh /opnode-entrypoint.sh ENTRYPOINT ["/bin/sh", "/opnode-entrypoint.sh"] diff --git a/ops/devnet-up.sh b/ops/devnet-up.sh new file mode 100644 index 000000000000..f06fadf716a0 --- /dev/null +++ b/ops/devnet-up.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env bash + +# This script starts a local devnet using Docker Compose. We have to use +# this more complicated Bash script rather than Compose's native orchestration +# tooling because we need to start each service in a specific order, and specify +# their configuration along the way. The order is: +# +# 1. Start L1. +# 2. Compile contracts. +# 3. Deploy the contracts to L1 if necessary. +# 4. Start L2, inserting the compiled contract artifacts into the genesis. +# 5. Get the genesis hashes and timestamps from L1/L2. +# 6. Generate the rollup driver's config using the genesis hashes and the +# timestamps recovered in step 4 as well as the address of the OptimismPortal +# contract deployed in step 3. +# 7. Start the rollup driver. +# 8. Start the L2 output submitter. +# +# The timestamps are critically important here, since the rollup driver will fill in +# empty blocks if the tip of L1 lags behind the current timestamp. This can lead to +# a perceived infinite loop. To get around this, we set the timestamp to the current +# time in this script. +# +# This script is safe to run multiple times. It stores state in `.devnet`, and +# packages/contracts/deployments/devnetL1. +# +# Don't run this script directly. Run it using the makefile, e.g. `make devnet-up`. +# To clean up your devnet, run `make devnet-clean`. + +set -eu + +L1_URL="http://localhost:8545" +L2_URL="http://localhost:9545" + +# Helper method that waits for a given URL to be up. Can't use +# cURL's built-in retry logic because connection reset errors +# are ignored unless you're using a very recent version of cURL +function wait_up { + echo -n "Waiting for $1 to come up..." + i=0 + until curl -s -f -o /dev/null "$1" + do + echo -n . + sleep 0.25 + + ((i=i+1)) + if [ "$i" -eq 120 ]; then + echo " Timeout!" >&2 + exit 0 + fi + done + echo "Done!" +} + +# Regenerate the L1 genesis file if necessary. The existence of the genesis +# file is used to determine if we need to recreate the devnet's state folder. +if [ ! -f ./.devnet/genesis-l1.json ]; then + echo "Regenerating L1 genesis." + mkdir -p ./.devnet + GENESIS_TIMESTAMP=$(date +%s | xargs printf "0x%x") + jq ". | .timestamp = \"$GENESIS_TIMESTAMP\" " < ./ops/genesis-l1.json > ./.devnet/genesis-l1.json +else + GENESIS_TIMESTAMP=$(jq -r '.timestamp' < ./.devnet/genesis-l1.json) +fi + +# Bring up L1. +cd ops +echo "Bringing up L1..." +DOCKER_BUILDKIT=1 docker-compose build +docker-compose up -d l1 +wait_up $L1_URL +cd ../ + +# Deploy contracts using Hardhat. +if [ ! -f ./packages/contracts/deployments/devnetL1/OptimismPortal.json ]; then + echo "Deploying contracts." + cd ./packages/contracts + L2OO_STARTING_BLOCK_TIMESTAMP=$GENESIS_TIMESTAMP yarn hardhat --network devnetL1 deploy + cd ../../ +else + echo "Contracts already deployed, skipping." +fi + +# Pull out the necessary bytecode/addresses from the artifacts/deployments. +WITHDRAWER_BYTECODE=$(jq -r .deployedBytecode < ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json) +L1_BLOCK_INFO_BYTECODE=$(jq -r .deployedBytecode < ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json) +DEPOSIT_CONTRACT_ADDRESS=$(jq -r .address < ./packages/contracts/deployments/devnetL1/OptimismPortal.json) +L2OO_ADDRESS=$(jq -r .address < ./packages/contracts/deployments/devnetL1/L2OutputOracle.json) + +# Replace values in the L2 genesis file. It doesn't matter if this gets run every time, +# since the replaced values will be the same. +jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$L1_BLOCK_INFO_BYTECODE\"" < ./ops/genesis-l2.json | \ + jq ". | .alloc.\"4200000000000000000000000000000000000015\".balance = \"0x0\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000016\".code = \"$WITHDRAWER_BYTECODE\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000016\".balance = \"0x0\"" | \ + jq ". | .timestamp = \"$GENESIS_TIMESTAMP\" " > ./.devnet/genesis-l2.json + +# Bring up L2. +cd ops +echo "Bringing up L2..." +docker-compose up -d l2 +wait_up $L2_URL +cd ../ + +# Start putting together the rollup config. +echo "Building rollup config..." + +# Grab the L1 genesis. We can use cURL here to retry. +L1_GENESIS=$(curl \ + --silent \ + --fail \ + --retry 10 \ + --retry-delay 2 \ + --retry-connrefused \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + $L1_URL) + +# Grab the L2 genesis. We can use cURL here to retry. +L2_GENESIS=$(curl \ + --silent \ + --fail \ + --retry 10 \ + --retry-delay 2 \ + --retry-connrefused \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + $L2_URL) + +# Generate the rollup config. +jq ". | .genesis.l1.hash = \"$(echo $L1_GENESIS | jq -r '.result.hash')\"" < ./ops/rollup.json | \ + jq ". | .genesis.l2.hash = \"$(echo $L2_GENESIS | jq -r '.result.hash')\"" | \ + jq ". | .genesis.l2_time = $(echo $L2_GENESIS | jq -r '.result.timestamp' | xargs printf "%d")" | \ + jq ". | .deposit_contract_address = \"$DEPOSIT_CONTRACT_ADDRESS\"" > ./.devnet/rollup.json + +# Bring up everything else. +cd ops +echo "Bringing up rollup node..." +docker-compose up -d opnode +echo "Bringing up output submitter..." +docker-compose run -e L2OO_ADDRESS="$L2OO_ADDRESS" -d --name ops-l2os-1 l2os +cd ../ + +echo "Devnet ready." \ No newline at end of file diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index eaddc79c3245..7d313babbe95 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -1,5 +1,9 @@ version: '3.4' +# This Compose file is expected to be used with the devnet-up.sh script. +# The volumes below mount the configs generated by the script into each +# service. + volumes: l1_data: l2_data: @@ -9,26 +13,21 @@ services: build: context: . dockerfile: Dockerfile.l1 - args: - DEPOSIT_FEED_BYTECODE: $DEPOSIT_FEED_BYTECODE - GENESIS_TIMESTAMP: $GENESIS_TIMESTAMP ports: - "8545:8545" volumes: - "l1_data:/db" + - ${PWD}/../.devnet/genesis-l1.json:/genesis.json l2: build: context: . dockerfile: Dockerfile.l2 - args: - L1_BLOCK_INFO_BYTECODE: $L1_BLOCK_INFO_BYTECODE - WITHDRAWER_BYTECODE: $WITHDRAWER_BYTECODE - GENESIS_TIMESTAMP: $GENESIS_TIMESTAMP ports: - "9545:8545" volumes: - "l2_data:/db" + - ${PWD}/../.devnet/genesis-l2.json:/genesis.json opnode: depends_on: @@ -41,6 +40,23 @@ services: - "7545:8545" volumes: - ${PWD}/bss-key.txt:/config/bss-key.txt - - ${PWD}/rollup.json:/config/rollup.json - command: - - "opnode-entrypoint.sh" + - ${PWD}/../.devnet/rollup.json:/rollup.json + + l2os: + depends_on: + - l1 + - l2 + - opnode + build: + context: ../ + dockerfile: ./ops/Dockerfile.l2os + environment: + L1_ETH_RPC: http://l1:8545 + L2_ETH_RPC: http://l2:8545 + ROLLUP_RPC: http://opnode:8545 + OUTPUT_SUBMITTER_POLL_INTERVAL: 10s + OUTPUT_SUBMITTER_NUM_CONFIRMATIONS: 1 + OUTPUT_SUBMITTER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 + OUTPUT_SUBMITTER_RESUBMISSION_TIMEOUT: 30s + OUTPUT_SUBMITTER_MNEMONIC: test test test test test test test test test test test junk + OUTPUT_SUBMITTER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" \ No newline at end of file diff --git a/ops/entrypoint.sh b/ops/entrypoint.sh index 6c318dd097fb..17cc66fdc82d 100644 --- a/ops/entrypoint.sh +++ b/ops/entrypoint.sh @@ -31,6 +31,9 @@ else echo "$GETH_CHAINDATA_DIR exists." fi +# Warning: Archive mode is required, otherwise old trie nodes will be +# pruned within minutes of starting the devnet. + exec geth \ --datadir="$GETH_DATA_DIR" \ --verbosity="$VERBOSITY" \ @@ -39,7 +42,7 @@ exec geth \ --http.vhosts="*" \ --http.addr=0.0.0.0 \ --http.port=8545 \ - --http.api=debug,eth,txpool,net,engine \ + --http.api=web3,debug,eth,txpool,net,engine \ --ws \ --ws.addr=0.0.0.0 \ --ws.port=8546 \ @@ -54,4 +57,5 @@ exec geth \ --miner.etherbase=$BLOCK_SIGNER_ADDRESS \ --password="$GETH_DATA_DIR"/password \ --allow-insecure-unlock \ + --gcmode=archive \ "$@" diff --git a/ops/genesis-l1.json b/ops/genesis-l1.json index 7f38d28636a8..74f1a1b66640 100644 --- a/ops/genesis-l1.json +++ b/ops/genesis-l1.json @@ -799,13 +799,12 @@ "f39fd6e51aad88f6f4ce6ab8827279cfffb92266": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, - "deaddeaddeaddeaddeaddeaddeaddeaddead0001": { - "code": "", - "balance": "0x0" + "70997970C51812dc3A010C7d01b50e0d17dc79C8": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" } }, "number": "0x0", "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "baseFeePerGas": null -} \ No newline at end of file +} diff --git a/ops/genesis-l2.json b/ops/genesis-l2.json index 565b154714a1..54bed7f23729 100644 --- a/ops/genesis-l2.json +++ b/ops/genesis-l2.json @@ -804,6 +804,13 @@ "4200000000000000000000000000000000000015": { "code": "", "balance": "0x0" + }, + "4200000000000000000000000000000000000016": { + "code": "", + "balance": "0x0" + }, + "70997970C51812dc3A010C7d01b50e0d17dc79C8": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" } }, "number": "0x0", diff --git a/ops/l2os-entrypoint.sh b/ops/l2os-entrypoint.sh new file mode 100644 index 000000000000..1990c0bec182 --- /dev/null +++ b/ops/l2os-entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -exu + +curl \ + --fail \ + --retry 10 \ + --retry-delay 2 \ + --retry-connrefused \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + http://l1:8545 + +exec l2os diff --git a/ops/opnode-entrypoint.sh b/ops/opnode-entrypoint.sh index c16640bca81c..a0ce96ebe7d2 100644 --- a/ops/opnode-entrypoint.sh +++ b/ops/opnode-entrypoint.sh @@ -1,36 +1,6 @@ #!/bin/sh set -exu -L1_GENESIS=$(curl \ - --fail \ - --retry 10 \ - --retry-delay 2 \ - --retry-connrefused \ - -X POST \ - -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ - http://l1:8545) - -L2_GENESIS=$(curl \ - --fail \ - --retry 10 \ - --retry-delay 2 \ - --retry-connrefused \ - -X POST \ - -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ - http://l2:8545) - -echo "L2 genesis timestamp:" -echo $L2_GENESIS | jq -r '.result.timestamp' - -cat /rollup.json \ - | jq ". | .genesis.l1.hash = \"$(echo $L1_GENESIS | jq -r '.result.hash')\"" \ - | jq ". | .genesis.l2.hash = \"$(echo $L2_GENESIS | jq -r '.result.hash')\"" \ - | jq ". | .genesis.l2_time = $(echo $L2_GENESIS | jq -r '.result.timestamp' | xargs printf "%d")" \ - | tee /rollup-with-l2-hash.json && \ - mv /rollup-with-l2-hash.json /rollup.json - exec op \ --l1 ws://l1:8546 \ --l2 ws://l2:8546 \ diff --git a/ops/test-integration.sh b/ops/test-integration.sh new file mode 100644 index 000000000000..1a892fa4c223 --- /dev/null +++ b/ops/test-integration.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# This script starts the integration tests using the deployed contracts. The script +# takes one argument: a path to the deployments directory. + +set -eu + +DEPLOYMENTS_DIR="$1" + +if [ ! -f "$DEPLOYMENTS_DIR/OptimismPortal.json" ]; then + echo "Deployment directory $DEPLOYMENTS_DIR not found. Please " + echo "check the path, then try again." +fi + +export OPTIMISM_PORTAL_ADDRESS=$(jq -r '.address' < "$DEPLOYMENTS_DIR/OptimismPortal.json") +cd ./packages/integration-tests +yarn test \ No newline at end of file diff --git a/packages/contracts/.eslintrc.js b/packages/contracts/.eslintrc.js index 97852d4c7764..d4766c8352f7 100644 --- a/packages/contracts/.eslintrc.js +++ b/packages/contracts/.eslintrc.js @@ -16,6 +16,7 @@ module.exports = { ecmaVersion: 12, }, rules: { + 'node/no-unpublished-import': 'off', 'node/no-unsupported-features/es-syntax': [ 'error', { ignores: ['modules'] }, diff --git a/packages/contracts/.gitignore b/packages/contracts/.gitignore index 19d9d7338bfc..1aec10c8032d 100644 --- a/packages/contracts/.gitignore +++ b/packages/contracts/.gitignore @@ -4,3 +4,4 @@ cache typechain coverage.out .deps +deployments \ No newline at end of file diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index bf827872c566..35f798a8ba74 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -52,20 +52,22 @@ contract L2OutputOracle is Ownable { * @param _genesisL2Output The initial L2 output of the L2 chain. * @param _historicalTotalBlocks The number of blocks that preceding the * initialization of the L2 chain. + * @param _startingBlockTimestamp The timestamp to start L2 block at. */ constructor( uint256 _submissionInterval, uint256 _l2BlockTime, bytes32 _genesisL2Output, uint256 _historicalTotalBlocks, + uint256 _startingBlockTimestamp, address sequencer ) { submissionInterval = _submissionInterval; l2BlockTime = _l2BlockTime; - l2Outputs[block.timestamp] = _genesisL2Output; // solhint-disable not-rely-on-time + l2Outputs[_startingBlockTimestamp] = _genesisL2Output; // solhint-disable not-rely-on-time historicalTotalBlocks = _historicalTotalBlocks; - latestBlockTimestamp = block.timestamp; // solhint-disable not-rely-on-time - startingBlockTimestamp = block.timestamp; // solhint-disable not-rely-on-time + latestBlockTimestamp = _startingBlockTimestamp; // solhint-disable not-rely-on-time + startingBlockTimestamp = _startingBlockTimestamp; // solhint-disable not-rely-on-time _transferOwnership(sequencer); } diff --git a/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol index 605a8223b325..3655f85d8549 100644 --- a/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol @@ -35,7 +35,7 @@ library WithdrawalVerifier { uint256 _value, uint256 _gasLimit, bytes calldata _data - ) external pure returns (bytes32) { + ) internal pure returns (bytes32) { return keccak256(abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data)); } diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index fe7f5eeeb1cd..2fffc0481963 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -36,6 +36,7 @@ contract L2OutputOracle_Initializer is DSTest { l2BlockTime, genesisL2Output, historicalTotalBlocks, + initTime, sequencer ); startingBlockTimestamp = block.timestamp; diff --git a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol index 544c66d9bb6c..2155ae91b4a9 100644 --- a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol +++ b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol @@ -97,6 +97,7 @@ contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is DSTest { l2BlockTime, genesisL2Output, historicalTotalBlocks, + initTime, sequencer ); startingBlockTimestamp = block.timestamp; diff --git a/packages/contracts/deploy/000-L2OutputOracle.deploy.ts b/packages/contracts/deploy/000-L2OutputOracle.deploy.ts new file mode 100644 index 000000000000..3cbae9f12cf0 --- /dev/null +++ b/packages/contracts/deploy/000-L2OutputOracle.deploy.ts @@ -0,0 +1,35 @@ +/* Imports: Internal */ +import { DeployFunction } from 'hardhat-deploy/dist/types' +import 'hardhat-deploy' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + if ( + !process.env.L2OO_STARTING_BLOCK_TIMESTAMP || + isNaN(Number(process.env.L2OO_STARTING_BLOCK_TIMESTAMP)) + ) { + throw new Error( + 'Cannot deploy L2OutputOracle without specifying a valid L2OO_STARTING_BLOCK_TIMESTAMP.' + ) + } + + await deploy('L2OutputOracle', { + from: deployer, + args: [ + 15, + 2, + `0x${'00'.repeat(32)}`, + 0, + process.env.L2OO_STARTING_BLOCK_TIMESTAMP, + '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', + ], + log: true, + waitConfirmations: 1, + }) +} + +deployFn.tags = ['L2OutputOracle'] + +export default deployFn diff --git a/packages/contracts/deploy/001-OptimismPortal.deploy.ts b/packages/contracts/deploy/001-OptimismPortal.deploy.ts new file mode 100644 index 000000000000..460f0e62021f --- /dev/null +++ b/packages/contracts/deploy/001-OptimismPortal.deploy.ts @@ -0,0 +1,20 @@ +/* Imports: Internal */ +import { DeployFunction } from 'hardhat-deploy/dist/types' +import 'hardhat-deploy' + +const deployFn: DeployFunction = async (hre) => { + const { deploy, get } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + const oracle = await get('L2OutputOracle') + + await deploy('OptimismPortal', { + from: deployer, + args: [oracle.address, 2], + log: true, + waitConfirmations: 1, + }) +} + +deployFn.tags = ['OptimismPortal'] + +export default deployFn diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index 7b79f2075c2e..0c07fe31f348 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -3,6 +3,8 @@ import '@nomiclabs/hardhat-waffle' import '@typechain/hardhat' import 'hardhat-gas-reporter' import 'solidity-coverage' +import 'hardhat-deploy' + import './tasks/deposits' task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { @@ -15,11 +17,23 @@ task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { const config: HardhatUserConfig = { solidity: '0.8.10', - networks: {}, + networks: { + devnetL1: { + url: 'http://localhost:8545', + accounts: [ + 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', + ], + }, + }, gasReporter: { enabled: process.env.REPORT_GAS !== undefined, currency: 'USD', }, + namedAccounts: { + deployer: { + default: 0, + }, + }, } export default config diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 39c775d64631..7b65a75b5a52 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -54,6 +54,7 @@ "eslint-plugin-promise": "^5.1.0", "ethereum-waffle": "^3.0.0", "ethers": "^5.0.0", + "hardhat-deploy": "^0.11.4", "hardhat-gas-reporter": "^1.0.4", "prettier": "^2.3.2", "prettier-plugin-solidity": "^1.0.0-beta.13", diff --git a/packages/contracts/yarn.lock b/packages/contracts/yarn.lock index 0b8635d57e36..145a6a6282a9 100644 --- a/packages/contracts/yarn.lock +++ b/packages/contracts/yarn.lock @@ -253,6 +253,21 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.0.tgz#ea07cbc1eec2374d32485679c12408005895e9f3" + integrity sha512-AhVByTwdXCc2YQ20v300w6KVHle9g2OFc28ZAFCPnJyEpkv1xKXjZcSTgWOlv1i+0dqlgF8RCF2Rn2KC1t+1Vg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/abstract-provider@5.5.1", "@ethersproject/abstract-provider@^5.4.1", "@ethersproject/abstract-provider@^5.5.0": version "5.5.1" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" @@ -266,6 +281,19 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/web" "^5.5.0" +"@ethersproject/abstract-provider@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz#0c4ac7054650dbd9c476cf5907f588bbb6ef3061" + integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + "@ethersproject/abstract-signer@5.5.0", "@ethersproject/abstract-signer@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" @@ -277,6 +305,17 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/properties" "^5.5.0" +"@ethersproject/abstract-signer@^5.4.1", "@ethersproject/abstract-signer@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz#9cd7ae9211c2b123a3b29bf47aab17d4d016e3e7" + integrity sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/address@5.5.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" @@ -288,7 +327,7 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/rlp" "^5.5.0" -"@ethersproject/address@^5.6.0": +"@ethersproject/address@^5.4.0", "@ethersproject/address@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== @@ -306,6 +345,13 @@ dependencies: "@ethersproject/bytes" "^5.5.0" +"@ethersproject/base64@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.0.tgz#a12c4da2a6fb86d88563216b0282308fc15907c9" + integrity sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/basex@5.5.0", "@ethersproject/basex@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.5.0.tgz#e40a53ae6d6b09ab4d977bd037010d4bed21b4d3" @@ -314,6 +360,14 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/properties" "^5.5.0" +"@ethersproject/basex@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.0.tgz#9ea7209bf0a1c3ddc2a90f180c3a7f0d7d2e8a69" + integrity sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" @@ -323,7 +377,7 @@ "@ethersproject/logger" "^5.5.0" bn.js "^4.11.9" -"@ethersproject/bignumber@^5.6.0": +"@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.0.tgz#116c81b075c57fa765a8f3822648cf718a8a0e26" integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== @@ -339,7 +393,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/bytes@^5.6.0", "@ethersproject/bytes@^5.6.1": +"@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.6.0", "@ethersproject/bytes@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== @@ -353,6 +407,13 @@ dependencies: "@ethersproject/bignumber" "^5.5.0" +"@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.0.tgz#55e3eb0918584d3acc0688e9958b0cedef297088" + integrity sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/contracts@5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.5.0.tgz#b735260d4bd61283a670a82d5275e2a38892c197" @@ -369,6 +430,22 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/transactions" "^5.5.0" +"@ethersproject/contracts@^5.4.1": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.0.tgz#60f2cfc7addd99a865c6c8cfbbcec76297386067" + integrity sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw== + dependencies: + "@ethersproject/abi" "^5.6.0" + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/hash@5.5.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" @@ -383,6 +460,20 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/hash@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.0.tgz#d24446a5263e02492f9808baa99b6e2b4c3429a2" + integrity sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/hdnode@5.5.0", "@ethersproject/hdnode@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.5.0.tgz#4a04e28f41c546f7c978528ea1575206a200ddf6" @@ -401,6 +492,24 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" +"@ethersproject/hdnode@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.0.tgz#9dcbe8d629bbbcf144f2cae476337fe92d320998" + integrity sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + "@ethersproject/json-wallets@5.5.0", "@ethersproject/json-wallets@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz#dd522d4297e15bccc8e1427d247ec8376b60e325" @@ -420,6 +529,25 @@ aes-js "3.0.0" scrypt-js "3.0.1" +"@ethersproject/json-wallets@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz#4c2fc27f17e36c583e7a252fb938bc46f98891e5" + integrity sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + "@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" @@ -453,6 +581,13 @@ dependencies: "@ethersproject/logger" "^5.5.0" +"@ethersproject/networks@^5.6.0": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.1.tgz#7a21ed1f83e86121737b16841961ec99ccf5c9c7" + integrity sha512-b2rrupf3kCTcc3jr9xOWBuHylSFtbpJf79Ga7QR98ienU2UqGimPGEsYMgbI29KHJfA5Us89XwGVmxrlxmSrMg== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2@5.5.0", "@ethersproject/pbkdf2@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz#e25032cdf02f31505d47afbf9c3e000d95c4a050" @@ -461,6 +596,14 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/sha2" "^5.5.0" +"@ethersproject/pbkdf2@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz#04fcc2d7c6bff88393f5b4237d906a192426685a" + integrity sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/properties@5.5.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" @@ -468,6 +611,13 @@ dependencies: "@ethersproject/logger" "^5.5.0" +"@ethersproject/properties@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" + integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/providers@5.5.1", "@ethersproject/providers@^5.4.5": version "5.5.1" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.1.tgz#ba87e3c93219bbd2e2edf8b369873aee774abf04" @@ -493,6 +643,31 @@ bech32 "1.1.4" ws "7.4.6" +"@ethersproject/providers@^5.4.4": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.2.tgz#b9807b1c8c6f59fa2ee4b3cf6519724d07a9f422" + integrity sha512-6/EaFW/hNWz+224FXwl8+HdMRzVHt8DpPmu5MZaIQqx/K/ELnC9eY236SMV7mleCM3NnEArFwcAAxH5kUUgaRg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + bech32 "1.1.4" + ws "7.4.6" + "@ethersproject/random@5.5.0", "@ethersproject/random@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.0.tgz#305ed9e033ca537735365ac12eed88580b0f81f9" @@ -501,6 +676,14 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" +"@ethersproject/random@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.0.tgz#1505d1ab6a250e0ee92f436850fa3314b2cb5ae6" + integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/rlp@5.5.0", "@ethersproject/rlp@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" @@ -526,6 +709,15 @@ "@ethersproject/logger" "^5.5.0" hash.js "1.1.7" +"@ethersproject/sha2@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.0.tgz#364c4c11cc753bda36f31f001628706ebadb64d9" + integrity sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + hash.js "1.1.7" + "@ethersproject/signing-key@5.5.0", "@ethersproject/signing-key@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" @@ -538,6 +730,18 @@ elliptic "6.5.4" hash.js "1.1.7" +"@ethersproject/signing-key@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.0.tgz#4f02e3fb09e22b71e2e1d6dc4bcb5dafa69ce042" + integrity sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + "@ethersproject/solidity@5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.5.0.tgz#2662eb3e5da471b85a20531e420054278362f93f" @@ -550,6 +754,18 @@ "@ethersproject/sha2" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/solidity@^5.4.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.0.tgz#64657362a596bf7f5630bdc921c07dd78df06dc3" + integrity sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/strings@5.5.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" @@ -559,6 +775,15 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" +"@ethersproject/strings@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.0.tgz#9891b26709153d996bf1303d39a7f4bc047878fd" + integrity sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/transactions@5.5.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" @@ -574,6 +799,21 @@ "@ethersproject/rlp" "^5.5.0" "@ethersproject/signing-key" "^5.5.0" +"@ethersproject/transactions@^5.4.0", "@ethersproject/transactions@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.0.tgz#4b594d73a868ef6e1529a2f8f94a785e6791ae4e" + integrity sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/units@5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.5.0.tgz#104d02db5b5dc42cc672cc4587bafb87a95ee45e" @@ -604,6 +844,27 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" +"@ethersproject/wallet@^5.4.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.0.tgz#33d11a806d783864208f348709a5a3badac8e22a" + integrity sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/json-wallets" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + "@ethersproject/web@5.5.1", "@ethersproject/web@^5.5.0": version "5.5.1" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316" @@ -615,6 +876,17 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/web@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.0.tgz#4bf8b3cbc17055027e1a5dd3c357e37474eaaeb8" + integrity sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg== + dependencies: + "@ethersproject/base64" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/wordlists@5.5.0", "@ethersproject/wordlists@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.5.0.tgz#aac74963aa43e643638e5172353d931b347d584f" @@ -626,6 +898,17 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/wordlists@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.0.tgz#79e62c5276e091d8575f6930ba01a29218ded032" + integrity sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@humanwhocodes/config-array@^0.5.0": version "0.5.0" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" @@ -1029,7 +1312,7 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.2.tgz#4c62fae93eb479660c3bd93f9d24d561597a8281" integrity sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA== -"@types/qs@^6.2.31": +"@types/qs@^6.2.31", "@types/qs@^6.9.7": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== @@ -1576,6 +1859,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -2545,7 +2835,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2605,6 +2895,21 @@ chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.2" +chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -3027,6 +3332,13 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + decamelize@^1.1.1, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3285,6 +3597,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -3325,7 +3642,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.0, enquirer@^2.3.5: +enquirer@^2.3.0, enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -4552,11 +4869,23 @@ flow-stoplight@^1.0.0: resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha1-x7vxJN7ELJ0ZHPuUfQqXeN2YbAw= + dependencies: + imul "^1.0.0" + follow-redirects@^1.12.1: version "1.14.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd" integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A== +follow-redirects@^1.14.0: + version "1.14.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" + integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== + for-each@^0.3.3, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -4597,6 +4926,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -4644,6 +4982,15 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" + integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -5033,6 +5380,34 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hardhat-deploy@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.4.tgz#39b06d3b0ad25195071cc1f2f71649b1f9f030d0" + integrity sha512-BNMwWqaxrwb8XKrYzmCwnUzOSKzicUBk+fwd28doUNoAGFFh8kpoypkcHMzKDVdLhnamAardcfqJet73zrZoTA== + dependencies: + "@ethersproject/abi" "^5.4.0" + "@ethersproject/abstract-signer" "^5.4.1" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.1" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/contracts" "^5.4.1" + "@ethersproject/providers" "^5.4.4" + "@ethersproject/solidity" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/wallet" "^5.4.0" + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + hardhat-gas-reporter@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.6.tgz#699bc0bb96e8c962c7f136a1c1f29cd3c32d569e" @@ -5385,6 +5760,11 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk= + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -6455,6 +6835,11 @@ markdown-table@^1.1.3: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -6819,6 +7204,15 @@ multihashes@^0.4.15, multihashes@~0.4.15: multibase "^0.7.0" varint "^5.0.0" +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -7668,6 +8062,13 @@ qs@^6.4.0, qs@^6.7.0: dependencies: side-channel "^1.0.4" +qs@^6.9.4: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" diff --git a/packages/integration-tests/contracts/MultiDepositor.sol b/packages/integration-tests/contracts/MultiDepositor.sol index 50658b458097..cad7ebcab43f 100644 --- a/packages/integration-tests/contracts/MultiDepositor.sol +++ b/packages/integration-tests/contracts/MultiDepositor.sol @@ -13,9 +13,13 @@ interface DepositFeed { contract MultiDepositor { DepositFeed df = DepositFeed(0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001); + constructor(address _df) { + df = DepositFeed(_df); + } + function deposit(address to) external payable { for (uint i = 0; i < 3; i++) { - df.depositTransaction{ value: 1000000000 }( + df.depositTransaction{value : 1000000000}( to, 1000, 3000000, diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index c2bd35b97365..14656c6e1dd1 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -65,6 +65,7 @@ "typescript": "^4.3.5" }, "dependencies": { - "ts-mocha": "^9.0.2" + "ts-mocha": "^9.0.2", + "winston": "^3.7.2" } } diff --git a/packages/integration-tests/test/000_withdrawals.spec.ts b/packages/integration-tests/test/000_withdrawals.spec.ts new file mode 100644 index 000000000000..eac36382b3f6 --- /dev/null +++ b/packages/integration-tests/test/000_withdrawals.spec.ts @@ -0,0 +1,212 @@ +// Named 000 in order to run first since the output submitter +// can fall behind. + +/* Imports: External */ +import { BigNumber, constants, Contract, ContractReceipt, utils, Wallet } from 'ethers' +import { awaitCondition } from '@eth-optimism/core-utils' +import * as rlp from 'rlp' +import { Block } from '@ethersproject/abstract-provider' + +/* Imports: Internal */ +import { WITHDRAWER_ADDR } from './shared/constants' +import env from './shared/env' +import { expect } from './shared/setup' +import winston from 'winston' + +const withdrawerArtifact = require('../../contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json') +const l2OOracleArtifact = require('../../contracts/artifacts/contracts/L1/L2OutputOracle.sol/L2OutputOracle.json') +const counterArtifact = require('../artifacts/Counter.sol/Counter.json') +const multiDepositorArtifact = require('../artifacts/MultiDepositor.sol/MultiDepositor.json') + +describe('Withdrawals', () => { + let logger: winston.Logger + let portal: Contract + let withdrawer: Contract + + let recipient: Wallet + + before(async () => { + logger = env.logger + portal = env.optimismPortal + + withdrawer = new Contract( + WITHDRAWER_ADDR, + withdrawerArtifact.abi, + ) + }) + + describe('simple withdrawals', () => { + let nonce: BigNumber + let burnBlock: Block + let withdrawalHash: string + const value = utils.parseEther('1') + const gasLimit = 3000000 + + before(async function () { + this.timeout(60_000) + recipient = Wallet.createRandom().connect(env.l2Provider) + withdrawer = withdrawer.connect(recipient) + + logger.info('Generated new wallet', { + recipient: recipient.address, + }) + logger.info('Depositing to new address on L2') + let tx = await portal.connect(env.l1Wallet).depositTransaction( + recipient.address, + utils.parseEther('1.337'), + gasLimit, + false, + [], + { + value: utils.parseEther('1.337'), + }, + ) + await tx.wait() + + await awaitCondition(async () => { + const bal = await recipient.getBalance() + return bal.eq(tx.value) + }) + + logger.info('Transferring funds on L1') + tx = await env.l1Wallet.sendTransaction({ + to: recipient.address, + value, + }) + await tx.wait() + }) + + it('should create a withdrawal on L2', async () => { + nonce = await withdrawer.nonce() + const tx = await withdrawer.initiateWithdrawal( + recipient.address, + gasLimit, + [], + { + value, + }, + ) + const receipt: ContractReceipt = await tx.wait() + expect(receipt.events!.length).to.eq(1) + expect(receipt.events![0].args).to.deep.eq([ + nonce, + recipient.address, + recipient.address, + value, + BigNumber.from(gasLimit), + '0x', + ]) + + burnBlock = await env.l2Provider.getBlock(receipt.blockHash) + withdrawalHash = utils.keccak256( + utils.defaultAbiCoder.encode( + ['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes'], + [ + utils.hexZeroPad(nonce.toHexString(), 32), + recipient.address, + recipient.address, + value, + gasLimit, + '0x', + ], + ), + ) + }) + + it('should verify the withdrawal on L1', async function () { + recipient = recipient.connect(env.l1Provider) + portal = portal.connect(recipient) + const oracle = new Contract( + await portal.L2_ORACLE(), + l2OOracleArtifact.abi, + ).connect(recipient) + + const nextTimestamp = (await oracle.nextTimestamp()).toNumber() + const difference = burnBlock.timestamp - nextTimestamp + this.timeout(difference * 1000 + 60000) + + let targetOutputTimestamp: number + await awaitCondition( + async () => { + const nextTimestamp = (await oracle.nextTimestamp()).toNumber() + const difference = burnBlock.timestamp - nextTimestamp + logger.info('Waiting for timestamp', { + burnTS: burnBlock.timestamp, + nextTS: nextTimestamp, + difference: difference, + }) + // update this number on each iteration. When the condition is met, this will be the + // timestamp we want to prove against. + targetOutputTimestamp = nextTimestamp + return nextTimestamp > burnBlock.timestamp + }, + 2000, + 100, + ) + + let output: string + await awaitCondition(async () => { + output = await oracle.getL2Output(targetOutputTimestamp) + logger.info('Waiting for output submission', { + targetTimestamp: targetOutputTimestamp, + output, + }) + return output != constants.HashZero + }, 2000, 100) + + // suppress compilation errors since Typescript cannot detect + // that awaitCondition above will throw if it times out. + targetOutputTimestamp = targetOutputTimestamp! + output = output! + + const blocksSinceBurn = Math.floor((targetOutputTimestamp - burnBlock.timestamp) / 2) + const targetBlockNum = burnBlock.number + blocksSinceBurn + 1 + const targetBlockNumHex = utils.hexValue(targetBlockNum) + const storageSlot = '00'.repeat(31) + '01' // i.e the second variable declared in the contract + const proof = await env.l2Provider.send('eth_getProof', [ + WITHDRAWER_ADDR, + [utils.keccak256(withdrawalHash + storageSlot)], + targetBlockNumHex, + ]) + + const {stateRoot: targetStateRoot, hash: targetHash} = await env.l2Provider.send( + 'eth_getBlockByNumber', + [ + targetBlockNumHex, + false, + ], + ) + + const finalizationPeriod = (await portal.FINALIZATION_PERIOD()).toNumber() + logger.info('Waiting finalization period', { + seconds: finalizationPeriod, + }) + await new Promise((resolve) => setTimeout(resolve, finalizationPeriod * 1000)) + + logger.info('Finalizing withdrawal') + const initialBal = await recipient.getBalance() + const tx = await portal.finalizeWithdrawalTransaction( + nonce, + recipient.address, + recipient.address, + value, + gasLimit, + '0x', + targetOutputTimestamp, + { + version: constants.HashZero, + stateRoot: targetStateRoot, + withdrawerStorageRoot: proof.storageHash, + latestBlockhash: targetHash, + }, + rlp.encode(proof.storageProof[0].proof), + { + gasLimit, + }, + ) + await tx.wait() + const finalBal = await recipient.getBalance() + expect(finalBal.gte(initialBal)).to.be.true + }).timeout(180_000) + }) +}) diff --git a/packages/integration-tests/test/deposit.spec.ts b/packages/integration-tests/test/deposit.spec.ts index ac21253b44e7..4528bac8fcb1 100644 --- a/packages/integration-tests/test/deposit.spec.ts +++ b/packages/integration-tests/test/deposit.spec.ts @@ -3,22 +3,17 @@ import { Contract, ContractFactory, utils, Wallet } from 'ethers' import { awaitCondition } from '@eth-optimism/core-utils' /* Imports: Internal */ -import { DEPOSIT_FEED_ADDR } from './shared/constants' import { defaultTransactionFactory } from './shared/utils' import env from './shared/env' -const depositFeedArtifact = require('../../contracts/artifacts/contracts/L1/OptimismPortal.sol/OptimismPortal.json') const counterArtifact = require('../artifacts/Counter.sol/Counter.json') const multiDepositorArtifact = require('../artifacts/MultiDepositor.sol/MultiDepositor.json') describe('Deposits', () => { - let depositFeed: Contract + let portal: Contract before(() => { - depositFeed = new Contract( - DEPOSIT_FEED_ADDR, - depositFeedArtifact.abi, - ).connect(env.l1Wallet) + portal = env.optimismPortal.connect(env.l1Wallet) }) it('should deposit value', async () => { @@ -26,7 +21,7 @@ describe('Deposits', () => { const tx = defaultTransactionFactory() tx.value = utils.parseEther('1.337') tx.to = recipWallet.address - const result = await depositFeed.depositTransaction( + const result = await portal.depositTransaction( tx.to, tx.value, '3000000', @@ -51,7 +46,8 @@ describe('Deposits', () => { multiDepositorArtifact.abi, multiDepositorArtifact.bytecode.object, ).connect(env.l1Wallet) - const contract = await factory.deploy() + const contract = await factory.deploy(portal.address) + await contract.deployed() const tx = await contract.deposit(recipWallet.address, { value, }) @@ -61,7 +57,7 @@ describe('Deposits', () => { const bal = await recipWallet.getBalance() return bal.eq('3000') }) - }) + }).timeout(60_000) it.skip('should deposit a contract creation', async () => { const value = utils.parseEther('0.1') @@ -70,7 +66,7 @@ describe('Deposits', () => { counterArtifact.bytecode.object, ) const tx = await factory.getDeployTransaction() - const result = await depositFeed.depositTransaction( + const result = await portal.depositTransaction( `0x${'0'.repeat(40)}`, '0', '3000000', diff --git a/packages/integration-tests/test/rpc.spec.ts b/packages/integration-tests/test/rpc.spec.ts index 009f5a0e78e4..e1d4546ac13e 100644 --- a/packages/integration-tests/test/rpc.spec.ts +++ b/packages/integration-tests/test/rpc.spec.ts @@ -40,7 +40,9 @@ describe('RPCs', () => { counterArtifact.abi, counterArtifact.bytecode.object, ).connect(wallet) - const counter = await factory.deploy() + const counter = await factory.deploy({ + gasLimit: 1_000_000 + }) await counter.deployed() expect(await env.l2Provider.getCode(counter.address)).not.to.equal('0x') }) diff --git a/packages/integration-tests/test/shared/constants.ts b/packages/integration-tests/test/shared/constants.ts index 5e3b956088ba..164c1f163055 100644 --- a/packages/integration-tests/test/shared/constants.ts +++ b/packages/integration-tests/test/shared/constants.ts @@ -1 +1 @@ -export const DEPOSIT_FEED_ADDR = '0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001' \ No newline at end of file +export const WITHDRAWER_ADDR = '0x4200000000000000000000000000000000000016' \ No newline at end of file diff --git a/packages/integration-tests/test/shared/env.ts b/packages/integration-tests/test/shared/env.ts index df6993f226a9..7fd19b24a76f 100644 --- a/packages/integration-tests/test/shared/env.ts +++ b/packages/integration-tests/test/shared/env.ts @@ -1,10 +1,13 @@ /* Imports: External */ -import { Wallet, providers } from 'ethers' +import { Wallet, providers, Contract } from 'ethers' import { bool, cleanEnv, num, str } from 'envalid' +import dotenv from 'dotenv' +import winston, { info } from 'winston' + +const {combine, timestamp, printf, colorize, align} = winston.format /* Imports: Internal */ -import { asL2Provider } from '@eth-optimism/sdk' -import dotenv from 'dotenv' +const portalArtifact = require('../../../contracts/artifacts/contracts/L1/OptimismPortal.sol/OptimismPortal.json') dotenv.config() @@ -15,6 +18,8 @@ const procEnv = cleanEnv(process.env, { L2_URL: str({default: 'http://localhost:9545'}), L2_POLLING_INTERVAL: num({default: 1}), + OPTIMISM_PORTAL_ADDRESS: str(), + PRIVATE_KEY: str({ default: 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', @@ -26,6 +31,10 @@ const procEnv = cleanEnv(process.env, { MOCHA_BAIL: bool({ default: false, }), + + LOG_LEVEL: str({ + default: 'info', + }), }) /// Helper class for instantiating a test environment with a funded account @@ -38,6 +47,11 @@ export class OptimismEnv { l1Provider: providers.JsonRpcProvider l2Provider: providers.JsonRpcProvider + // Contracts + optimismPortal: Contract + + logger: winston.Logger + constructor() { const l1Provider = new providers.JsonRpcProvider(procEnv.L1_URL) l1Provider.pollingInterval = procEnv.L1_POLLING_INTERVAL @@ -48,11 +62,51 @@ export class OptimismEnv { const l1Wallet = new Wallet(procEnv.PRIVATE_KEY, l1Provider) const l2Wallet = new Wallet(procEnv.PRIVATE_KEY, l2Provider) + if (!procEnv.OPTIMISM_PORTAL_ADDRESS) { + throw new Error('Must define an OptimismPortal address.') + } + this.l1Wallet = l1Wallet this.l2Wallet = l2Wallet this.l1Provider = l1Provider this.l2Provider = l2Provider + this.optimismPortal = new Contract( + procEnv.OPTIMISM_PORTAL_ADDRESS, + portalArtifact.abi, + ) + this.logger = winston.createLogger({ + level: process.env.LOG_LEVEL || 'info', + format: combine( + { + transform(info) { + // @ts-ignore + const args = info[Symbol.for('splat')] + const meta = args ? args[0] : null + const suffix = meta ? ` ${keyify(meta)}` : '' + info.message = `${info.message}${suffix}` + return info + }, + }, + colorize({all: true}), + timestamp({ + format: 'YYYY-MM-DD hh:mm:ss.SSS A', + }), + align(), + printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`), + ), + transports: [new winston.transports.Stream({ + stream: process.stderr, + })], + }) + } +} + +const keyify = (kv: object): string => { + const out = [] + for (const [k, v] of Object.entries(kv)) { + out.push(`${k}=${v}`) } + return out.join(' ') } const env = new OptimismEnv() diff --git a/packages/integration-tests/yarn.lock b/packages/integration-tests/yarn.lock index a5de871a24ea..1a7f15aebb09 100644 --- a/packages/integration-tests/yarn.lock +++ b/packages/integration-tests/yarn.lock @@ -208,6 +208,11 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" resolved "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz" @@ -220,6 +225,15 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" +"@dabh/diagnostics@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== + dependencies: + colorspace "1.1.x" + enabled "2.0.x" + kuler "^2.0.0" + "@ensdomains/ens@^0.4.4": version "0.4.5" resolved "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz" @@ -1449,6 +1463,11 @@ async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: dependencies: lodash "^4.17.14" +async@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" + integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" @@ -2595,7 +2614,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -2614,11 +2633,35 @@ color-name@1.1.3: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.6.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.0.tgz#63b6ebd1bec11999d1df3a79a7569451ac2be8aa" + integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.1.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + +colorspace@1.1.x: + version "1.1.4" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" + integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== + dependencies: + color "^3.1.3" + text-hex "1.0.x" + combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" @@ -3157,6 +3200,11 @@ emoji-regex@^8.0.0: resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +enabled@2.0.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" @@ -4139,6 +4187,11 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fecha@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce" + integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q== + fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz" @@ -4265,6 +4318,11 @@ flow-stoplight@^1.0.0: resolved "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz" integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= +fn.name@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + for-each@^0.3.3, for-each@~0.3.3: version "0.3.3" resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" @@ -4944,6 +5002,11 @@ is-arrayish@^0.2.1: resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" @@ -5173,6 +5236,11 @@ is-stream@^1.0.0, is-stream@^1.0.1: resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" @@ -5508,6 +5576,11 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +kuler@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== + lcid@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" @@ -5733,6 +5806,17 @@ log-symbols@4.0.0: dependencies: chalk "^4.0.0" +logform@^2.3.2, logform@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" + integrity sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw== + dependencies: + "@colors/colors" "1.5.0" + fecha "^4.2.0" + ms "^2.1.1" + safe-stable-stringify "^2.3.1" + triple-beam "^1.3.0" + looper@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz" @@ -6466,6 +6550,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +one-time@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== + dependencies: + fn.name "1.x.x" + open@^7.4.2: version "7.4.2" resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz" @@ -7455,6 +7546,11 @@ safe-regex@^2.1.1: dependencies: regexp-tree "~0.1.1" +safe-stable-stringify@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73" + integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" @@ -7659,6 +7755,13 @@ simple-get@^3.0.3: once "^1.3.1" simple-concat "^1.0.0" +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + slash@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz" @@ -7840,6 +7943,11 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" @@ -8139,6 +8247,11 @@ testrpc@0.0.1: resolved "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz" integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" @@ -8251,6 +8364,11 @@ trim-right@^1.0.1: resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +triple-beam@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" + integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== + ts-essentials@^1.0.0: version "1.0.4" resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz" @@ -9033,6 +9151,31 @@ window-size@^0.2.0: resolved "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz" integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= +winston-transport@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" + integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== + dependencies: + logform "^2.3.2" + readable-stream "^3.6.0" + triple-beam "^1.3.0" + +winston@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.7.2.tgz#95b4eeddbec902b3db1424932ac634f887c400b1" + integrity sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng== + dependencies: + "@dabh/diagnostics" "^2.0.2" + async "^3.2.3" + is-stream "^2.0.0" + logform "^2.4.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.5.0" + word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" From 2f14c04bcb6d9cdf154182dc64e4933547b74703 Mon Sep 17 00:00:00 2001 From: inphi Date: Mon, 11 Apr 2022 16:34:56 -0400 Subject: [PATCH 477/585] go.mod: bump l2geth version --- go.mod | 2 +- go.sum | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7b9090e86f69..3d269f3c14bd 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220408020128-a9d9c835433e +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8 // For local debugging: //replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/go.sum b/go.sum index 37f415f0bddb..e0dda8d6e340 100644 --- a/go.sum +++ b/go.sum @@ -70,6 +70,7 @@ github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrf github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd/btcec/v2 v2.1.2 h1:YoYoC9J0jwfukodSBMzZYUVQ8PTiYg4BnOWiJVzTmLs= github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -136,8 +137,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220408020128-a9d9c835433e h1:jf42JF7YfNFqgzxkDFjq752UXMMvSFvsD6G8ezslQg0= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220408020128-a9d9c835433e/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8 h1:GrJtCdIozmrjTDrt/4PLwtVMkF3xYtgVVfnJb14gm+Y= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= 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= From 05136a32b9828b595dde47f767218dec53f19aa4 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 11 Apr 2022 15:38:04 -0700 Subject: [PATCH 478/585] opnode: Update and deploy contracts (#360) This is rather than hardcoding the contract bytecode. It slows down the e2e tests (by having to wait 1 L1 block for contracts to be ready), but it is more accurate to what occurs (and is now required as we initialize actions). This also pins the L2OutputOracle to v0.8.10 of solidity. --- l2os/bindings/l2oo/l2_output_oracle.go | 8 +- opnode/contracts/Makefile | 81 +- opnode/contracts/abis/DepositFeed.json | 93 - opnode/contracts/abis/L1Block.json | 104 - .../deposit/deposit_feed_deployed.go | 5 - opnode/contracts/deposit/deposit_feed_raw.go | 3850 ++++++++++++++++- opnode/contracts/doc.go | 2 +- .../l1block/l1_block_info_deployed.go | 2 +- opnode/contracts/l1block/l1_block_info_raw.go | 220 +- opnode/test/geth.go | 66 +- opnode/test/setup.go | 97 +- opnode/test/system_test.go | 107 +- .../contracts/contracts/L1/L2OutputOracle.sol | 2 +- 13 files changed, 4068 insertions(+), 569 deletions(-) delete mode 100644 opnode/contracts/abis/DepositFeed.json delete mode 100644 opnode/contracts/abis/L1Block.json delete mode 100644 opnode/contracts/deposit/deposit_feed_deployed.go diff --git a/l2os/bindings/l2oo/l2_output_oracle.go b/l2os/bindings/l2oo/l2_output_oracle.go index f3342fb55586..719741610fc3 100644 --- a/l2os/bindings/l2oo/l2_output_oracle.go +++ b/l2os/bindings/l2oo/l2_output_oracle.go @@ -30,8 +30,8 @@ var ( // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620012db380380620012db83398181016040528101906200003891906200025f565b620000586200004c620000b360201b60201c565b620000bb60201b60201c565b84608081815250508360a081815250508260026000428152602001908152602001600020819055508160c08181525050426001819055504260e08181525050620000a881620000bb60201b60201c565b5050505050620002e7565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b620001998162000184565b8114620001a557600080fd5b50565b600081519050620001b9816200018e565b92915050565b6000819050919050565b620001d481620001bf565b8114620001e057600080fd5b50565b600081519050620001f481620001c9565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022782620001fa565b9050919050565b62000239816200021a565b81146200024557600080fd5b50565b60008151905062000259816200022e565b92915050565b600080600080600060a086880312156200027e576200027d6200017f565b5b60006200028e88828901620001a8565b9550506020620002a188828901620001a8565b9450506040620002b488828901620001e3565b9350506060620002c788828901620001a8565b9250506080620002da8882890162000248565b9150509295509295909350565b60805160a05160c05160e051610f9762000344600039600081816102b30152818161033701526106af01526000818161036b01526106d3015260008181610316015261066e01526000818161058a01526106f70152610f976000f3fe6080604052600436106100a75760003560e01c806393991af31161006457806393991af31461019d578063a25ae557146101c8578063c5095d6814610205578063c90ec2da14610230578063e1a41bcf1461025b578063f2fde38b14610286576100a7565b806302e51345146100ac5780630c1952d3146100e95780632518810414610114578063357e951f14610130578063715018a61461015b5780638da5cb5b14610172575b600080fd5b3480156100b857600080fd5b506100d360048036038101906100ce9190610917565b6102af565b6040516100e09190610953565b60405180910390f35b3480156100f557600080fd5b506100fe610393565b60405161010b9190610953565b60405180910390f35b61012e600480360381019061012991906109a4565b610399565b005b34801561013c57600080fd5b50610145610586565b6040516101529190610953565b60405180910390f35b34801561016757600080fd5b506101706105bb565b005b34801561017e57600080fd5b50610187610643565b6040516101949190610a4c565b60405180910390f35b3480156101a957600080fd5b506101b261066c565b6040516101bf9190610953565b60405180910390f35b3480156101d457600080fd5b506101ef60048036038101906101ea9190610917565b610690565b6040516101fc9190610a76565b60405180910390f35b34801561021157600080fd5b5061021a6106ad565b6040516102279190610953565b60405180910390f35b34801561023c57600080fd5b506102456106d1565b6040516102529190610953565b60405180910390f35b34801561026757600080fd5b506102706106f5565b60405161027d9190610953565b60405180910390f35b34801561029257600080fd5b506102ad60048036038101906102a89190610abd565b610719565b005b60007f0000000000000000000000000000000000000000000000000000000000000000821015610314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030b90610b6d565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161036657610365610b8d565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6103a1610810565b73ffffffffffffffffffffffffffffffffffffffff166103bf610643565b73ffffffffffffffffffffffffffffffffffffffff1614610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040c90610c08565b60405180910390fd5b428310610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e90610c9a565b60405180910390fd5b61045f610586565b83146104a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049790610d2c565b60405180910390fd5b6000801b84036104e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104dc90610d98565b60405180910390fd5b6000801b82146105335781814014610532576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052990610e2a565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546105b69190610e79565b905090565b6105c3610810565b73ffffffffffffffffffffffffffffffffffffffff166105e1610643565b73ffffffffffffffffffffffffffffffffffffffff1614610637576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062e90610c08565b60405180910390fd5b6106416000610818565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610721610810565b73ffffffffffffffffffffffffffffffffffffffff1661073f610643565b73ffffffffffffffffffffffffffffffffffffffff1614610795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078c90610c08565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610804576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fb90610f41565b60405180910390fd5b61080d81610818565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6108f4816108e1565b81146108ff57600080fd5b50565b600081359050610911816108eb565b92915050565b60006020828403121561092d5761092c6108dc565b5b600061093b84828501610902565b91505092915050565b61094d816108e1565b82525050565b60006020820190506109686000830184610944565b92915050565b6000819050919050565b6109818161096e565b811461098c57600080fd5b50565b60008135905061099e81610978565b92915050565b600080600080608085870312156109be576109bd6108dc565b5b60006109cc8782880161098f565b94505060206109dd87828801610902565b93505060406109ee8782880161098f565b92505060606109ff87828801610902565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a3682610a0b565b9050919050565b610a4681610a2b565b82525050565b6000602082019050610a616000830184610a3d565b92915050565b610a708161096e565b82525050565b6000602082019050610a8b6000830184610a67565b92915050565b610a9a81610a2b565b8114610aa557600080fd5b50565b600081359050610ab781610a91565b92915050565b600060208284031215610ad357610ad26108dc565b5b6000610ae184828501610aa8565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610b57602983610aea565b9150610b6282610afb565b604082019050919050565b60006020820190508181036000830152610b8681610b4a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610bf2602083610aea565b9150610bfd82610bbc565b602082019050919050565b60006020820190508181036000830152610c2181610be5565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610c84602183610aea565b9150610c8f82610c28565b604082019050919050565b60006020820190508181036000830152610cb381610c77565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610d16602e83610aea565b9150610d2182610cba565b604082019050919050565b60006020820190508181036000830152610d4581610d09565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610d82601d83610aea565b9150610d8d82610d4c565b602082019050919050565b60006020820190508181036000830152610db181610d75565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610e14603983610aea565b9150610e1f82610db8565b604082019050919050565b60006020820190508181036000830152610e4381610e07565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e84826108e1565b9150610e8f836108e1565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ec457610ec3610e4a565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610f2b602683610aea565b9150610f3682610ecf565b604082019050919050565b60006020820190508181036000830152610f5a81610f1e565b905091905056fea264697066735822122084b8f35610306af12a2673f370ec439475d79fd28e3748169a331e30b3d14e6b64736f6c634300080d0033", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620012f2380380620012f2833981810160405281019062000038919062000260565b620000586200004c620000b460201b60201c565b620000bc60201b60201c565b85608081815250508460a081815250508360026000848152602001908152602001600020819055508260c08181525050816001819055508160e08181525050620000a881620000bc60201b60201c565b505050505050620002fc565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6200019a8162000185565b8114620001a657600080fd5b50565b600081519050620001ba816200018f565b92915050565b6000819050919050565b620001d581620001c0565b8114620001e157600080fd5b50565b600081519050620001f581620001ca565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022882620001fb565b9050919050565b6200023a816200021b565b81146200024657600080fd5b50565b6000815190506200025a816200022f565b92915050565b60008060008060008060c0878903121562000280576200027f62000180565b5b60006200029089828a01620001a9565b9650506020620002a389828a01620001a9565b9550506040620002b689828a01620001e4565b9450506060620002c989828a01620001a9565b9350506080620002dc89828a01620001a9565b92505060a0620002ef89828a0162000249565b9150509295509295509295565b60805160a05160c05160e051610f9962000359600039600081816102b30152818161033701526106b001526000818161036b01526106d4015260008181610316015261066f01526000818161058b01526106f80152610f996000f3fe6080604052600436106100a75760003560e01c806393991af31161006457806393991af31461019d578063a25ae557146101c8578063c5095d6814610205578063c90ec2da14610230578063e1a41bcf1461025b578063f2fde38b14610286576100a7565b806302e51345146100ac5780630c1952d3146100e95780632518810414610114578063357e951f14610130578063715018a61461015b5780638da5cb5b14610172575b600080fd5b3480156100b857600080fd5b506100d360048036038101906100ce9190610919565b6102af565b6040516100e09190610955565b60405180910390f35b3480156100f557600080fd5b506100fe610393565b60405161010b9190610955565b60405180910390f35b61012e600480360381019061012991906109a6565b610399565b005b34801561013c57600080fd5b50610145610587565b6040516101529190610955565b60405180910390f35b34801561016757600080fd5b506101706105bc565b005b34801561017e57600080fd5b50610187610644565b6040516101949190610a4e565b60405180910390f35b3480156101a957600080fd5b506101b261066d565b6040516101bf9190610955565b60405180910390f35b3480156101d457600080fd5b506101ef60048036038101906101ea9190610919565b610691565b6040516101fc9190610a78565b60405180910390f35b34801561021157600080fd5b5061021a6106ae565b6040516102279190610955565b60405180910390f35b34801561023c57600080fd5b506102456106d2565b6040516102529190610955565b60405180910390f35b34801561026757600080fd5b506102706106f6565b60405161027d9190610955565b60405180910390f35b34801561029257600080fd5b506102ad60048036038101906102a89190610abf565b61071a565b005b60007f0000000000000000000000000000000000000000000000000000000000000000821015610314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030b90610b6f565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161036657610365610b8f565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6103a1610812565b73ffffffffffffffffffffffffffffffffffffffff166103bf610644565b73ffffffffffffffffffffffffffffffffffffffff1614610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040c90610c0a565b60405180910390fd5b428310610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e90610c9c565b60405180910390fd5b61045f610587565b83146104a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049790610d2e565b60405180910390fd5b6000801b8414156104e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104dd90610d9a565b60405180910390fd5b6000801b82146105345781814014610533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052a90610e2c565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546105b79190610e7b565b905090565b6105c4610812565b73ffffffffffffffffffffffffffffffffffffffff166105e2610644565b73ffffffffffffffffffffffffffffffffffffffff1614610638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062f90610c0a565b60405180910390fd5b610642600061081a565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610722610812565b73ffffffffffffffffffffffffffffffffffffffff16610740610644565b73ffffffffffffffffffffffffffffffffffffffff1614610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078d90610c0a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fd90610f43565b60405180910390fd5b61080f8161081a565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6108f6816108e3565b811461090157600080fd5b50565b600081359050610913816108ed565b92915050565b60006020828403121561092f5761092e6108de565b5b600061093d84828501610904565b91505092915050565b61094f816108e3565b82525050565b600060208201905061096a6000830184610946565b92915050565b6000819050919050565b61098381610970565b811461098e57600080fd5b50565b6000813590506109a08161097a565b92915050565b600080600080608085870312156109c0576109bf6108de565b5b60006109ce87828801610991565b94505060206109df87828801610904565b93505060406109f087828801610991565b9250506060610a0187828801610904565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a3882610a0d565b9050919050565b610a4881610a2d565b82525050565b6000602082019050610a636000830184610a3f565b92915050565b610a7281610970565b82525050565b6000602082019050610a8d6000830184610a69565b92915050565b610a9c81610a2d565b8114610aa757600080fd5b50565b600081359050610ab981610a93565b92915050565b600060208284031215610ad557610ad46108de565b5b6000610ae384828501610aaa565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610b59602983610aec565b9150610b6482610afd565b604082019050919050565b60006020820190508181036000830152610b8881610b4c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610bf4602083610aec565b9150610bff82610bbe565b602082019050919050565b60006020820190508181036000830152610c2381610be7565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610c86602183610aec565b9150610c9182610c2a565b604082019050919050565b60006020820190508181036000830152610cb581610c79565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610d18602e83610aec565b9150610d2382610cbc565b604082019050919050565b60006020820190508181036000830152610d4781610d0b565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610d84601d83610aec565b9150610d8f82610d4e565b602082019050919050565b60006020820190508181036000830152610db381610d77565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610e16603983610aec565b9150610e2182610dba565b604082019050919050565b60006020820190508181036000830152610e4581610e09565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e86826108e3565b9150610e91836108e3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ec657610ec5610e4c565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610f2d602683610aec565b9150610f3882610ed1565b604082019050919050565b60006020820190508181036000830152610f5c81610f20565b905091905056fea2646970667358221220980520f45819a707ff13a09b23bdace7cce468e4b8e92e7fd2f480d56c85cb7664736f6c634300080a0033", } // L2OutputOracleABI is the input ABI used to generate the binding from. @@ -43,7 +43,7 @@ var L2OutputOracleABI = L2OutputOracleMetaData.ABI var L2OutputOracleBin = L2OutputOracleMetaData.Bin // DeployL2OutputOracle deploys a new Ethereum contract, binding an instance of L2OutputOracle to it. -func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionInterval *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int, sequencer common.Address) (common.Address, *types.Transaction, *L2OutputOracle, error) { +func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionInterval *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int, _startingBlockTimestamp *big.Int, sequencer common.Address) (common.Address, *types.Transaction, *L2OutputOracle, error) { parsed, err := L2OutputOracleMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -52,7 +52,7 @@ func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L2OutputOracleBin), backend, _submissionInterval, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks, sequencer) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L2OutputOracleBin), backend, _submissionInterval, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks, _startingBlockTimestamp, sequencer) if err != nil { return common.Address{}, nil, nil, err } diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index ed6700cd96a6..eb1b153acdd4 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -1,56 +1,49 @@ SHELL := /bin/bash -CONTRACTS_PATH := "../../packages/contracts/artifacts/contracts" +CONTRACTS_PATH := "../../packages/contracts/" +OPTIMISM_PORTAL := ../../packages/contracts/contracts/L1/OptimismPortal.sol +L1_BLOCK_INFO := ../../packages/contracts/contracts/L2/L1Block.sol -binding: abi - $(eval temp := $(shell mktemp)) - cat abis/DepositFeed.json \ - | jq -r .bytecode > $(temp) +bindings: bindings-l1-block-info bindings-optimism-portal deployed-bin-l1-block-info - cat abis/DepositFeed.json \ - | jq .abi \ - | abigen --pkg deposit \ - --abi - \ - --out deposit/deposit_feed_raw.go \ - --type deposit \ - --bin $(temp) - - $(eval deployedBytecode := $(shell cat abis/DepositFeed.json | jq -r .deployedBytecode)) - echo "// Code generated - DO NOT EDIT." > deposit/deposit_feed_deployed.go - echo "// This file is a generated binding and any manual changes will be lost." >> deposit/deposit_feed_deployed.go - echo "package deposit" >> deposit/deposit_feed_deployed.go - echo "var DepositDeployedBin = \"$(deployedBytecode)\"" >> deposit/deposit_feed_deployed.go - gofmt -s -w deposit/deposit_feed_deployed.go - - rm $(temp) - - $(eval temp := $(shell mktemp)) - - cat abis/L1Block.json \ - | jq -r .bytecode > $(temp) - cat abis/L1Block.json \ - | jq .abi \ - | abigen --pkg l1block \ - --abi - \ - --out l1block/l1_block_info_raw.go \ - --type l1block \ - --bin $(temp) - - $(eval deployedBytecode := $(shell cat abis/L1Block.json | jq -r .deployedBytecode)) +# Split up b/c I don't know how to include this step in the L1 Block Info Bindings +# What is occuring is that the `temp` variable is hard to pull into the `eval` +deployed-bin-l1-block-info: bindings-l1-block-info + $(eval deployedBytecode := $(shell cat bin/l1block_deployed.hex)) echo "// Code generated - DO NOT EDIT." > l1block/l1_block_info_deployed.go echo "// This file is a generated binding and any manual changes will be lost." >> l1block/l1_block_info_deployed.go echo "package l1block" >> l1block/l1_block_info_deployed.go echo "var L1blockDeployedBin = \"$(deployedBytecode)\"" >> l1block/l1_block_info_deployed.go gofmt -s -w l1block/l1_block_info_deployed.go - rm $(temp) - -abi: - cat $(CONTRACTS_PATH)/L1/DepositFeed.sol/DepositFeed.json \ - | jq '{abi,bytecode,deployedBytecode}' \ - > abis/DepositFeed.json - cat $(CONTRACTS_PATH)/L2/L1Block.sol/L1Block.json \ - | jq '{abi,bytecode,deployedBytecode}' \ - > abis/L1Block.json +bindings-l1-block-info: + $(eval temp := $(shell mktemp -d)) + solc \ + --abi $(L1_BLOCK_INFO) \ + --bin $(L1_BLOCK_INFO) \ + --combined-json abi,bin,bin-runtime \ + --allow-paths $(CONTRACTS_PATH) \ + -o $(temp) + abigen \ + --combined-json $(temp)/combined.json \ + --pkg l1block \ + --type l1block \ + --out ./l1block/l1_block_info_raw.go + cat $(temp)/combined.json | jq -r ".contracts | with_entries(select(.key | match(\"L1Block\")))[] | .\"bin-runtime\"" > bin/l1block_deployed.hex + + +bindings-optimism-portal: + $(eval temp := $(shell mktemp -d)) + solc \ + --abi $(OPTIMISM_PORTAL) \ + --bin $(OPTIMISM_PORTAL) \ + --combined-json abi,bin,bin-runtime \ + --allow-paths $(CONTRACTS_PATH) \ + -o $(temp) + abigen \ + --combined-json $(temp)/combined.json \ + --pkg deposit \ + --type deposit \ + --out ./deposit/deposit_feed_raw.go \ No newline at end of file diff --git a/opnode/contracts/abis/DepositFeed.json b/opnode/contracts/abis/DepositFeed.json deleted file mode 100644 index 8208be7f61fc..000000000000 --- a/opnode/contracts/abis/DepositFeed.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "name": "NonZeroCreationTarget", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "mint", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isCreation", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "TransactionDeposited", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasLimit", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "_isCreation", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "depositTransaction", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b5061056a806100206000396000f3fe60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033", - "deployedBytecode": "0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" -} diff --git a/opnode/contracts/abis/L1Block.json b/opnode/contracts/abis/L1Block.json deleted file mode 100644 index 9460fc2c628b..000000000000 --- a/opnode/contracts/abis/L1Block.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "name": "OnlyDepositor", - "type": "error" - }, - { - "inputs": [], - "name": "DEPOSITOR_ACCOUNT", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "basefee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "number", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_number", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_basefee", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_hash", - "type": "bytes32" - } - ], - "name": "setL1BlockValues", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033" -} diff --git a/opnode/contracts/deposit/deposit_feed_deployed.go b/opnode/contracts/deposit/deposit_feed_deployed.go deleted file mode 100644 index 61f7cf8246bf..000000000000 --- a/opnode/contracts/deposit/deposit_feed_deployed.go +++ /dev/null @@ -1,5 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. -package deposit - -var DepositDeployedBin = "0x60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033" diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/opnode/contracts/deposit/deposit_feed_raw.go index 076a59adca75..a94c2ee60513 100644 --- a/opnode/contracts/deposit/deposit_feed_raw.go +++ b/opnode/contracts/deposit/deposit_feed_raw.go @@ -28,23 +28,31 @@ var ( _ = event.NewSubscription ) -// DepositMetaData contains all meta data concerning the Deposit contract. -var DepositMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061056a806100206000396000f3fe60806040526004361061001e5760003560e01c8063fa92670c14610023575b600080fd5b61003d6004803603810190610038919061039d565b61003f565b005b8180156100795750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156100b0576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010257731111000000000000000000000000000000001111330190505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516101679594939291906104da565b60405180910390a3505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101b68261018b565b9050919050565b6101c6816101ab565b81146101d157600080fd5b50565b6000813590506101e3816101bd565b92915050565b6000819050919050565b6101fc816101e9565b811461020757600080fd5b50565b600081359050610219816101f3565b92915050565b60008115159050919050565b6102348161021f565b811461023f57600080fd5b50565b6000813590506102518161022b565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102aa82610261565b810181811067ffffffffffffffff821117156102c9576102c8610272565b5b80604052505050565b60006102dc610177565b90506102e882826102a1565b919050565b600067ffffffffffffffff82111561030857610307610272565b5b61031182610261565b9050602081019050919050565b82818337600083830152505050565b600061034061033b846102ed565b6102d2565b90508281526020810184848401111561035c5761035b61025c565b5b61036784828561031e565b509392505050565b600082601f83011261038457610383610257565b5b813561039484826020860161032d565b91505092915050565b600080600080600060a086880312156103b9576103b8610181565b5b60006103c7888289016101d4565b95505060206103d88882890161020a565b94505060406103e98882890161020a565b93505060606103fa88828901610242565b925050608086013567ffffffffffffffff81111561041b5761041a610186565b5b6104278882890161036f565b9150509295509295909350565b61043d816101e9565b82525050565b61044c8161021f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561048c578082015181840152602081019050610471565b8381111561049b576000848401525b50505050565b60006104ac82610452565b6104b6818561045d565b93506104c681856020860161046e565b6104cf81610261565b840191505092915050565b600060a0820190506104ef6000830188610434565b6104fc6020830187610434565b6105096040830186610434565b6105166060830185610443565b818103608083015261052881846104a1565b9050969550505050505056fea264697066735822122025140b7451be29e927d33c9ad0e2dd3744f824f592e16cb35f009b57442e2c9364736f6c634300080a0033", +// WithdrawalVerifierOutputRootProof is an auto generated low-level Go binding around an user-defined struct. +type WithdrawalVerifierOutputRootProof struct { + Version [32]byte + StateRoot [32]byte + WithdrawerStorageRoot [32]byte + LatestBlockhash [32]byte +} + +// AddressAliasHelperMetaData contains all meta data concerning the AddressAliasHelper contract. +var AddressAliasHelperMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c7fa45f5503f62c2292b9c4a466d09aacd158cdc3685a7753531ac6bf8bda5ef64736f6c634300080a0033", } -// DepositABI is the input ABI used to generate the binding from. -// Deprecated: Use DepositMetaData.ABI instead. -var DepositABI = DepositMetaData.ABI +// AddressAliasHelperABI is the input ABI used to generate the binding from. +// Deprecated: Use AddressAliasHelperMetaData.ABI instead. +var AddressAliasHelperABI = AddressAliasHelperMetaData.ABI -// DepositBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use DepositMetaData.Bin instead. -var DepositBin = DepositMetaData.Bin +// AddressAliasHelperBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AddressAliasHelperMetaData.Bin instead. +var AddressAliasHelperBin = AddressAliasHelperMetaData.Bin -// DeployDeposit deploys a new Ethereum contract, binding an instance of Deposit to it. -func DeployDeposit(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Deposit, error) { - parsed, err := DepositMetaData.GetAbi() +// DeployAddressAliasHelper deploys a new Ethereum contract, binding an instance of AddressAliasHelper to it. +func DeployAddressAliasHelper(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *AddressAliasHelper, error) { + parsed, err := AddressAliasHelperMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -52,111 +60,413 @@ func DeployDeposit(auth *bind.TransactOpts, backend bind.ContractBackend) (commo return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(DepositBin), backend) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AddressAliasHelperBin), backend) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &Deposit{DepositCaller: DepositCaller{contract: contract}, DepositTransactor: DepositTransactor{contract: contract}, DepositFilterer: DepositFilterer{contract: contract}}, nil + return address, tx, &AddressAliasHelper{AddressAliasHelperCaller: AddressAliasHelperCaller{contract: contract}, AddressAliasHelperTransactor: AddressAliasHelperTransactor{contract: contract}, AddressAliasHelperFilterer: AddressAliasHelperFilterer{contract: contract}}, nil +} + +// AddressAliasHelper is an auto generated Go binding around an Ethereum contract. +type AddressAliasHelper struct { + AddressAliasHelperCaller // Read-only binding to the contract + AddressAliasHelperTransactor // Write-only binding to the contract + AddressAliasHelperFilterer // Log filterer for contract events +} + +// AddressAliasHelperCaller is an auto generated read-only Go binding around an Ethereum contract. +type AddressAliasHelperCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AddressAliasHelperTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AddressAliasHelperTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AddressAliasHelperFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AddressAliasHelperFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AddressAliasHelperSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AddressAliasHelperSession struct { + Contract *AddressAliasHelper // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AddressAliasHelperCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AddressAliasHelperCallerSession struct { + Contract *AddressAliasHelperCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AddressAliasHelperTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AddressAliasHelperTransactorSession struct { + Contract *AddressAliasHelperTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AddressAliasHelperRaw is an auto generated low-level Go binding around an Ethereum contract. +type AddressAliasHelperRaw struct { + Contract *AddressAliasHelper // Generic contract binding to access the raw methods on +} + +// AddressAliasHelperCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AddressAliasHelperCallerRaw struct { + Contract *AddressAliasHelperCaller // Generic read-only contract binding to access the raw methods on +} + +// AddressAliasHelperTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AddressAliasHelperTransactorRaw struct { + Contract *AddressAliasHelperTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAddressAliasHelper creates a new instance of AddressAliasHelper, bound to a specific deployed contract. +func NewAddressAliasHelper(address common.Address, backend bind.ContractBackend) (*AddressAliasHelper, error) { + contract, err := bindAddressAliasHelper(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AddressAliasHelper{AddressAliasHelperCaller: AddressAliasHelperCaller{contract: contract}, AddressAliasHelperTransactor: AddressAliasHelperTransactor{contract: contract}, AddressAliasHelperFilterer: AddressAliasHelperFilterer{contract: contract}}, nil +} + +// NewAddressAliasHelperCaller creates a new read-only instance of AddressAliasHelper, bound to a specific deployed contract. +func NewAddressAliasHelperCaller(address common.Address, caller bind.ContractCaller) (*AddressAliasHelperCaller, error) { + contract, err := bindAddressAliasHelper(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AddressAliasHelperCaller{contract: contract}, nil +} + +// NewAddressAliasHelperTransactor creates a new write-only instance of AddressAliasHelper, bound to a specific deployed contract. +func NewAddressAliasHelperTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressAliasHelperTransactor, error) { + contract, err := bindAddressAliasHelper(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AddressAliasHelperTransactor{contract: contract}, nil +} + +// NewAddressAliasHelperFilterer creates a new log filterer instance of AddressAliasHelper, bound to a specific deployed contract. +func NewAddressAliasHelperFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressAliasHelperFilterer, error) { + contract, err := bindAddressAliasHelper(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AddressAliasHelperFilterer{contract: contract}, nil +} + +// bindAddressAliasHelper binds a generic wrapper to an already deployed contract. +func bindAddressAliasHelper(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AddressAliasHelperABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_AddressAliasHelper *AddressAliasHelperRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AddressAliasHelper.Contract.AddressAliasHelperCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_AddressAliasHelper *AddressAliasHelperRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AddressAliasHelper.Contract.AddressAliasHelperTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AddressAliasHelper *AddressAliasHelperRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AddressAliasHelper.Contract.AddressAliasHelperTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_AddressAliasHelper *AddressAliasHelperCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AddressAliasHelper.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_AddressAliasHelper *AddressAliasHelperTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AddressAliasHelper.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AddressAliasHelper *AddressAliasHelperTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AddressAliasHelper.Contract.contract.Transact(opts, method, params...) +} + +// ContextMetaData contains all meta data concerning the Context contract. +var ContextMetaData = &bind.MetaData{ + ABI: "[]", } -// Deposit is an auto generated Go binding around an Ethereum contract. -type Deposit struct { - DepositCaller // Read-only binding to the contract - DepositTransactor // Write-only binding to the contract - DepositFilterer // Log filterer for contract events +// ContextABI is the input ABI used to generate the binding from. +// Deprecated: Use ContextMetaData.ABI instead. +var ContextABI = ContextMetaData.ABI + +// Context is an auto generated Go binding around an Ethereum contract. +type Context struct { + ContextCaller // Read-only binding to the contract + ContextTransactor // Write-only binding to the contract + ContextFilterer // Log filterer for contract events } -// DepositCaller is an auto generated read-only Go binding around an Ethereum contract. -type DepositCaller struct { +// ContextCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContextCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// DepositTransactor is an auto generated write-only Go binding around an Ethereum contract. -type DepositTransactor struct { +// ContextTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContextTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// DepositFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type DepositFilterer struct { +// ContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContextFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// DepositSession is an auto generated Go binding around an Ethereum contract, +// ContextSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. -type DepositSession struct { - Contract *Deposit // Generic contract binding to set the session for +type ContextSession struct { + Contract *Context // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// DepositCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// ContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. -type DepositCallerSession struct { - Contract *DepositCaller // Generic contract caller binding to set the session for +type ContextCallerSession struct { + Contract *ContextCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } -// DepositTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// ContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. -type DepositTransactorSession struct { - Contract *DepositTransactor // Generic contract transactor binding to set the session for +type ContextTransactorSession struct { + Contract *ContextTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// DepositRaw is an auto generated low-level Go binding around an Ethereum contract. -type DepositRaw struct { - Contract *Deposit // Generic contract binding to access the raw methods on +// ContextRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContextRaw struct { + Contract *Context // Generic contract binding to access the raw methods on +} + +// ContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContextCallerRaw struct { + Contract *ContextCaller // Generic read-only contract binding to access the raw methods on +} + +// ContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContextTransactorRaw struct { + Contract *ContextTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewContext creates a new instance of Context, bound to a specific deployed contract. +func NewContext(address common.Address, backend bind.ContractBackend) (*Context, error) { + contract, err := bindContext(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Context{ContextCaller: ContextCaller{contract: contract}, ContextTransactor: ContextTransactor{contract: contract}, ContextFilterer: ContextFilterer{contract: contract}}, nil +} + +// NewContextCaller creates a new read-only instance of Context, bound to a specific deployed contract. +func NewContextCaller(address common.Address, caller bind.ContractCaller) (*ContextCaller, error) { + contract, err := bindContext(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContextCaller{contract: contract}, nil +} + +// NewContextTransactor creates a new write-only instance of Context, bound to a specific deployed contract. +func NewContextTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextTransactor, error) { + contract, err := bindContext(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContextTransactor{contract: contract}, nil +} + +// NewContextFilterer creates a new log filterer instance of Context, bound to a specific deployed contract. +func NewContextFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextFilterer, error) { + contract, err := bindContext(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContextFilterer{contract: contract}, nil +} + +// bindContext binds a generic wrapper to an already deployed contract. +func bindContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ContextABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.ContextCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.contract.Transact(opts, method, params...) +} + +// DepositFeedMetaData contains all meta data concerning the DepositFeed contract. +var DepositFeedMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", +} + +// DepositFeedABI is the input ABI used to generate the binding from. +// Deprecated: Use DepositFeedMetaData.ABI instead. +var DepositFeedABI = DepositFeedMetaData.ABI + +// DepositFeed is an auto generated Go binding around an Ethereum contract. +type DepositFeed struct { + DepositFeedCaller // Read-only binding to the contract + DepositFeedTransactor // Write-only binding to the contract + DepositFeedFilterer // Log filterer for contract events +} + +// DepositFeedCaller is an auto generated read-only Go binding around an Ethereum contract. +type DepositFeedCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DepositFeedTransactor is an auto generated write-only Go binding around an Ethereum contract. +type DepositFeedTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DepositFeedFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type DepositFeedFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DepositFeedSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type DepositFeedSession struct { + Contract *DepositFeed // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DepositFeedCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type DepositFeedCallerSession struct { + Contract *DepositFeedCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// DepositFeedTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type DepositFeedTransactorSession struct { + Contract *DepositFeedTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DepositFeedRaw is an auto generated low-level Go binding around an Ethereum contract. +type DepositFeedRaw struct { + Contract *DepositFeed // Generic contract binding to access the raw methods on } -// DepositCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type DepositCallerRaw struct { - Contract *DepositCaller // Generic read-only contract binding to access the raw methods on +// DepositFeedCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type DepositFeedCallerRaw struct { + Contract *DepositFeedCaller // Generic read-only contract binding to access the raw methods on } -// DepositTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type DepositTransactorRaw struct { - Contract *DepositTransactor // Generic write-only contract binding to access the raw methods on +// DepositFeedTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type DepositFeedTransactorRaw struct { + Contract *DepositFeedTransactor // Generic write-only contract binding to access the raw methods on } -// NewDeposit creates a new instance of Deposit, bound to a specific deployed contract. -func NewDeposit(address common.Address, backend bind.ContractBackend) (*Deposit, error) { - contract, err := bindDeposit(address, backend, backend, backend) +// NewDepositFeed creates a new instance of DepositFeed, bound to a specific deployed contract. +func NewDepositFeed(address common.Address, backend bind.ContractBackend) (*DepositFeed, error) { + contract, err := bindDepositFeed(address, backend, backend, backend) if err != nil { return nil, err } - return &Deposit{DepositCaller: DepositCaller{contract: contract}, DepositTransactor: DepositTransactor{contract: contract}, DepositFilterer: DepositFilterer{contract: contract}}, nil + return &DepositFeed{DepositFeedCaller: DepositFeedCaller{contract: contract}, DepositFeedTransactor: DepositFeedTransactor{contract: contract}, DepositFeedFilterer: DepositFeedFilterer{contract: contract}}, nil } -// NewDepositCaller creates a new read-only instance of Deposit, bound to a specific deployed contract. -func NewDepositCaller(address common.Address, caller bind.ContractCaller) (*DepositCaller, error) { - contract, err := bindDeposit(address, caller, nil, nil) +// NewDepositFeedCaller creates a new read-only instance of DepositFeed, bound to a specific deployed contract. +func NewDepositFeedCaller(address common.Address, caller bind.ContractCaller) (*DepositFeedCaller, error) { + contract, err := bindDepositFeed(address, caller, nil, nil) if err != nil { return nil, err } - return &DepositCaller{contract: contract}, nil + return &DepositFeedCaller{contract: contract}, nil } -// NewDepositTransactor creates a new write-only instance of Deposit, bound to a specific deployed contract. -func NewDepositTransactor(address common.Address, transactor bind.ContractTransactor) (*DepositTransactor, error) { - contract, err := bindDeposit(address, nil, transactor, nil) +// NewDepositFeedTransactor creates a new write-only instance of DepositFeed, bound to a specific deployed contract. +func NewDepositFeedTransactor(address common.Address, transactor bind.ContractTransactor) (*DepositFeedTransactor, error) { + contract, err := bindDepositFeed(address, nil, transactor, nil) if err != nil { return nil, err } - return &DepositTransactor{contract: contract}, nil + return &DepositFeedTransactor{contract: contract}, nil } -// NewDepositFilterer creates a new log filterer instance of Deposit, bound to a specific deployed contract. -func NewDepositFilterer(address common.Address, filterer bind.ContractFilterer) (*DepositFilterer, error) { - contract, err := bindDeposit(address, nil, nil, filterer) +// NewDepositFeedFilterer creates a new log filterer instance of DepositFeed, bound to a specific deployed contract. +func NewDepositFeedFilterer(address common.Address, filterer bind.ContractFilterer) (*DepositFeedFilterer, error) { + contract, err := bindDepositFeed(address, nil, nil, filterer) if err != nil { return nil, err } - return &DepositFilterer{contract: contract}, nil + return &DepositFeedFilterer{contract: contract}, nil } -// bindDeposit binds a generic wrapper to an already deployed contract. -func bindDeposit(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(DepositABI)) +// bindDepositFeed binds a generic wrapper to an already deployed contract. +func bindDepositFeed(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(DepositFeedABI)) if err != nil { return nil, err } @@ -167,64 +477,64 @@ func bindDeposit(address common.Address, caller bind.ContractCaller, transactor // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_Deposit *DepositRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Deposit.Contract.DepositCaller.contract.Call(opts, result, method, params...) +func (_DepositFeed *DepositFeedRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DepositFeed.Contract.DepositFeedCaller.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_Deposit *DepositRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Deposit.Contract.DepositTransactor.contract.Transfer(opts) +func (_DepositFeed *DepositFeedRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DepositFeed.Contract.DepositFeedTransactor.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_Deposit *DepositRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Deposit.Contract.DepositTransactor.contract.Transact(opts, method, params...) +func (_DepositFeed *DepositFeedRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DepositFeed.Contract.DepositFeedTransactor.contract.Transact(opts, method, params...) } // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_Deposit *DepositCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Deposit.Contract.contract.Call(opts, result, method, params...) +func (_DepositFeed *DepositFeedCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DepositFeed.Contract.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_Deposit *DepositTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Deposit.Contract.contract.Transfer(opts) +func (_DepositFeed *DepositFeedTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DepositFeed.Contract.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_Deposit *DepositTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Deposit.Contract.contract.Transact(opts, method, params...) +func (_DepositFeed *DepositFeedTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DepositFeed.Contract.contract.Transact(opts, method, params...) } // DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. // // Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_Deposit *DepositTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _Deposit.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) +func (_DepositFeed *DepositFeedTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _DepositFeed.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) } // DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. // // Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_Deposit *DepositSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _Deposit.Contract.DepositTransaction(&_Deposit.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +func (_DepositFeed *DepositFeedSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _DepositFeed.Contract.DepositTransaction(&_DepositFeed.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) } // DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. // // Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_Deposit *DepositTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _Deposit.Contract.DepositTransaction(&_Deposit.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +func (_DepositFeed *DepositFeedTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _DepositFeed.Contract.DepositTransaction(&_DepositFeed.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) } -// DepositTransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the Deposit contract. -type DepositTransactionDepositedIterator struct { - Event *DepositTransactionDeposited // Event containing the contract specifics and raw log +// DepositFeedTransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the DepositFeed contract. +type DepositFeedTransactionDepositedIterator struct { + Event *DepositFeedTransactionDeposited // 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 @@ -238,7 +548,7 @@ type DepositTransactionDepositedIterator struct { // 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 *DepositTransactionDepositedIterator) Next() bool { +func (it *DepositFeedTransactionDepositedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -247,7 +557,7 @@ func (it *DepositTransactionDepositedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(DepositTransactionDeposited) + it.Event = new(DepositFeedTransactionDeposited) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -262,7 +572,7 @@ func (it *DepositTransactionDepositedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(DepositTransactionDeposited) + it.Event = new(DepositFeedTransactionDeposited) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -278,19 +588,19 @@ func (it *DepositTransactionDepositedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *DepositTransactionDepositedIterator) Error() error { +func (it *DepositFeedTransactionDepositedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *DepositTransactionDepositedIterator) Close() error { +func (it *DepositFeedTransactionDepositedIterator) Close() error { it.sub.Unsubscribe() return nil } -// DepositTransactionDeposited represents a TransactionDeposited event raised by the Deposit contract. -type DepositTransactionDeposited struct { +// DepositFeedTransactionDeposited represents a TransactionDeposited event raised by the DepositFeed contract. +type DepositFeedTransactionDeposited struct { From common.Address To common.Address Mint *big.Int @@ -304,7 +614,7 @@ type DepositTransactionDeposited struct { // FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. // // Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) -func (_Deposit *DepositFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DepositTransactionDepositedIterator, error) { +func (_DepositFeed *DepositFeedFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DepositFeedTransactionDepositedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -315,17 +625,17 @@ func (_Deposit *DepositFilterer) FilterTransactionDeposited(opts *bind.FilterOpt toRule = append(toRule, toItem) } - logs, sub, err := _Deposit.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule) + logs, sub, err := _DepositFeed.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule) if err != nil { return nil, err } - return &DepositTransactionDepositedIterator{contract: _Deposit.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil + return &DepositFeedTransactionDepositedIterator{contract: _DepositFeed.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil } // WatchTransactionDeposited is a free log subscription operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. // // Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) -func (_Deposit *DepositFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *DepositTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_DepositFeed *DepositFeedFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *DepositFeedTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -336,7 +646,7 @@ func (_Deposit *DepositFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, toRule = append(toRule, toItem) } - logs, sub, err := _Deposit.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule) + logs, sub, err := _DepositFeed.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule) if err != nil { return nil, err } @@ -346,8 +656,8 @@ func (_Deposit *DepositFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(DepositTransactionDeposited) - if err := _Deposit.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { + event := new(DepositFeedTransactionDeposited) + if err := _DepositFeed.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { return err } event.Raw = log @@ -371,9 +681,3347 @@ func (_Deposit *DepositFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, // ParseTransactionDeposited is a log parse operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. // // Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) -func (_Deposit *DepositFilterer) ParseTransactionDeposited(log types.Log) (*DepositTransactionDeposited, error) { - event := new(DepositTransactionDeposited) - if err := _Deposit.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { +func (_DepositFeed *DepositFeedFilterer) ParseTransactionDeposited(log types.Log) (*DepositFeedTransactionDeposited, error) { + event := new(DepositFeedTransactionDeposited) + if err := _DepositFeed.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. +var L2OutputOracleMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620012f2380380620012f2833981810160405281019062000038919062000260565b620000586200004c620000b460201b60201c565b620000bc60201b60201c565b85608081815250508460a081815250508360026000848152602001908152602001600020819055508260c08181525050816001819055508160e08181525050620000a881620000bc60201b60201c565b505050505050620002fc565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6200019a8162000185565b8114620001a657600080fd5b50565b600081519050620001ba816200018f565b92915050565b6000819050919050565b620001d581620001c0565b8114620001e157600080fd5b50565b600081519050620001f581620001ca565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022882620001fb565b9050919050565b6200023a816200021b565b81146200024657600080fd5b50565b6000815190506200025a816200022f565b92915050565b60008060008060008060c0878903121562000280576200027f62000180565b5b60006200029089828a01620001a9565b9650506020620002a389828a01620001a9565b9550506040620002b689828a01620001e4565b9450506060620002c989828a01620001a9565b9350506080620002dc89828a01620001a9565b92505060a0620002ef89828a0162000249565b9150509295509295509295565b60805160a05160c05160e051610f9962000359600039600081816102b30152818161033701526106b001526000818161036b01526106d4015260008181610316015261066f01526000818161058b01526106f80152610f996000f3fe6080604052600436106100a75760003560e01c806393991af31161006457806393991af31461019d578063a25ae557146101c8578063c5095d6814610205578063c90ec2da14610230578063e1a41bcf1461025b578063f2fde38b14610286576100a7565b806302e51345146100ac5780630c1952d3146100e95780632518810414610114578063357e951f14610130578063715018a61461015b5780638da5cb5b14610172575b600080fd5b3480156100b857600080fd5b506100d360048036038101906100ce9190610919565b6102af565b6040516100e09190610955565b60405180910390f35b3480156100f557600080fd5b506100fe610393565b60405161010b9190610955565b60405180910390f35b61012e600480360381019061012991906109a6565b610399565b005b34801561013c57600080fd5b50610145610587565b6040516101529190610955565b60405180910390f35b34801561016757600080fd5b506101706105bc565b005b34801561017e57600080fd5b50610187610644565b6040516101949190610a4e565b60405180910390f35b3480156101a957600080fd5b506101b261066d565b6040516101bf9190610955565b60405180910390f35b3480156101d457600080fd5b506101ef60048036038101906101ea9190610919565b610691565b6040516101fc9190610a78565b60405180910390f35b34801561021157600080fd5b5061021a6106ae565b6040516102279190610955565b60405180910390f35b34801561023c57600080fd5b506102456106d2565b6040516102529190610955565b60405180910390f35b34801561026757600080fd5b506102706106f6565b60405161027d9190610955565b60405180910390f35b34801561029257600080fd5b506102ad60048036038101906102a89190610abf565b61071a565b005b60007f0000000000000000000000000000000000000000000000000000000000000000821015610314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030b90610b6f565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161036657610365610b8f565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6103a1610812565b73ffffffffffffffffffffffffffffffffffffffff166103bf610644565b73ffffffffffffffffffffffffffffffffffffffff1614610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040c90610c0a565b60405180910390fd5b428310610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e90610c9c565b60405180910390fd5b61045f610587565b83146104a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049790610d2e565b60405180910390fd5b6000801b8414156104e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104dd90610d9a565b60405180910390fd5b6000801b82146105345781814014610533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052a90610e2c565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546105b79190610e7b565b905090565b6105c4610812565b73ffffffffffffffffffffffffffffffffffffffff166105e2610644565b73ffffffffffffffffffffffffffffffffffffffff1614610638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062f90610c0a565b60405180910390fd5b610642600061081a565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610722610812565b73ffffffffffffffffffffffffffffffffffffffff16610740610644565b73ffffffffffffffffffffffffffffffffffffffff1614610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078d90610c0a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fd90610f43565b60405180910390fd5b61080f8161081a565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6108f6816108e3565b811461090157600080fd5b50565b600081359050610913816108ed565b92915050565b60006020828403121561092f5761092e6108de565b5b600061093d84828501610904565b91505092915050565b61094f816108e3565b82525050565b600060208201905061096a6000830184610946565b92915050565b6000819050919050565b61098381610970565b811461098e57600080fd5b50565b6000813590506109a08161097a565b92915050565b600080600080608085870312156109c0576109bf6108de565b5b60006109ce87828801610991565b94505060206109df87828801610904565b93505060406109f087828801610991565b9250506060610a0187828801610904565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a3882610a0d565b9050919050565b610a4881610a2d565b82525050565b6000602082019050610a636000830184610a3f565b92915050565b610a7281610970565b82525050565b6000602082019050610a8d6000830184610a69565b92915050565b610a9c81610a2d565b8114610aa757600080fd5b50565b600081359050610ab981610a93565b92915050565b600060208284031215610ad557610ad46108de565b5b6000610ae384828501610aaa565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610b59602983610aec565b9150610b6482610afd565b604082019050919050565b60006020820190508181036000830152610b8881610b4c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610bf4602083610aec565b9150610bff82610bbe565b602082019050919050565b60006020820190508181036000830152610c2381610be7565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610c86602183610aec565b9150610c9182610c2a565b604082019050919050565b60006020820190508181036000830152610cb581610c79565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610d18602e83610aec565b9150610d2382610cbc565b604082019050919050565b60006020820190508181036000830152610d4781610d0b565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610d84601d83610aec565b9150610d8f82610d4e565b602082019050919050565b60006020820190508181036000830152610db381610d77565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610e16603983610aec565b9150610e2182610dba565b604082019050919050565b60006020820190508181036000830152610e4581610e09565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e86826108e3565b9150610e91836108e3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ec657610ec5610e4c565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610f2d602683610aec565b9150610f3882610ed1565b604082019050919050565b60006020820190508181036000830152610f5c81610f20565b905091905056fea2646970667358221220980520f45819a707ff13a09b23bdace7cce468e4b8e92e7fd2f480d56c85cb7664736f6c634300080a0033", +} + +// L2OutputOracleABI is the input ABI used to generate the binding from. +// Deprecated: Use L2OutputOracleMetaData.ABI instead. +var L2OutputOracleABI = L2OutputOracleMetaData.ABI + +// L2OutputOracleBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use L2OutputOracleMetaData.Bin instead. +var L2OutputOracleBin = L2OutputOracleMetaData.Bin + +// DeployL2OutputOracle deploys a new Ethereum contract, binding an instance of L2OutputOracle to it. +func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionInterval *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int, _startingBlockTimestamp *big.Int, sequencer common.Address) (common.Address, *types.Transaction, *L2OutputOracle, error) { + parsed, err := L2OutputOracleMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L2OutputOracleBin), backend, _submissionInterval, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks, _startingBlockTimestamp, sequencer) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &L2OutputOracle{L2OutputOracleCaller: L2OutputOracleCaller{contract: contract}, L2OutputOracleTransactor: L2OutputOracleTransactor{contract: contract}, L2OutputOracleFilterer: L2OutputOracleFilterer{contract: contract}}, nil +} + +// L2OutputOracle is an auto generated Go binding around an Ethereum contract. +type L2OutputOracle struct { + L2OutputOracleCaller // Read-only binding to the contract + L2OutputOracleTransactor // Write-only binding to the contract + L2OutputOracleFilterer // Log filterer for contract events +} + +// L2OutputOracleCaller is an auto generated read-only Go binding around an Ethereum contract. +type L2OutputOracleCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L2OutputOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. +type L2OutputOracleTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L2OutputOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type L2OutputOracleFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// L2OutputOracleSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type L2OutputOracleSession struct { + Contract *L2OutputOracle // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// L2OutputOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type L2OutputOracleCallerSession struct { + Contract *L2OutputOracleCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// L2OutputOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type L2OutputOracleTransactorSession struct { + Contract *L2OutputOracleTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// L2OutputOracleRaw is an auto generated low-level Go binding around an Ethereum contract. +type L2OutputOracleRaw struct { + Contract *L2OutputOracle // Generic contract binding to access the raw methods on +} + +// L2OutputOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type L2OutputOracleCallerRaw struct { + Contract *L2OutputOracleCaller // Generic read-only contract binding to access the raw methods on +} + +// L2OutputOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type L2OutputOracleTransactorRaw struct { + Contract *L2OutputOracleTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewL2OutputOracle creates a new instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracle(address common.Address, backend bind.ContractBackend) (*L2OutputOracle, error) { + contract, err := bindL2OutputOracle(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &L2OutputOracle{L2OutputOracleCaller: L2OutputOracleCaller{contract: contract}, L2OutputOracleTransactor: L2OutputOracleTransactor{contract: contract}, L2OutputOracleFilterer: L2OutputOracleFilterer{contract: contract}}, nil +} + +// NewL2OutputOracleCaller creates a new read-only instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracleCaller(address common.Address, caller bind.ContractCaller) (*L2OutputOracleCaller, error) { + contract, err := bindL2OutputOracle(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &L2OutputOracleCaller{contract: contract}, nil +} + +// NewL2OutputOracleTransactor creates a new write-only instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*L2OutputOracleTransactor, error) { + contract, err := bindL2OutputOracle(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &L2OutputOracleTransactor{contract: contract}, nil +} + +// NewL2OutputOracleFilterer creates a new log filterer instance of L2OutputOracle, bound to a specific deployed contract. +func NewL2OutputOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*L2OutputOracleFilterer, error) { + contract, err := bindL2OutputOracle(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &L2OutputOracleFilterer{contract: contract}, nil +} + +// bindL2OutputOracle binds a generic wrapper to an already deployed contract. +func bindL2OutputOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(L2OutputOracleABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_L2OutputOracle *L2OutputOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L2OutputOracle.Contract.L2OutputOracleCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_L2OutputOracle *L2OutputOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L2OutputOracle.Contract.L2OutputOracleTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_L2OutputOracle *L2OutputOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L2OutputOracle.Contract.L2OutputOracleTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_L2OutputOracle *L2OutputOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L2OutputOracle.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L2OutputOracle.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L2OutputOracle.Contract.contract.Transact(opts, method, params...) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "historicalTotalBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) HistoricalTotalBlocks() (*big.Int, error) { + return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +} + +// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// +// Solidity: function historicalTotalBlocks() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) HistoricalTotalBlocks() (*big.Int, error) { + return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "l2BlockTime") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) L2BlockTime() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +} + +// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// +// Solidity: function l2BlockTime() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) L2BlockTime() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) LatestBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "latestBlockTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) LatestBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. +// +// Solidity: function latestBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) LatestBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) NextTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "nextTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) NextTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts) +} + +// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. +// +// Solidity: function nextTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) NextTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_L2OutputOracle *L2OutputOracleCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_L2OutputOracle *L2OutputOracleSession) Owner() (common.Address, error) { + return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_L2OutputOracle *L2OutputOracleCallerSession) Owner() (common.Address, error) { + return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) StartingBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "startingBlockTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) StartingBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. +// +// Solidity: function startingBlockTimestamp() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) StartingBlockTimestamp() (*big.Int, error) { + return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) +} + +// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. +// +// Solidity: function submissionInterval() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) SubmissionInterval(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "submissionInterval") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. +// +// Solidity: function submissionInterval() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) SubmissionInterval() (*big.Int, error) { + return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) +} + +// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. +// +// Solidity: function submissionInterval() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) SubmissionInterval() (*big.Int, error) { + return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() +func (_L2OutputOracle *L2OutputOracleTransactor) AppendL2Output(opts *bind.TransactOpts, _l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "appendL2Output", _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() +func (_L2OutputOracle *L2OutputOracleSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { + return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) +} + +// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. +// +// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { + return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_L2OutputOracle *L2OutputOracleTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_L2OutputOracle *L2OutputOracleSession) RenounceOwnership() (*types.Transaction, error) { + return _L2OutputOracle.Contract.RenounceOwnership(&_L2OutputOracle.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _L2OutputOracle.Contract.RenounceOwnership(&_L2OutputOracle.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_L2OutputOracle *L2OutputOracleTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_L2OutputOracle *L2OutputOracleSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.Contract.TransferOwnership(&_L2OutputOracle.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _L2OutputOracle.Contract.TransferOwnership(&_L2OutputOracle.TransactOpts, newOwner) +} + +// L2OutputOracleOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the L2OutputOracle contract. +type L2OutputOracleOwnershipTransferredIterator struct { + Event *L2OutputOracleOwnershipTransferred // 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 *L2OutputOracleOwnershipTransferredIterator) 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(L2OutputOracleOwnershipTransferred) + 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(L2OutputOracleOwnershipTransferred) + 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 *L2OutputOracleOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *L2OutputOracleOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// L2OutputOracleOwnershipTransferred represents a OwnershipTransferred event raised by the L2OutputOracle contract. +type L2OutputOracleOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*L2OutputOracleOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &L2OutputOracleOwnershipTransferredIterator{contract: _L2OutputOracle.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *L2OutputOracleOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(L2OutputOracleOwnershipTransferred) + if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_L2OutputOracle *L2OutputOracleFilterer) ParseOwnershipTransferred(log types.Log) (*L2OutputOracleOwnershipTransferred, error) { + event := new(L2OutputOracleOwnershipTransferred) + if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// L2OutputOracleL2OutputAppendedIterator is returned from FilterL2OutputAppended and is used to iterate over the raw logs and unpacked data for L2OutputAppended events raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputAppendedIterator struct { + Event *L2OutputOracleL2OutputAppended // 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 *L2OutputOracleL2OutputAppendedIterator) 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(L2OutputOracleL2OutputAppended) + 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(L2OutputOracleL2OutputAppended) + 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 *L2OutputOracleL2OutputAppendedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *L2OutputOracleL2OutputAppendedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// L2OutputOracleL2OutputAppended represents a L2OutputAppended event raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputAppended struct { + L2Output [32]byte + L2timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterL2OutputAppended is a free log retrieval operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputAppendedIterator, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) + if err != nil { + return nil, err + } + return &L2OutputOracleL2OutputAppendedIterator{contract: _L2OutputOracle.contract, event: "l2OutputAppended", logs: logs, sub: sub}, nil +} + +// WatchL2OutputAppended is a free log subscription operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputAppended, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) + 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(L2OutputOracleL2OutputAppended) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", 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 +} + +// ParseL2OutputAppended is a log parse operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.Log) (*L2OutputOracleL2OutputAppended, error) { + event := new(L2OutputOracleL2OutputAppended) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// LibBytesUtilsMetaData contains all meta data concerning the LibBytesUtils contract. +var LibBytesUtilsMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e958e3c5fd0868451927cf89f50e248831442cc24af29e21bca4bc8a02ffeb9764736f6c634300080a0033", +} + +// LibBytesUtilsABI is the input ABI used to generate the binding from. +// Deprecated: Use LibBytesUtilsMetaData.ABI instead. +var LibBytesUtilsABI = LibBytesUtilsMetaData.ABI + +// LibBytesUtilsBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use LibBytesUtilsMetaData.Bin instead. +var LibBytesUtilsBin = LibBytesUtilsMetaData.Bin + +// DeployLibBytesUtils deploys a new Ethereum contract, binding an instance of LibBytesUtils to it. +func DeployLibBytesUtils(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibBytesUtils, error) { + parsed, err := LibBytesUtilsMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibBytesUtilsBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &LibBytesUtils{LibBytesUtilsCaller: LibBytesUtilsCaller{contract: contract}, LibBytesUtilsTransactor: LibBytesUtilsTransactor{contract: contract}, LibBytesUtilsFilterer: LibBytesUtilsFilterer{contract: contract}}, nil +} + +// LibBytesUtils is an auto generated Go binding around an Ethereum contract. +type LibBytesUtils struct { + LibBytesUtilsCaller // Read-only binding to the contract + LibBytesUtilsTransactor // Write-only binding to the contract + LibBytesUtilsFilterer // Log filterer for contract events +} + +// LibBytesUtilsCaller is an auto generated read-only Go binding around an Ethereum contract. +type LibBytesUtilsCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibBytesUtilsTransactor is an auto generated write-only Go binding around an Ethereum contract. +type LibBytesUtilsTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibBytesUtilsFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type LibBytesUtilsFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibBytesUtilsSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type LibBytesUtilsSession struct { + Contract *LibBytesUtils // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibBytesUtilsCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type LibBytesUtilsCallerSession struct { + Contract *LibBytesUtilsCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// LibBytesUtilsTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type LibBytesUtilsTransactorSession struct { + Contract *LibBytesUtilsTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibBytesUtilsRaw is an auto generated low-level Go binding around an Ethereum contract. +type LibBytesUtilsRaw struct { + Contract *LibBytesUtils // Generic contract binding to access the raw methods on +} + +// LibBytesUtilsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type LibBytesUtilsCallerRaw struct { + Contract *LibBytesUtilsCaller // Generic read-only contract binding to access the raw methods on +} + +// LibBytesUtilsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type LibBytesUtilsTransactorRaw struct { + Contract *LibBytesUtilsTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewLibBytesUtils creates a new instance of LibBytesUtils, bound to a specific deployed contract. +func NewLibBytesUtils(address common.Address, backend bind.ContractBackend) (*LibBytesUtils, error) { + contract, err := bindLibBytesUtils(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LibBytesUtils{LibBytesUtilsCaller: LibBytesUtilsCaller{contract: contract}, LibBytesUtilsTransactor: LibBytesUtilsTransactor{contract: contract}, LibBytesUtilsFilterer: LibBytesUtilsFilterer{contract: contract}}, nil +} + +// NewLibBytesUtilsCaller creates a new read-only instance of LibBytesUtils, bound to a specific deployed contract. +func NewLibBytesUtilsCaller(address common.Address, caller bind.ContractCaller) (*LibBytesUtilsCaller, error) { + contract, err := bindLibBytesUtils(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LibBytesUtilsCaller{contract: contract}, nil +} + +// NewLibBytesUtilsTransactor creates a new write-only instance of LibBytesUtils, bound to a specific deployed contract. +func NewLibBytesUtilsTransactor(address common.Address, transactor bind.ContractTransactor) (*LibBytesUtilsTransactor, error) { + contract, err := bindLibBytesUtils(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LibBytesUtilsTransactor{contract: contract}, nil +} + +// NewLibBytesUtilsFilterer creates a new log filterer instance of LibBytesUtils, bound to a specific deployed contract. +func NewLibBytesUtilsFilterer(address common.Address, filterer bind.ContractFilterer) (*LibBytesUtilsFilterer, error) { + contract, err := bindLibBytesUtils(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LibBytesUtilsFilterer{contract: contract}, nil +} + +// bindLibBytesUtils binds a generic wrapper to an already deployed contract. +func bindLibBytesUtils(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(LibBytesUtilsABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibBytesUtils *LibBytesUtilsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibBytesUtils.Contract.LibBytesUtilsCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibBytesUtils *LibBytesUtilsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibBytesUtils.Contract.LibBytesUtilsTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibBytesUtils *LibBytesUtilsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibBytesUtils.Contract.LibBytesUtilsTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibBytesUtils *LibBytesUtilsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibBytesUtils.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibBytesUtils *LibBytesUtilsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibBytesUtils.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibBytesUtils *LibBytesUtilsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibBytesUtils.Contract.contract.Transact(opts, method, params...) +} + +// LibMerkleTrieMetaData contains all meta data concerning the LibMerkleTrie contract. +var LibMerkleTrieMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212204e5467228078a9262e6dfded9555ccabe760347ff5c34b33bdd846b1084e54b764736f6c634300080a0033", +} + +// LibMerkleTrieABI is the input ABI used to generate the binding from. +// Deprecated: Use LibMerkleTrieMetaData.ABI instead. +var LibMerkleTrieABI = LibMerkleTrieMetaData.ABI + +// LibMerkleTrieBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use LibMerkleTrieMetaData.Bin instead. +var LibMerkleTrieBin = LibMerkleTrieMetaData.Bin + +// DeployLibMerkleTrie deploys a new Ethereum contract, binding an instance of LibMerkleTrie to it. +func DeployLibMerkleTrie(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibMerkleTrie, error) { + parsed, err := LibMerkleTrieMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibMerkleTrieBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &LibMerkleTrie{LibMerkleTrieCaller: LibMerkleTrieCaller{contract: contract}, LibMerkleTrieTransactor: LibMerkleTrieTransactor{contract: contract}, LibMerkleTrieFilterer: LibMerkleTrieFilterer{contract: contract}}, nil +} + +// LibMerkleTrie is an auto generated Go binding around an Ethereum contract. +type LibMerkleTrie struct { + LibMerkleTrieCaller // Read-only binding to the contract + LibMerkleTrieTransactor // Write-only binding to the contract + LibMerkleTrieFilterer // Log filterer for contract events +} + +// LibMerkleTrieCaller is an auto generated read-only Go binding around an Ethereum contract. +type LibMerkleTrieCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibMerkleTrieTransactor is an auto generated write-only Go binding around an Ethereum contract. +type LibMerkleTrieTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibMerkleTrieFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type LibMerkleTrieFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibMerkleTrieSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type LibMerkleTrieSession struct { + Contract *LibMerkleTrie // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibMerkleTrieCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type LibMerkleTrieCallerSession struct { + Contract *LibMerkleTrieCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// LibMerkleTrieTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type LibMerkleTrieTransactorSession struct { + Contract *LibMerkleTrieTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibMerkleTrieRaw is an auto generated low-level Go binding around an Ethereum contract. +type LibMerkleTrieRaw struct { + Contract *LibMerkleTrie // Generic contract binding to access the raw methods on +} + +// LibMerkleTrieCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type LibMerkleTrieCallerRaw struct { + Contract *LibMerkleTrieCaller // Generic read-only contract binding to access the raw methods on +} + +// LibMerkleTrieTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type LibMerkleTrieTransactorRaw struct { + Contract *LibMerkleTrieTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewLibMerkleTrie creates a new instance of LibMerkleTrie, bound to a specific deployed contract. +func NewLibMerkleTrie(address common.Address, backend bind.ContractBackend) (*LibMerkleTrie, error) { + contract, err := bindLibMerkleTrie(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LibMerkleTrie{LibMerkleTrieCaller: LibMerkleTrieCaller{contract: contract}, LibMerkleTrieTransactor: LibMerkleTrieTransactor{contract: contract}, LibMerkleTrieFilterer: LibMerkleTrieFilterer{contract: contract}}, nil +} + +// NewLibMerkleTrieCaller creates a new read-only instance of LibMerkleTrie, bound to a specific deployed contract. +func NewLibMerkleTrieCaller(address common.Address, caller bind.ContractCaller) (*LibMerkleTrieCaller, error) { + contract, err := bindLibMerkleTrie(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LibMerkleTrieCaller{contract: contract}, nil +} + +// NewLibMerkleTrieTransactor creates a new write-only instance of LibMerkleTrie, bound to a specific deployed contract. +func NewLibMerkleTrieTransactor(address common.Address, transactor bind.ContractTransactor) (*LibMerkleTrieTransactor, error) { + contract, err := bindLibMerkleTrie(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LibMerkleTrieTransactor{contract: contract}, nil +} + +// NewLibMerkleTrieFilterer creates a new log filterer instance of LibMerkleTrie, bound to a specific deployed contract. +func NewLibMerkleTrieFilterer(address common.Address, filterer bind.ContractFilterer) (*LibMerkleTrieFilterer, error) { + contract, err := bindLibMerkleTrie(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LibMerkleTrieFilterer{contract: contract}, nil +} + +// bindLibMerkleTrie binds a generic wrapper to an already deployed contract. +func bindLibMerkleTrie(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(LibMerkleTrieABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibMerkleTrie *LibMerkleTrieRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibMerkleTrie.Contract.LibMerkleTrieCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibMerkleTrie *LibMerkleTrieRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibMerkleTrie.Contract.LibMerkleTrieTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibMerkleTrie *LibMerkleTrieRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibMerkleTrie.Contract.LibMerkleTrieTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibMerkleTrie *LibMerkleTrieCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibMerkleTrie.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibMerkleTrie *LibMerkleTrieTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibMerkleTrie.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibMerkleTrie *LibMerkleTrieTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibMerkleTrie.Contract.contract.Transact(opts, method, params...) +} + +// LibRLPReaderMetaData contains all meta data concerning the LibRLPReader contract. +var LibRLPReaderMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e5de027b2466f0cb69615d578b02779f2ad9c727a9dd3b17b8e9279e3334f80864736f6c634300080a0033", +} + +// LibRLPReaderABI is the input ABI used to generate the binding from. +// Deprecated: Use LibRLPReaderMetaData.ABI instead. +var LibRLPReaderABI = LibRLPReaderMetaData.ABI + +// LibRLPReaderBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use LibRLPReaderMetaData.Bin instead. +var LibRLPReaderBin = LibRLPReaderMetaData.Bin + +// DeployLibRLPReader deploys a new Ethereum contract, binding an instance of LibRLPReader to it. +func DeployLibRLPReader(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibRLPReader, error) { + parsed, err := LibRLPReaderMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibRLPReaderBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &LibRLPReader{LibRLPReaderCaller: LibRLPReaderCaller{contract: contract}, LibRLPReaderTransactor: LibRLPReaderTransactor{contract: contract}, LibRLPReaderFilterer: LibRLPReaderFilterer{contract: contract}}, nil +} + +// LibRLPReader is an auto generated Go binding around an Ethereum contract. +type LibRLPReader struct { + LibRLPReaderCaller // Read-only binding to the contract + LibRLPReaderTransactor // Write-only binding to the contract + LibRLPReaderFilterer // Log filterer for contract events +} + +// LibRLPReaderCaller is an auto generated read-only Go binding around an Ethereum contract. +type LibRLPReaderCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibRLPReaderTransactor is an auto generated write-only Go binding around an Ethereum contract. +type LibRLPReaderTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibRLPReaderFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type LibRLPReaderFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibRLPReaderSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type LibRLPReaderSession struct { + Contract *LibRLPReader // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibRLPReaderCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type LibRLPReaderCallerSession struct { + Contract *LibRLPReaderCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// LibRLPReaderTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type LibRLPReaderTransactorSession struct { + Contract *LibRLPReaderTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibRLPReaderRaw is an auto generated low-level Go binding around an Ethereum contract. +type LibRLPReaderRaw struct { + Contract *LibRLPReader // Generic contract binding to access the raw methods on +} + +// LibRLPReaderCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type LibRLPReaderCallerRaw struct { + Contract *LibRLPReaderCaller // Generic read-only contract binding to access the raw methods on +} + +// LibRLPReaderTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type LibRLPReaderTransactorRaw struct { + Contract *LibRLPReaderTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewLibRLPReader creates a new instance of LibRLPReader, bound to a specific deployed contract. +func NewLibRLPReader(address common.Address, backend bind.ContractBackend) (*LibRLPReader, error) { + contract, err := bindLibRLPReader(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LibRLPReader{LibRLPReaderCaller: LibRLPReaderCaller{contract: contract}, LibRLPReaderTransactor: LibRLPReaderTransactor{contract: contract}, LibRLPReaderFilterer: LibRLPReaderFilterer{contract: contract}}, nil +} + +// NewLibRLPReaderCaller creates a new read-only instance of LibRLPReader, bound to a specific deployed contract. +func NewLibRLPReaderCaller(address common.Address, caller bind.ContractCaller) (*LibRLPReaderCaller, error) { + contract, err := bindLibRLPReader(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LibRLPReaderCaller{contract: contract}, nil +} + +// NewLibRLPReaderTransactor creates a new write-only instance of LibRLPReader, bound to a specific deployed contract. +func NewLibRLPReaderTransactor(address common.Address, transactor bind.ContractTransactor) (*LibRLPReaderTransactor, error) { + contract, err := bindLibRLPReader(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LibRLPReaderTransactor{contract: contract}, nil +} + +// NewLibRLPReaderFilterer creates a new log filterer instance of LibRLPReader, bound to a specific deployed contract. +func NewLibRLPReaderFilterer(address common.Address, filterer bind.ContractFilterer) (*LibRLPReaderFilterer, error) { + contract, err := bindLibRLPReader(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LibRLPReaderFilterer{contract: contract}, nil +} + +// bindLibRLPReader binds a generic wrapper to an already deployed contract. +func bindLibRLPReader(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(LibRLPReaderABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibRLPReader *LibRLPReaderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibRLPReader.Contract.LibRLPReaderCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibRLPReader *LibRLPReaderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibRLPReader.Contract.LibRLPReaderTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibRLPReader *LibRLPReaderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibRLPReader.Contract.LibRLPReaderTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibRLPReader *LibRLPReaderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibRLPReader.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibRLPReader *LibRLPReaderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibRLPReader.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibRLPReader *LibRLPReaderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibRLPReader.Contract.contract.Transact(opts, method, params...) +} + +// LibRLPWriterMetaData contains all meta data concerning the LibRLPWriter contract. +var LibRLPWriterMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220bef8e644bef83a13fe830ce5a62f8dd508a8ed03087ab7d1f194c2164c3d8cfe64736f6c634300080a0033", +} + +// LibRLPWriterABI is the input ABI used to generate the binding from. +// Deprecated: Use LibRLPWriterMetaData.ABI instead. +var LibRLPWriterABI = LibRLPWriterMetaData.ABI + +// LibRLPWriterBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use LibRLPWriterMetaData.Bin instead. +var LibRLPWriterBin = LibRLPWriterMetaData.Bin + +// DeployLibRLPWriter deploys a new Ethereum contract, binding an instance of LibRLPWriter to it. +func DeployLibRLPWriter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibRLPWriter, error) { + parsed, err := LibRLPWriterMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibRLPWriterBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &LibRLPWriter{LibRLPWriterCaller: LibRLPWriterCaller{contract: contract}, LibRLPWriterTransactor: LibRLPWriterTransactor{contract: contract}, LibRLPWriterFilterer: LibRLPWriterFilterer{contract: contract}}, nil +} + +// LibRLPWriter is an auto generated Go binding around an Ethereum contract. +type LibRLPWriter struct { + LibRLPWriterCaller // Read-only binding to the contract + LibRLPWriterTransactor // Write-only binding to the contract + LibRLPWriterFilterer // Log filterer for contract events +} + +// LibRLPWriterCaller is an auto generated read-only Go binding around an Ethereum contract. +type LibRLPWriterCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibRLPWriterTransactor is an auto generated write-only Go binding around an Ethereum contract. +type LibRLPWriterTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibRLPWriterFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type LibRLPWriterFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibRLPWriterSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type LibRLPWriterSession struct { + Contract *LibRLPWriter // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibRLPWriterCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type LibRLPWriterCallerSession struct { + Contract *LibRLPWriterCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// LibRLPWriterTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type LibRLPWriterTransactorSession struct { + Contract *LibRLPWriterTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibRLPWriterRaw is an auto generated low-level Go binding around an Ethereum contract. +type LibRLPWriterRaw struct { + Contract *LibRLPWriter // Generic contract binding to access the raw methods on +} + +// LibRLPWriterCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type LibRLPWriterCallerRaw struct { + Contract *LibRLPWriterCaller // Generic read-only contract binding to access the raw methods on +} + +// LibRLPWriterTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type LibRLPWriterTransactorRaw struct { + Contract *LibRLPWriterTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewLibRLPWriter creates a new instance of LibRLPWriter, bound to a specific deployed contract. +func NewLibRLPWriter(address common.Address, backend bind.ContractBackend) (*LibRLPWriter, error) { + contract, err := bindLibRLPWriter(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LibRLPWriter{LibRLPWriterCaller: LibRLPWriterCaller{contract: contract}, LibRLPWriterTransactor: LibRLPWriterTransactor{contract: contract}, LibRLPWriterFilterer: LibRLPWriterFilterer{contract: contract}}, nil +} + +// NewLibRLPWriterCaller creates a new read-only instance of LibRLPWriter, bound to a specific deployed contract. +func NewLibRLPWriterCaller(address common.Address, caller bind.ContractCaller) (*LibRLPWriterCaller, error) { + contract, err := bindLibRLPWriter(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LibRLPWriterCaller{contract: contract}, nil +} + +// NewLibRLPWriterTransactor creates a new write-only instance of LibRLPWriter, bound to a specific deployed contract. +func NewLibRLPWriterTransactor(address common.Address, transactor bind.ContractTransactor) (*LibRLPWriterTransactor, error) { + contract, err := bindLibRLPWriter(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LibRLPWriterTransactor{contract: contract}, nil +} + +// NewLibRLPWriterFilterer creates a new log filterer instance of LibRLPWriter, bound to a specific deployed contract. +func NewLibRLPWriterFilterer(address common.Address, filterer bind.ContractFilterer) (*LibRLPWriterFilterer, error) { + contract, err := bindLibRLPWriter(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LibRLPWriterFilterer{contract: contract}, nil +} + +// bindLibRLPWriter binds a generic wrapper to an already deployed contract. +func bindLibRLPWriter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(LibRLPWriterABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibRLPWriter *LibRLPWriterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibRLPWriter.Contract.LibRLPWriterCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibRLPWriter *LibRLPWriterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibRLPWriter.Contract.LibRLPWriterTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibRLPWriter *LibRLPWriterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibRLPWriter.Contract.LibRLPWriterTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibRLPWriter *LibRLPWriterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibRLPWriter.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibRLPWriter *LibRLPWriterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibRLPWriter.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibRLPWriter *LibRLPWriterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibRLPWriter.Contract.contract.Transact(opts, method, params...) +} + +// LibSecureMerkleTrieMetaData contains all meta data concerning the LibSecureMerkleTrie contract. +var LibSecureMerkleTrieMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202826b55c1fd499dcab01cf9cefa4f87b2c8d925e6014f9f077213f8dbc479ba964736f6c634300080a0033", +} + +// LibSecureMerkleTrieABI is the input ABI used to generate the binding from. +// Deprecated: Use LibSecureMerkleTrieMetaData.ABI instead. +var LibSecureMerkleTrieABI = LibSecureMerkleTrieMetaData.ABI + +// LibSecureMerkleTrieBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use LibSecureMerkleTrieMetaData.Bin instead. +var LibSecureMerkleTrieBin = LibSecureMerkleTrieMetaData.Bin + +// DeployLibSecureMerkleTrie deploys a new Ethereum contract, binding an instance of LibSecureMerkleTrie to it. +func DeployLibSecureMerkleTrie(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibSecureMerkleTrie, error) { + parsed, err := LibSecureMerkleTrieMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibSecureMerkleTrieBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &LibSecureMerkleTrie{LibSecureMerkleTrieCaller: LibSecureMerkleTrieCaller{contract: contract}, LibSecureMerkleTrieTransactor: LibSecureMerkleTrieTransactor{contract: contract}, LibSecureMerkleTrieFilterer: LibSecureMerkleTrieFilterer{contract: contract}}, nil +} + +// LibSecureMerkleTrie is an auto generated Go binding around an Ethereum contract. +type LibSecureMerkleTrie struct { + LibSecureMerkleTrieCaller // Read-only binding to the contract + LibSecureMerkleTrieTransactor // Write-only binding to the contract + LibSecureMerkleTrieFilterer // Log filterer for contract events +} + +// LibSecureMerkleTrieCaller is an auto generated read-only Go binding around an Ethereum contract. +type LibSecureMerkleTrieCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibSecureMerkleTrieTransactor is an auto generated write-only Go binding around an Ethereum contract. +type LibSecureMerkleTrieTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibSecureMerkleTrieFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type LibSecureMerkleTrieFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// LibSecureMerkleTrieSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type LibSecureMerkleTrieSession struct { + Contract *LibSecureMerkleTrie // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibSecureMerkleTrieCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type LibSecureMerkleTrieCallerSession struct { + Contract *LibSecureMerkleTrieCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// LibSecureMerkleTrieTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type LibSecureMerkleTrieTransactorSession struct { + Contract *LibSecureMerkleTrieTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// LibSecureMerkleTrieRaw is an auto generated low-level Go binding around an Ethereum contract. +type LibSecureMerkleTrieRaw struct { + Contract *LibSecureMerkleTrie // Generic contract binding to access the raw methods on +} + +// LibSecureMerkleTrieCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type LibSecureMerkleTrieCallerRaw struct { + Contract *LibSecureMerkleTrieCaller // Generic read-only contract binding to access the raw methods on +} + +// LibSecureMerkleTrieTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type LibSecureMerkleTrieTransactorRaw struct { + Contract *LibSecureMerkleTrieTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewLibSecureMerkleTrie creates a new instance of LibSecureMerkleTrie, bound to a specific deployed contract. +func NewLibSecureMerkleTrie(address common.Address, backend bind.ContractBackend) (*LibSecureMerkleTrie, error) { + contract, err := bindLibSecureMerkleTrie(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LibSecureMerkleTrie{LibSecureMerkleTrieCaller: LibSecureMerkleTrieCaller{contract: contract}, LibSecureMerkleTrieTransactor: LibSecureMerkleTrieTransactor{contract: contract}, LibSecureMerkleTrieFilterer: LibSecureMerkleTrieFilterer{contract: contract}}, nil +} + +// NewLibSecureMerkleTrieCaller creates a new read-only instance of LibSecureMerkleTrie, bound to a specific deployed contract. +func NewLibSecureMerkleTrieCaller(address common.Address, caller bind.ContractCaller) (*LibSecureMerkleTrieCaller, error) { + contract, err := bindLibSecureMerkleTrie(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LibSecureMerkleTrieCaller{contract: contract}, nil +} + +// NewLibSecureMerkleTrieTransactor creates a new write-only instance of LibSecureMerkleTrie, bound to a specific deployed contract. +func NewLibSecureMerkleTrieTransactor(address common.Address, transactor bind.ContractTransactor) (*LibSecureMerkleTrieTransactor, error) { + contract, err := bindLibSecureMerkleTrie(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LibSecureMerkleTrieTransactor{contract: contract}, nil +} + +// NewLibSecureMerkleTrieFilterer creates a new log filterer instance of LibSecureMerkleTrie, bound to a specific deployed contract. +func NewLibSecureMerkleTrieFilterer(address common.Address, filterer bind.ContractFilterer) (*LibSecureMerkleTrieFilterer, error) { + contract, err := bindLibSecureMerkleTrie(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LibSecureMerkleTrieFilterer{contract: contract}, nil +} + +// bindLibSecureMerkleTrie binds a generic wrapper to an already deployed contract. +func bindLibSecureMerkleTrie(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(LibSecureMerkleTrieABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibSecureMerkleTrie *LibSecureMerkleTrieRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibSecureMerkleTrie.Contract.LibSecureMerkleTrieCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibSecureMerkleTrie *LibSecureMerkleTrieRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibSecureMerkleTrie.Contract.LibSecureMerkleTrieTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibSecureMerkleTrie *LibSecureMerkleTrieRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibSecureMerkleTrie.Contract.LibSecureMerkleTrieTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_LibSecureMerkleTrie *LibSecureMerkleTrieCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LibSecureMerkleTrie.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_LibSecureMerkleTrie *LibSecureMerkleTrieTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LibSecureMerkleTrie.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_LibSecureMerkleTrie *LibSecureMerkleTrieTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LibSecureMerkleTrie.Contract.contract.Transact(opts, method, params...) +} + +// OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. +var OptimismPortalMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60c060405261dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005357600080fd5b506040516200306b3803806200306b83398181016040528101906200007991906200017a565b81818173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050806080818152505050505050620001c1565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000f382620000c6565b9050919050565b60006200010782620000e6565b9050919050565b6200011981620000fa565b81146200012557600080fd5b50565b60008151905062000139816200010e565b92915050565b6000819050919050565b62000154816200013f565b81146200016057600080fd5b50565b600081519050620001748162000149565b92915050565b60008060408385031215620001945762000193620000c1565b5b6000620001a48582860162000128565b9250506020620001b78582860162000163565b9150509250929050565b60805160a051612e76620001f5600039600081816102b2015261037801526000818161031a01526106720152612e766000f3fe6080604052600436106100585760003560e01c80621c2ff6146100835780639bf62d82146100ae578063a14238e7146100d9578063eecf1c3614610116578063fa92670c1461013f578063ff61cc931461015b5761007e565b3661007e5761007c3334617530600060405180602001604052806000815250610186565b005b600080fd5b34801561008f57600080fd5b506100986102b0565b6040516100a59190611bd9565b60405180910390f35b3480156100ba57600080fd5b506100c36102d4565b6040516100d09190611c15565b60405180910390f35b3480156100e557600080fd5b5061010060048036038101906100fb9190611c7a565b6102f8565b60405161010d9190611cc2565b60405180910390f35b34801561012257600080fd5b5061013d60048036038101906101389190611dc8565b610318565b005b61015960048036038101906101549190612041565b610186565b005b34801561016757600080fd5b50610170610670565b60405161017d91906120e7565b60405180910390f35b8180156101c05750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156101f7576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461023b5761023833610694565b90505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516102a095949392919061218a565b60405180910390a3505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915054906101000a900460ff1681565b7f00000000000000000000000000000000000000000000000000000000000000008401421015610374576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a25ae557866040518263ffffffff1660e01b81526004016103cf91906120e7565b602060405180830381865afa1580156103ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041091906121f9565b905061041b846106b4565b8114610453576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104648d8d8d8d8d8d8d6106fa565b90506000151561047a828760400135878761073c565b151514156104b4576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600115156001600083815260200190815260200160002060009054906101000a900460ff1615151415610513576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161057f929190612256565b600060405180830381858888f193505050503d80600081146105bd576040519150601f19603f3d011682016040523d82523d6000602084013e6105c2565b606091505b5050905061dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600180600084815260200190815260200160002060006101000a81548160ff021916908315150217905550817f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f60405160405180910390a25050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600073111100000000000000000000000000000000111182019050919050565b600081600001358260200135836040013584606001356040516020016106dd949392919061227e565b604051602081830303815290604052805190602001209050919050565b60008787878787878760405160200161071997969594939291906122f0565b604051602081830303815290604052805190602001209050979650505050505050565b60008085600160405160200161075392919061235a565b60405160208183030381529060405280519060200120905061080f8160405160200161077f91906123a4565b6040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508861081a565b915050949350505050565b6000806108268661083f565b90506108348186868661086f565b915050949350505050565b6060818051906020012060405160200161085991906123a4565b6040516020818303038152906040529050919050565b600080600061087f8786866108a2565b915091508180156108965750610895868261097b565b5b92505050949350505050565b6000606060006108b185610996565b905060008060006108c3848a89610a8b565b925092509250600080835114905080806108da5750815b610919576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109109061241c565b60405180910390fd5b6000816109355760405180602001604052806000815250610965565b61096486600187610946919061246b565b815181106109575761095661249f565b5b6020026020010151610efc565b5b9050818197509750505050505050935093915050565b60008180519060200120838051906020012014905092915050565b606060006109a383610f3d565b90506000815167ffffffffffffffff8111156109c2576109c1611f16565b5b6040519080825280602002602001820160405280156109fb57816020015b6109e8611b26565b8152602001906001900390816109e05790505b50905060005b8251811015610a80576000610a2f848381518110610a2257610a2161249f565b5b6020026020010151610f57565b90506040518060400160405280828152602001610a4b83610f3d565b815250838381518110610a6157610a6061249f565b5b6020026020010181905250508080610a78906124ce565b915050610a01565b508092505050919050565b60006060600080600090506000610aa187610fed565b90506000869050600080610ab3611b26565b60005b8c51811015610eac578c8181518110610ad257610ad161249f565b5b602002602001015191508284610ae89190612517565b9350600187610af79190612517565b96506000841415610b54578482600001518051906020012014610b4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b46906125b9565b60405180910390fd5b610c03565b602082600001515110610bb3578482600001518051906020012014610bae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba590612625565b60405180910390fd5b610c02565b84610bc18360000151611192565b14610c01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf890612691565b60405180910390fd5b5b5b60016010610c119190612517565b8260200151511415610c8c578551841415610c2b57610eac565b6000868581518110610c4057610c3f61249f565b5b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c6c57610c6b61249f565b5b60200260200101519050610c7f816111cc565b9650600194505050610e99565b60028260200151511415610e5e576000610ca58361120a565b9050600081600081518110610cbd57610cbc61249f565b5b602001015160f81c60f81b60f81c90506000600282610cdc91906126ed565b6002610ce8919061271e565b90506000610cf9848360ff16611243565b90506000610d078b8a611243565b90506000610d158383611284565b9050600260ff168560ff161480610d325750600360ff168560ff16145b15610d8f57808351148015610d475750808251145b15610d5b57808a610d589190612517565b99505b608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b600060ff168560ff161480610daa5750600160ff168560ff16145b15610e235782518114610deb57608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b610e138860200151600181518110610e0657610e0561249f565b5b60200260200101516111cc565b9a50809850505050505050610e99565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e55906127c4565b60405180910390fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9090612830565b60405180910390fd5b8080610ea4906124ce565b915050610ab6565b506000608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168514905086610ee58786611243565b829950995099505050505050505093509350939050565b6060610f3682602001516001846020015151610f18919061246b565b81518110610f2957610f2861249f565b5b6020026020010151610f57565b9050919050565b6060610f50610f4b83611347565b611375565b9050919050565b60606000806000610f678561156c565b92509250925060006001811115610f8157610f80612850565b5b816001811115610f9457610f93612850565b5b14610fd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fcb906128cb565b60405180910390fd5b610fe385602001518484611885565b9350505050919050565b6060600060028351610fff91906128eb565b67ffffffffffffffff81111561101857611017611f16565b5b6040519080825280601f01601f19166020018201604052801561104a5781602001600182028036833780820191505090505b50905060005b835181101561118857600484828151811061106e5761106d61249f565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c826002836110ab91906128eb565b815181106110bc576110bb61249f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506010848281518110611100576110ff61249f565b5b602001015160f81c60f81b60f81c61111891906126ed565b60f81b82600160028461112b91906128eb565b6111359190612517565b815181106111465761114561249f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080611180906124ce565b915050611050565b5080915050919050565b60006020825110156111b057600060208301519050809150506111c7565b818060200190518101906111c491906121f9565b90505b919050565b600060606020836000015110156111ed576111e68361198b565b90506111f9565b6111f683610f57565b90505b61120281611192565b915050919050565b606061123c611237836020015160008151811061122a5761122961249f565b5b6020026020010151610f57565b610fed565b9050919050565b6060825182106112645760405180602001604052806000815250905061127e565b61127b8383848651611276919061246b565b61199d565b90505b92915050565b600080600090505b80845111801561129c5750808351115b801561132557508281815181106112b6576112b561249f565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112f6576112f561249f565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b1561133d578080611335906124ce565b91505061128c565b8091505092915050565b61134f611b40565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606000806113838461156c565b925050915060018081111561139b5761139a612850565b5b8160018111156113ae576113ad612850565b5b146113ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e590612991565b60405180910390fd5b6000602067ffffffffffffffff81111561140b5761140a611f16565b5b60405190808252806020026020018201604052801561144457816020015b611431611b40565b8152602001906001900390816114295790505b5090506000808490505b866000015181101561155c576020821061149d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149490612a23565b60405180910390fd5b6000806114db6040518060400160405280858c600001516114be919061246b565b8152602001858c602001516114d39190612517565b81525061156c565b5091509150604051806040016040528083836114f79190612517565b8152602001848b6020015161150c9190612517565b8152508585815181106115225761152161249f565b5b602002602001018190525060018461153a9190612517565b935080826115489190612517565b836115539190612517565b9250505061144e565b8183528295505050505050919050565b6000806000808460000151116115b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ae90612a8f565b60405180910390fd5b6000846020015190506000815160001a9050607f81116115e457600060016000945094509450505061187e565b60b781116116565760006080826115fb919061246b565b905080876000015111611643576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163a90612afb565b60405180910390fd5b600181600095509550955050505061187e565b60bf811161173757600060b78261166d919061246b565b9050808760000151116116b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ac90612b67565b60405180910390fd5b6000816020036101000a600185015104905080826116d39190612517565b886000015111611718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170f90612bd3565b60405180910390fd5b8160016117259190612517565b8160009650965096505050505061187e565b60f781116117a957600060c08261174e919061246b565b905080876000015111611796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178d90612c3f565b60405180910390fd5b600181600195509550955050505061187e565b600060f7826117b8919061246b565b905080876000015111611800576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f790612cab565b60405180910390fd5b6000816020036101000a6001850151049050808261181e9190612517565b886000015111611863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185a90612d17565b60405180910390fd5b8160016118709190612517565b816001965096509650505050505b9193909250565b606060008267ffffffffffffffff8111156118a3576118a2611f16565b5b6040519080825280601f01601f1916602001820160405280156118d55781602001600182028036833780820191505090505b5090506000815114156118eb5780915050611984565b600084866118f99190612517565b9050600060208301905060005b6020866119139190612d37565b81101561194f578251825260208361192b9190612517565b925060208261193a9190612517565b91508080611947906124ce565b915050611906565b506000600160208781611965576119646126be565b5b066020036101000a039050808251168119845116178252839450505050505b9392505050565b606061199682611b09565b9050919050565b606081601f836119ad9190612517565b10156119ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e590612db4565b60405180910390fd5b8282846119fb9190612517565b1015611a3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a3390612db4565b60405180910390fd5b8183611a489190612517565b84511015611a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8290612e20565b60405180910390fd5b6060821560008114611aac5760405191506000825260208201604052611afd565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611aea5780518352602083019250602081019050611acd565b50868552601f19601f8301166040525050505b50809150509392505050565b6060611b1f826020015160008460000151611885565b9050919050565b604051806040016040528060608152602001606081525090565b604051806040016040528060008152602001600081525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611b9f611b9a611b9584611b5a565b611b7a565b611b5a565b9050919050565b6000611bb182611b84565b9050919050565b6000611bc382611ba6565b9050919050565b611bd381611bb8565b82525050565b6000602082019050611bee6000830184611bca565b92915050565b6000611bff82611b5a565b9050919050565b611c0f81611bf4565b82525050565b6000602082019050611c2a6000830184611c06565b92915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b611c5781611c44565b8114611c6257600080fd5b50565b600081359050611c7481611c4e565b92915050565b600060208284031215611c9057611c8f611c3a565b5b6000611c9e84828501611c65565b91505092915050565b60008115159050919050565b611cbc81611ca7565b82525050565b6000602082019050611cd76000830184611cb3565b92915050565b6000819050919050565b611cf081611cdd565b8114611cfb57600080fd5b50565b600081359050611d0d81611ce7565b92915050565b611d1c81611bf4565b8114611d2757600080fd5b50565b600081359050611d3981611d13565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611d6457611d63611d3f565b5b8235905067ffffffffffffffff811115611d8157611d80611d44565b5b602083019150836001820283011115611d9d57611d9c611d49565b5b9250929050565b600080fd5b600060808284031215611dbf57611dbe611da4565b5b81905092915050565b60008060008060008060008060008060006101808c8e031215611dee57611ded611c3a565b5b6000611dfc8e828f01611cfe565b9b50506020611e0d8e828f01611d2a565b9a50506040611e1e8e828f01611d2a565b9950506060611e2f8e828f01611cfe565b9850506080611e408e828f01611cfe565b97505060a08c013567ffffffffffffffff811115611e6157611e60611c3f565b5b611e6d8e828f01611d4e565b965096505060c0611e808e828f01611cfe565b94505060e0611e918e828f01611da9565b9350506101608c013567ffffffffffffffff811115611eb357611eb2611c3f565b5b611ebf8e828f01611d4e565b92509250509295989b509295989b9093969950565b611edd81611ca7565b8114611ee857600080fd5b50565b600081359050611efa81611ed4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611f4e82611f05565b810181811067ffffffffffffffff82111715611f6d57611f6c611f16565b5b80604052505050565b6000611f80611c30565b9050611f8c8282611f45565b919050565b600067ffffffffffffffff821115611fac57611fab611f16565b5b611fb582611f05565b9050602081019050919050565b82818337600083830152505050565b6000611fe4611fdf84611f91565b611f76565b90508281526020810184848401111561200057611fff611f00565b5b61200b848285611fc2565b509392505050565b600082601f83011261202857612027611d3f565b5b8135612038848260208601611fd1565b91505092915050565b600080600080600060a0868803121561205d5761205c611c3a565b5b600061206b88828901611d2a565b955050602061207c88828901611cfe565b945050604061208d88828901611cfe565b935050606061209e88828901611eeb565b925050608086013567ffffffffffffffff8111156120bf576120be611c3f565b5b6120cb88828901612013565b9150509295509295909350565b6120e181611cdd565b82525050565b60006020820190506120fc60008301846120d8565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561213c578082015181840152602081019050612121565b8381111561214b576000848401525b50505050565b600061215c82612102565b612166818561210d565b935061217681856020860161211e565b61217f81611f05565b840191505092915050565b600060a08201905061219f60008301886120d8565b6121ac60208301876120d8565b6121b960408301866120d8565b6121c66060830185611cb3565b81810360808301526121d88184612151565b90509695505050505050565b6000815190506121f381611c4e565b92915050565b60006020828403121561220f5761220e611c3a565b5b600061221d848285016121e4565b91505092915050565b600081905092915050565b600061223d8385612226565b935061224a838584611fc2565b82840190509392505050565b6000612263828486612231565b91508190509392505050565b61227881611c44565b82525050565b6000608082019050612293600083018761226f565b6122a0602083018661226f565b6122ad604083018561226f565b6122ba606083018461226f565b95945050505050565b60006122cf838561210d565b93506122dc838584611fc2565b6122e583611f05565b840190509392505050565b600060c082019050612305600083018a6120d8565b6123126020830189611c06565b61231f6040830188611c06565b61232c60608301876120d8565b61233960808301866120d8565b81810360a083015261234c8184866122c3565b905098975050505050505050565b600060408201905061236f600083018561226f565b61237c60208301846120d8565b9392505050565b6000819050919050565b61239e61239982611c44565b612383565b82525050565b60006123b0828461238d565b60208201915081905092915050565b600082825260208201905092915050565b7f50726f76696465642070726f6f6620697320696e76616c69642e000000000000600082015250565b6000612406601a836123bf565b9150612411826123d0565b602082019050919050565b60006020820190508181036000830152612435816123f9565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061247682611cdd565b915061248183611cdd565b9250828210156124945761249361243c565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006124d982611cdd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561250c5761250b61243c565b5b600182019050919050565b600061252282611cdd565b915061252d83611cdd565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125625761256161243c565b5b828201905092915050565b7f496e76616c696420726f6f742068617368000000000000000000000000000000600082015250565b60006125a36011836123bf565b91506125ae8261256d565b602082019050919050565b600060208201905081810360008301526125d281612596565b9050919050565b7f496e76616c6964206c6172676520696e7465726e616c20686173680000000000600082015250565b600061260f601b836123bf565b915061261a826125d9565b602082019050919050565b6000602082019050818103600083015261263e81612602565b9050919050565b7f496e76616c696420696e7465726e616c206e6f64652068617368000000000000600082015250565b600061267b601a836123bf565b915061268682612645565b602082019050919050565b600060208201905081810360008301526126aa8161266e565b9050919050565b600060ff82169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006126f8826126b1565b9150612703836126b1565b925082612713576127126126be565b5b828206905092915050565b6000612729826126b1565b9150612734836126b1565b9250828210156127475761274661243c565b5b828203905092915050565b7f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060008201527f7072656669780000000000000000000000000000000000000000000000000000602082015250565b60006127ae6026836123bf565b91506127b982612752565b604082019050919050565b600060208201905081810360008301526127dd816127a1565b9050919050565b7f526563656976656420616e20756e706172736561626c65206e6f64652e000000600082015250565b600061281a601d836123bf565b9150612825826127e4565b602082019050919050565b600060208201905081810360008301526128498161280d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f496e76616c696420524c502062797465732076616c75652e0000000000000000600082015250565b60006128b56018836123bf565b91506128c08261287f565b602082019050919050565b600060208201905081810360008301526128e4816128a8565b9050919050565b60006128f682611cdd565b915061290183611cdd565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561293a5761293961243c565b5b828202905092915050565b7f496e76616c696420524c50206c6973742076616c75652e000000000000000000600082015250565b600061297b6017836123bf565b915061298682612945565b602082019050919050565b600060208201905081810360008301526129aa8161296e565b9050919050565b7f50726f766964656420524c50206c6973742065786365656473206d6178206c6960008201527f7374206c656e6774682e00000000000000000000000000000000000000000000602082015250565b6000612a0d602a836123bf565b9150612a18826129b1565b604082019050919050565b60006020820190508181036000830152612a3c81612a00565b9050919050565b7f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000600082015250565b6000612a796018836123bf565b9150612a8482612a43565b602082019050919050565b60006020820190508181036000830152612aa881612a6c565b9050919050565b7f496e76616c696420524c502073686f727420737472696e672e00000000000000600082015250565b6000612ae56019836123bf565b9150612af082612aaf565b602082019050919050565b60006020820190508181036000830152612b1481612ad8565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00600082015250565b6000612b51601f836123bf565b9150612b5c82612b1b565b602082019050919050565b60006020820190508181036000830152612b8081612b44565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000600082015250565b6000612bbd6018836123bf565b9150612bc882612b87565b602082019050919050565b60006020820190508181036000830152612bec81612bb0565b9050919050565b7f496e76616c696420524c502073686f7274206c6973742e000000000000000000600082015250565b6000612c296017836123bf565b9150612c3482612bf3565b602082019050919050565b60006020820190508181036000830152612c5881612c1c565b9050919050565b7f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000600082015250565b6000612c95601d836123bf565b9150612ca082612c5f565b602082019050919050565b60006020820190508181036000830152612cc481612c88565b9050919050565b7f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000600082015250565b6000612d016016836123bf565b9150612d0c82612ccb565b602082019050919050565b60006020820190508181036000830152612d3081612cf4565b9050919050565b6000612d4282611cdd565b9150612d4d83611cdd565b925082612d5d57612d5c6126be565b5b828204905092915050565b7f736c6963655f6f766572666c6f77000000000000000000000000000000000000600082015250565b6000612d9e600e836123bf565b9150612da982612d68565b602082019050919050565b60006020820190508181036000830152612dcd81612d91565b9050919050565b7f736c6963655f6f75744f66426f756e6473000000000000000000000000000000600082015250565b6000612e0a6011836123bf565b9150612e1582612dd4565b602082019050919050565b60006020820190508181036000830152612e3981612dfd565b905091905056fea2646970667358221220476f1b0a95f0a876e335daed5cca410381992c0577e2b5bd936c3a5060def44964736f6c634300080a0033", +} + +// OptimismPortalABI is the input ABI used to generate the binding from. +// Deprecated: Use OptimismPortalMetaData.ABI instead. +var OptimismPortalABI = OptimismPortalMetaData.ABI + +// OptimismPortalBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use OptimismPortalMetaData.Bin instead. +var OptimismPortalBin = OptimismPortalMetaData.Bin + +// DeployOptimismPortal deploys a new Ethereum contract, binding an instance of OptimismPortal to it. +func DeployOptimismPortal(auth *bind.TransactOpts, backend bind.ContractBackend, _l2Oracle common.Address, _finalizationPeriod *big.Int) (common.Address, *types.Transaction, *OptimismPortal, error) { + parsed, err := OptimismPortalMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OptimismPortalBin), backend, _l2Oracle, _finalizationPeriod) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OptimismPortal{OptimismPortalCaller: OptimismPortalCaller{contract: contract}, OptimismPortalTransactor: OptimismPortalTransactor{contract: contract}, OptimismPortalFilterer: OptimismPortalFilterer{contract: contract}}, nil +} + +// OptimismPortal is an auto generated Go binding around an Ethereum contract. +type OptimismPortal struct { + OptimismPortalCaller // Read-only binding to the contract + OptimismPortalTransactor // Write-only binding to the contract + OptimismPortalFilterer // Log filterer for contract events +} + +// OptimismPortalCaller is an auto generated read-only Go binding around an Ethereum contract. +type OptimismPortalCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptimismPortalTransactor is an auto generated write-only Go binding around an Ethereum contract. +type OptimismPortalTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptimismPortalFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OptimismPortalFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptimismPortalSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type OptimismPortalSession struct { + Contract *OptimismPortal // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OptimismPortalCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type OptimismPortalCallerSession struct { + Contract *OptimismPortalCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// OptimismPortalTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type OptimismPortalTransactorSession struct { + Contract *OptimismPortalTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OptimismPortalRaw is an auto generated low-level Go binding around an Ethereum contract. +type OptimismPortalRaw struct { + Contract *OptimismPortal // Generic contract binding to access the raw methods on +} + +// OptimismPortalCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OptimismPortalCallerRaw struct { + Contract *OptimismPortalCaller // Generic read-only contract binding to access the raw methods on +} + +// OptimismPortalTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OptimismPortalTransactorRaw struct { + Contract *OptimismPortalTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewOptimismPortal creates a new instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortal(address common.Address, backend bind.ContractBackend) (*OptimismPortal, error) { + contract, err := bindOptimismPortal(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OptimismPortal{OptimismPortalCaller: OptimismPortalCaller{contract: contract}, OptimismPortalTransactor: OptimismPortalTransactor{contract: contract}, OptimismPortalFilterer: OptimismPortalFilterer{contract: contract}}, nil +} + +// NewOptimismPortalCaller creates a new read-only instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortalCaller(address common.Address, caller bind.ContractCaller) (*OptimismPortalCaller, error) { + contract, err := bindOptimismPortal(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OptimismPortalCaller{contract: contract}, nil +} + +// NewOptimismPortalTransactor creates a new write-only instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortalTransactor(address common.Address, transactor bind.ContractTransactor) (*OptimismPortalTransactor, error) { + contract, err := bindOptimismPortal(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OptimismPortalTransactor{contract: contract}, nil +} + +// NewOptimismPortalFilterer creates a new log filterer instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortalFilterer(address common.Address, filterer bind.ContractFilterer) (*OptimismPortalFilterer, error) { + contract, err := bindOptimismPortal(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OptimismPortalFilterer{contract: contract}, nil +} + +// bindOptimismPortal binds a generic wrapper to an already deployed contract. +func bindOptimismPortal(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(OptimismPortalABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_OptimismPortal *OptimismPortalRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismPortal.Contract.OptimismPortalCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_OptimismPortal *OptimismPortalRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal.Contract.OptimismPortalTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OptimismPortal *OptimismPortalRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismPortal.Contract.OptimismPortalTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_OptimismPortal *OptimismPortalCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismPortal.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_OptimismPortal *OptimismPortalTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OptimismPortal *OptimismPortalTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismPortal.Contract.contract.Transact(opts, method, params...) +} + +// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. +// +// Solidity: function FINALIZATION_PERIOD() view returns(uint256) +func (_OptimismPortal *OptimismPortalCaller) FINALIZATIONPERIOD(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _OptimismPortal.contract.Call(opts, &out, "FINALIZATION_PERIOD") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. +// +// Solidity: function FINALIZATION_PERIOD() view returns(uint256) +func (_OptimismPortal *OptimismPortalSession) FINALIZATIONPERIOD() (*big.Int, error) { + return _OptimismPortal.Contract.FINALIZATIONPERIOD(&_OptimismPortal.CallOpts) +} + +// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. +// +// Solidity: function FINALIZATION_PERIOD() view returns(uint256) +func (_OptimismPortal *OptimismPortalCallerSession) FINALIZATIONPERIOD() (*big.Int, error) { + return _OptimismPortal.Contract.FINALIZATIONPERIOD(&_OptimismPortal.CallOpts) +} + +// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. +// +// Solidity: function L2_ORACLE() view returns(address) +func (_OptimismPortal *OptimismPortalCaller) L2ORACLE(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal.contract.Call(opts, &out, "L2_ORACLE") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. +// +// Solidity: function L2_ORACLE() view returns(address) +func (_OptimismPortal *OptimismPortalSession) L2ORACLE() (common.Address, error) { + return _OptimismPortal.Contract.L2ORACLE(&_OptimismPortal.CallOpts) +} + +// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. +// +// Solidity: function L2_ORACLE() view returns(address) +func (_OptimismPortal *OptimismPortalCallerSession) L2ORACLE() (common.Address, error) { + return _OptimismPortal.Contract.L2ORACLE(&_OptimismPortal.CallOpts) +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_OptimismPortal *OptimismPortalCaller) FinalizedWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _OptimismPortal.contract.Call(opts, &out, "finalizedWithdrawals", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_OptimismPortal *OptimismPortalSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _OptimismPortal.Contract.FinalizedWithdrawals(&_OptimismPortal.CallOpts, arg0) +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_OptimismPortal *OptimismPortalCallerSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _OptimismPortal.Contract.FinalizedWithdrawals(&_OptimismPortal.CallOpts, arg0) +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_OptimismPortal *OptimismPortalCaller) L2Sender(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal.contract.Call(opts, &out, "l2Sender") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_OptimismPortal *OptimismPortalSession) L2Sender() (common.Address, error) { + return _OptimismPortal.Contract.L2Sender(&_OptimismPortal.CallOpts) +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_OptimismPortal *OptimismPortalCallerSession) L2Sender() (common.Address, error) { + return _OptimismPortal.Contract.L2Sender(&_OptimismPortal.CallOpts) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. +// +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() +func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. +// +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() +func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. +// +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() +func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal *OptimismPortalTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal *OptimismPortalSession) Receive() (*types.Transaction, error) { + return _OptimismPortal.Contract.Receive(&_OptimismPortal.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal *OptimismPortalTransactorSession) Receive() (*types.Transaction, error) { + return _OptimismPortal.Contract.Receive(&_OptimismPortal.TransactOpts) +} + +// OptimismPortalTransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the OptimismPortal contract. +type OptimismPortalTransactionDepositedIterator struct { + Event *OptimismPortalTransactionDeposited // 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 *OptimismPortalTransactionDepositedIterator) 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(OptimismPortalTransactionDeposited) + 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(OptimismPortalTransactionDeposited) + 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 *OptimismPortalTransactionDepositedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortalTransactionDepositedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortalTransactionDeposited represents a TransactionDeposited event raised by the OptimismPortal contract. +type OptimismPortalTransactionDeposited struct { + From common.Address + To common.Address + Mint *big.Int + Value *big.Int + GasLimit *big.Int + IsCreation bool + Data []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +func (_OptimismPortal *OptimismPortalFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismPortalTransactionDepositedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule) + if err != nil { + return nil, err + } + return &OptimismPortalTransactionDepositedIterator{contract: _OptimismPortal.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil +} + +// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +func (_OptimismPortal *OptimismPortalFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *OptimismPortalTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule) + 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(OptimismPortalTransactionDeposited) + if err := _OptimismPortal.contract.UnpackLog(event, "TransactionDeposited", 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 +} + +// ParseTransactionDeposited is a log parse operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +func (_OptimismPortal *OptimismPortalFilterer) ParseTransactionDeposited(log types.Log) (*OptimismPortalTransactionDeposited, error) { + event := new(OptimismPortalTransactionDeposited) + if err := _OptimismPortal.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OptimismPortalWithdrawalFinalizedIterator is returned from FilterWithdrawalFinalized and is used to iterate over the raw logs and unpacked data for WithdrawalFinalized events raised by the OptimismPortal contract. +type OptimismPortalWithdrawalFinalizedIterator struct { + Event *OptimismPortalWithdrawalFinalized // 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 *OptimismPortalWithdrawalFinalizedIterator) 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(OptimismPortalWithdrawalFinalized) + 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(OptimismPortalWithdrawalFinalized) + 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 *OptimismPortalWithdrawalFinalizedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortalWithdrawalFinalizedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortalWithdrawalFinalized represents a WithdrawalFinalized event raised by the OptimismPortal contract. +type OptimismPortalWithdrawalFinalized struct { + Arg0 [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawalFinalized is a free log retrieval operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +func (_OptimismPortal *OptimismPortalFilterer) FilterWithdrawalFinalized(opts *bind.FilterOpts, arg0 [][32]byte) (*OptimismPortalWithdrawalFinalizedIterator, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _OptimismPortal.contract.FilterLogs(opts, "WithdrawalFinalized", arg0Rule) + if err != nil { + return nil, err + } + return &OptimismPortalWithdrawalFinalizedIterator{contract: _OptimismPortal.contract, event: "WithdrawalFinalized", logs: logs, sub: sub}, nil +} + +// WatchWithdrawalFinalized is a free log subscription operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +func (_OptimismPortal *OptimismPortalFilterer) WatchWithdrawalFinalized(opts *bind.WatchOpts, sink chan<- *OptimismPortalWithdrawalFinalized, arg0 [][32]byte) (event.Subscription, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _OptimismPortal.contract.WatchLogs(opts, "WithdrawalFinalized", arg0Rule) + 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(OptimismPortalWithdrawalFinalized) + if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalFinalized", 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 +} + +// ParseWithdrawalFinalized is a log parse operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +func (_OptimismPortal *OptimismPortalFilterer) ParseWithdrawalFinalized(log types.Log) (*OptimismPortalWithdrawalFinalized, error) { + event := new(OptimismPortalWithdrawalFinalized) + if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OwnableMetaData contains all meta data concerning the Ownable contract. +var OwnableMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// OwnableABI is the input ABI used to generate the binding from. +// Deprecated: Use OwnableMetaData.ABI instead. +var OwnableABI = OwnableMetaData.ABI + +// Ownable is an auto generated Go binding around an Ethereum contract. +type Ownable struct { + OwnableCaller // Read-only binding to the contract + OwnableTransactor // Write-only binding to the contract + OwnableFilterer // Log filterer for contract events +} + +// OwnableCaller is an auto generated read-only Go binding around an Ethereum contract. +type OwnableCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type OwnableTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OwnableFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type OwnableSession struct { + Contract *Ownable // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OwnableCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type OwnableCallerSession struct { + Contract *OwnableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// OwnableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type OwnableTransactorSession struct { + Contract *OwnableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OwnableRaw is an auto generated low-level Go binding around an Ethereum contract. +type OwnableRaw struct { + Contract *Ownable // Generic contract binding to access the raw methods on +} + +// OwnableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OwnableCallerRaw struct { + Contract *OwnableCaller // Generic read-only contract binding to access the raw methods on +} + +// OwnableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OwnableTransactorRaw struct { + Contract *OwnableTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewOwnable creates a new instance of Ownable, bound to a specific deployed contract. +func NewOwnable(address common.Address, backend bind.ContractBackend) (*Ownable, error) { + contract, err := bindOwnable(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Ownable{OwnableCaller: OwnableCaller{contract: contract}, OwnableTransactor: OwnableTransactor{contract: contract}, OwnableFilterer: OwnableFilterer{contract: contract}}, nil +} + +// NewOwnableCaller creates a new read-only instance of Ownable, bound to a specific deployed contract. +func NewOwnableCaller(address common.Address, caller bind.ContractCaller) (*OwnableCaller, error) { + contract, err := bindOwnable(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OwnableCaller{contract: contract}, nil +} + +// NewOwnableTransactor creates a new write-only instance of Ownable, bound to a specific deployed contract. +func NewOwnableTransactor(address common.Address, transactor bind.ContractTransactor) (*OwnableTransactor, error) { + contract, err := bindOwnable(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OwnableTransactor{contract: contract}, nil +} + +// NewOwnableFilterer creates a new log filterer instance of Ownable, bound to a specific deployed contract. +func NewOwnableFilterer(address common.Address, filterer bind.ContractFilterer) (*OwnableFilterer, error) { + contract, err := bindOwnable(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OwnableFilterer{contract: contract}, nil +} + +// bindOwnable binds a generic wrapper to an already deployed contract. +func bindOwnable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(OwnableABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ownable *OwnableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ownable.Contract.OwnableCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ownable *OwnableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.Contract.OwnableTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ownable *OwnableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ownable.Contract.OwnableTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ownable *OwnableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ownable.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ownable *OwnableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ownable *OwnableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ownable.Contract.contract.Transact(opts, method, params...) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Ownable.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableSession) Owner() (common.Address, error) { + return _Ownable.Contract.Owner(&_Ownable.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableCallerSession) Owner() (common.Address, error) { + return _Ownable.Contract.Owner(&_Ownable.CallOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Ownable *OwnableTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Ownable *OwnableSession) RenounceOwnership() (*types.Transaction, error) { + return _Ownable.Contract.RenounceOwnership(&_Ownable.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Ownable *OwnableTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Ownable.Contract.RenounceOwnership(&_Ownable.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Ownable.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) +} + +// OwnableOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Ownable contract. +type OwnableOwnershipTransferredIterator struct { + Event *OwnableOwnershipTransferred // 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 *OwnableOwnershipTransferredIterator) 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(OwnableOwnershipTransferred) + 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(OwnableOwnershipTransferred) + 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 *OwnableOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OwnableOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OwnableOwnershipTransferred represents a OwnershipTransferred event raised by the Ownable contract. +type OwnableOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Ownable *OwnableFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*OwnableOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Ownable.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &OwnableOwnershipTransferredIterator{contract: _Ownable.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Ownable *OwnableFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OwnableOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Ownable.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(OwnableOwnershipTransferred) + if err := _Ownable.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Ownable *OwnableFilterer) ParseOwnershipTransferred(log types.Log) (*OwnableOwnershipTransferred, error) { + event := new(OwnableOwnershipTransferred) + if err := _Ownable.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// WithdrawalVerifierMetaData contains all meta data concerning the WithdrawalVerifier contract. +var WithdrawalVerifierMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212203fefb10a3ca14596cd54a35ac033725fc08679d4c580652ab8e765249653bb8c64736f6c634300080a0033", +} + +// WithdrawalVerifierABI is the input ABI used to generate the binding from. +// Deprecated: Use WithdrawalVerifierMetaData.ABI instead. +var WithdrawalVerifierABI = WithdrawalVerifierMetaData.ABI + +// WithdrawalVerifierBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use WithdrawalVerifierMetaData.Bin instead. +var WithdrawalVerifierBin = WithdrawalVerifierMetaData.Bin + +// DeployWithdrawalVerifier deploys a new Ethereum contract, binding an instance of WithdrawalVerifier to it. +func DeployWithdrawalVerifier(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *WithdrawalVerifier, error) { + parsed, err := WithdrawalVerifierMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(WithdrawalVerifierBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &WithdrawalVerifier{WithdrawalVerifierCaller: WithdrawalVerifierCaller{contract: contract}, WithdrawalVerifierTransactor: WithdrawalVerifierTransactor{contract: contract}, WithdrawalVerifierFilterer: WithdrawalVerifierFilterer{contract: contract}}, nil +} + +// WithdrawalVerifier is an auto generated Go binding around an Ethereum contract. +type WithdrawalVerifier struct { + WithdrawalVerifierCaller // Read-only binding to the contract + WithdrawalVerifierTransactor // Write-only binding to the contract + WithdrawalVerifierFilterer // Log filterer for contract events +} + +// WithdrawalVerifierCaller is an auto generated read-only Go binding around an Ethereum contract. +type WithdrawalVerifierCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawalVerifierTransactor is an auto generated write-only Go binding around an Ethereum contract. +type WithdrawalVerifierTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawalVerifierFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type WithdrawalVerifierFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawalVerifierSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type WithdrawalVerifierSession struct { + Contract *WithdrawalVerifier // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WithdrawalVerifierCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type WithdrawalVerifierCallerSession struct { + Contract *WithdrawalVerifierCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// WithdrawalVerifierTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type WithdrawalVerifierTransactorSession struct { + Contract *WithdrawalVerifierTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WithdrawalVerifierRaw is an auto generated low-level Go binding around an Ethereum contract. +type WithdrawalVerifierRaw struct { + Contract *WithdrawalVerifier // Generic contract binding to access the raw methods on +} + +// WithdrawalVerifierCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type WithdrawalVerifierCallerRaw struct { + Contract *WithdrawalVerifierCaller // Generic read-only contract binding to access the raw methods on +} + +// WithdrawalVerifierTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type WithdrawalVerifierTransactorRaw struct { + Contract *WithdrawalVerifierTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewWithdrawalVerifier creates a new instance of WithdrawalVerifier, bound to a specific deployed contract. +func NewWithdrawalVerifier(address common.Address, backend bind.ContractBackend) (*WithdrawalVerifier, error) { + contract, err := bindWithdrawalVerifier(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &WithdrawalVerifier{WithdrawalVerifierCaller: WithdrawalVerifierCaller{contract: contract}, WithdrawalVerifierTransactor: WithdrawalVerifierTransactor{contract: contract}, WithdrawalVerifierFilterer: WithdrawalVerifierFilterer{contract: contract}}, nil +} + +// NewWithdrawalVerifierCaller creates a new read-only instance of WithdrawalVerifier, bound to a specific deployed contract. +func NewWithdrawalVerifierCaller(address common.Address, caller bind.ContractCaller) (*WithdrawalVerifierCaller, error) { + contract, err := bindWithdrawalVerifier(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &WithdrawalVerifierCaller{contract: contract}, nil +} + +// NewWithdrawalVerifierTransactor creates a new write-only instance of WithdrawalVerifier, bound to a specific deployed contract. +func NewWithdrawalVerifierTransactor(address common.Address, transactor bind.ContractTransactor) (*WithdrawalVerifierTransactor, error) { + contract, err := bindWithdrawalVerifier(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &WithdrawalVerifierTransactor{contract: contract}, nil +} + +// NewWithdrawalVerifierFilterer creates a new log filterer instance of WithdrawalVerifier, bound to a specific deployed contract. +func NewWithdrawalVerifierFilterer(address common.Address, filterer bind.ContractFilterer) (*WithdrawalVerifierFilterer, error) { + contract, err := bindWithdrawalVerifier(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &WithdrawalVerifierFilterer{contract: contract}, nil +} + +// bindWithdrawalVerifier binds a generic wrapper to an already deployed contract. +func bindWithdrawalVerifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(WithdrawalVerifierABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_WithdrawalVerifier *WithdrawalVerifierRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _WithdrawalVerifier.Contract.WithdrawalVerifierCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_WithdrawalVerifier *WithdrawalVerifierRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WithdrawalVerifier.Contract.WithdrawalVerifierTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_WithdrawalVerifier *WithdrawalVerifierRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _WithdrawalVerifier.Contract.WithdrawalVerifierTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_WithdrawalVerifier *WithdrawalVerifierCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _WithdrawalVerifier.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_WithdrawalVerifier *WithdrawalVerifierTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WithdrawalVerifier.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_WithdrawalVerifier *WithdrawalVerifierTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _WithdrawalVerifier.Contract.contract.Transact(opts, method, params...) +} + +// WithdrawalsRelayMetaData contains all meta data concerning the WithdrawalsRelay contract. +var WithdrawalsRelayMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// WithdrawalsRelayABI is the input ABI used to generate the binding from. +// Deprecated: Use WithdrawalsRelayMetaData.ABI instead. +var WithdrawalsRelayABI = WithdrawalsRelayMetaData.ABI + +// WithdrawalsRelay is an auto generated Go binding around an Ethereum contract. +type WithdrawalsRelay struct { + WithdrawalsRelayCaller // Read-only binding to the contract + WithdrawalsRelayTransactor // Write-only binding to the contract + WithdrawalsRelayFilterer // Log filterer for contract events +} + +// WithdrawalsRelayCaller is an auto generated read-only Go binding around an Ethereum contract. +type WithdrawalsRelayCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawalsRelayTransactor is an auto generated write-only Go binding around an Ethereum contract. +type WithdrawalsRelayTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawalsRelayFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type WithdrawalsRelayFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawalsRelaySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type WithdrawalsRelaySession struct { + Contract *WithdrawalsRelay // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WithdrawalsRelayCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type WithdrawalsRelayCallerSession struct { + Contract *WithdrawalsRelayCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// WithdrawalsRelayTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type WithdrawalsRelayTransactorSession struct { + Contract *WithdrawalsRelayTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WithdrawalsRelayRaw is an auto generated low-level Go binding around an Ethereum contract. +type WithdrawalsRelayRaw struct { + Contract *WithdrawalsRelay // Generic contract binding to access the raw methods on +} + +// WithdrawalsRelayCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type WithdrawalsRelayCallerRaw struct { + Contract *WithdrawalsRelayCaller // Generic read-only contract binding to access the raw methods on +} + +// WithdrawalsRelayTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type WithdrawalsRelayTransactorRaw struct { + Contract *WithdrawalsRelayTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewWithdrawalsRelay creates a new instance of WithdrawalsRelay, bound to a specific deployed contract. +func NewWithdrawalsRelay(address common.Address, backend bind.ContractBackend) (*WithdrawalsRelay, error) { + contract, err := bindWithdrawalsRelay(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &WithdrawalsRelay{WithdrawalsRelayCaller: WithdrawalsRelayCaller{contract: contract}, WithdrawalsRelayTransactor: WithdrawalsRelayTransactor{contract: contract}, WithdrawalsRelayFilterer: WithdrawalsRelayFilterer{contract: contract}}, nil +} + +// NewWithdrawalsRelayCaller creates a new read-only instance of WithdrawalsRelay, bound to a specific deployed contract. +func NewWithdrawalsRelayCaller(address common.Address, caller bind.ContractCaller) (*WithdrawalsRelayCaller, error) { + contract, err := bindWithdrawalsRelay(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &WithdrawalsRelayCaller{contract: contract}, nil +} + +// NewWithdrawalsRelayTransactor creates a new write-only instance of WithdrawalsRelay, bound to a specific deployed contract. +func NewWithdrawalsRelayTransactor(address common.Address, transactor bind.ContractTransactor) (*WithdrawalsRelayTransactor, error) { + contract, err := bindWithdrawalsRelay(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &WithdrawalsRelayTransactor{contract: contract}, nil +} + +// NewWithdrawalsRelayFilterer creates a new log filterer instance of WithdrawalsRelay, bound to a specific deployed contract. +func NewWithdrawalsRelayFilterer(address common.Address, filterer bind.ContractFilterer) (*WithdrawalsRelayFilterer, error) { + contract, err := bindWithdrawalsRelay(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &WithdrawalsRelayFilterer{contract: contract}, nil +} + +// bindWithdrawalsRelay binds a generic wrapper to an already deployed contract. +func bindWithdrawalsRelay(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(WithdrawalsRelayABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_WithdrawalsRelay *WithdrawalsRelayRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _WithdrawalsRelay.Contract.WithdrawalsRelayCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_WithdrawalsRelay *WithdrawalsRelayRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WithdrawalsRelay.Contract.WithdrawalsRelayTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_WithdrawalsRelay *WithdrawalsRelayRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _WithdrawalsRelay.Contract.WithdrawalsRelayTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_WithdrawalsRelay *WithdrawalsRelayCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _WithdrawalsRelay.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_WithdrawalsRelay *WithdrawalsRelayTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WithdrawalsRelay.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_WithdrawalsRelay *WithdrawalsRelayTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _WithdrawalsRelay.Contract.contract.Transact(opts, method, params...) +} + +// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. +// +// Solidity: function FINALIZATION_PERIOD() view returns(uint256) +func (_WithdrawalsRelay *WithdrawalsRelayCaller) FINALIZATIONPERIOD(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _WithdrawalsRelay.contract.Call(opts, &out, "FINALIZATION_PERIOD") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. +// +// Solidity: function FINALIZATION_PERIOD() view returns(uint256) +func (_WithdrawalsRelay *WithdrawalsRelaySession) FINALIZATIONPERIOD() (*big.Int, error) { + return _WithdrawalsRelay.Contract.FINALIZATIONPERIOD(&_WithdrawalsRelay.CallOpts) +} + +// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. +// +// Solidity: function FINALIZATION_PERIOD() view returns(uint256) +func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) FINALIZATIONPERIOD() (*big.Int, error) { + return _WithdrawalsRelay.Contract.FINALIZATIONPERIOD(&_WithdrawalsRelay.CallOpts) +} + +// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. +// +// Solidity: function L2_ORACLE() view returns(address) +func (_WithdrawalsRelay *WithdrawalsRelayCaller) L2ORACLE(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _WithdrawalsRelay.contract.Call(opts, &out, "L2_ORACLE") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. +// +// Solidity: function L2_ORACLE() view returns(address) +func (_WithdrawalsRelay *WithdrawalsRelaySession) L2ORACLE() (common.Address, error) { + return _WithdrawalsRelay.Contract.L2ORACLE(&_WithdrawalsRelay.CallOpts) +} + +// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. +// +// Solidity: function L2_ORACLE() view returns(address) +func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) L2ORACLE() (common.Address, error) { + return _WithdrawalsRelay.Contract.L2ORACLE(&_WithdrawalsRelay.CallOpts) +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_WithdrawalsRelay *WithdrawalsRelayCaller) FinalizedWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _WithdrawalsRelay.contract.Call(opts, &out, "finalizedWithdrawals", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_WithdrawalsRelay *WithdrawalsRelaySession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _WithdrawalsRelay.Contract.FinalizedWithdrawals(&_WithdrawalsRelay.CallOpts, arg0) +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _WithdrawalsRelay.Contract.FinalizedWithdrawals(&_WithdrawalsRelay.CallOpts, arg0) +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_WithdrawalsRelay *WithdrawalsRelayCaller) L2Sender(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _WithdrawalsRelay.contract.Call(opts, &out, "l2Sender") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_WithdrawalsRelay *WithdrawalsRelaySession) L2Sender() (common.Address, error) { + return _WithdrawalsRelay.Contract.L2Sender(&_WithdrawalsRelay.CallOpts) +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) L2Sender() (common.Address, error) { + return _WithdrawalsRelay.Contract.L2Sender(&_WithdrawalsRelay.CallOpts) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. +// +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() +func (_WithdrawalsRelay *WithdrawalsRelayTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _WithdrawalsRelay.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. +// +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() +func (_WithdrawalsRelay *WithdrawalsRelaySession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _WithdrawalsRelay.Contract.FinalizeWithdrawalTransaction(&_WithdrawalsRelay.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. +// +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() +func (_WithdrawalsRelay *WithdrawalsRelayTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _WithdrawalsRelay.Contract.FinalizeWithdrawalTransaction(&_WithdrawalsRelay.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +} + +// WithdrawalsRelayWithdrawalFinalizedIterator is returned from FilterWithdrawalFinalized and is used to iterate over the raw logs and unpacked data for WithdrawalFinalized events raised by the WithdrawalsRelay contract. +type WithdrawalsRelayWithdrawalFinalizedIterator struct { + Event *WithdrawalsRelayWithdrawalFinalized // 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 *WithdrawalsRelayWithdrawalFinalizedIterator) 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(WithdrawalsRelayWithdrawalFinalized) + 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(WithdrawalsRelayWithdrawalFinalized) + 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 *WithdrawalsRelayWithdrawalFinalizedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *WithdrawalsRelayWithdrawalFinalizedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// WithdrawalsRelayWithdrawalFinalized represents a WithdrawalFinalized event raised by the WithdrawalsRelay contract. +type WithdrawalsRelayWithdrawalFinalized struct { + Arg0 [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawalFinalized is a free log retrieval operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +func (_WithdrawalsRelay *WithdrawalsRelayFilterer) FilterWithdrawalFinalized(opts *bind.FilterOpts, arg0 [][32]byte) (*WithdrawalsRelayWithdrawalFinalizedIterator, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _WithdrawalsRelay.contract.FilterLogs(opts, "WithdrawalFinalized", arg0Rule) + if err != nil { + return nil, err + } + return &WithdrawalsRelayWithdrawalFinalizedIterator{contract: _WithdrawalsRelay.contract, event: "WithdrawalFinalized", logs: logs, sub: sub}, nil +} + +// WatchWithdrawalFinalized is a free log subscription operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +func (_WithdrawalsRelay *WithdrawalsRelayFilterer) WatchWithdrawalFinalized(opts *bind.WatchOpts, sink chan<- *WithdrawalsRelayWithdrawalFinalized, arg0 [][32]byte) (event.Subscription, error) { + + var arg0Rule []interface{} + for _, arg0Item := range arg0 { + arg0Rule = append(arg0Rule, arg0Item) + } + + logs, sub, err := _WithdrawalsRelay.contract.WatchLogs(opts, "WithdrawalFinalized", arg0Rule) + 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(WithdrawalsRelayWithdrawalFinalized) + if err := _WithdrawalsRelay.contract.UnpackLog(event, "WithdrawalFinalized", 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 +} + +// ParseWithdrawalFinalized is a log parse operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +func (_WithdrawalsRelay *WithdrawalsRelayFilterer) ParseWithdrawalFinalized(log types.Log) (*WithdrawalsRelayWithdrawalFinalized, error) { + event := new(WithdrawalsRelayWithdrawalFinalized) + if err := _WithdrawalsRelay.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { return nil, err } event.Raw = log diff --git a/opnode/contracts/doc.go b/opnode/contracts/doc.go index 015f3d8b65e9..075c04dc7f17 100644 --- a/opnode/contracts/doc.go +++ b/opnode/contracts/doc.go @@ -4,7 +4,7 @@ The contracts package provides Go bindings for our contracts. To regenerate the bindings, run `make` -The following programs are required: `jq`, `abigen`, and having run `yarn build` in the contracts directory. +The following programs are required: `jq`, `abigen`, and `solc` (at version 0.8.10) */ package contracts diff --git a/opnode/contracts/l1block/l1_block_info_deployed.go b/opnode/contracts/l1block/l1_block_info_deployed.go index 32b797d19171..9d5b0387dba4 100644 --- a/opnode/contracts/l1block/l1_block_info_deployed.go +++ b/opnode/contracts/l1block/l1_block_info_deployed.go @@ -2,4 +2,4 @@ // This file is a generated binding and any manual changes will be lost. package l1block -var L1blockDeployedBin = "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033" +var L1blockDeployedBin = "608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220223f4770a19b9fba63f4604d9ad8c075ca4f396c2d57476d208c9414ec7f831464736f6c634300080a0033" diff --git a/opnode/contracts/l1block/l1_block_info_raw.go b/opnode/contracts/l1block/l1_block_info_raw.go index 6653114f45bd..2c2ad0e861dc 100644 --- a/opnode/contracts/l1block/l1_block_info_raw.go +++ b/opnode/contracts/l1block/l1_block_info_raw.go @@ -28,23 +28,23 @@ var ( _ = event.NewSubscription ) -// L1blockMetaData contains all meta data concerning the L1block contract. -var L1blockMetaData = &bind.MetaData{ +// L1BlockMetaData contains all meta data concerning the L1Block contract. +var L1BlockMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220cdaea4f1ee477c3fe7f1b3caa2283ad58d53d6a652006ec9e6f6bf22354b258264736f6c634300080a0033", + Bin: "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220223f4770a19b9fba63f4604d9ad8c075ca4f396c2d57476d208c9414ec7f831464736f6c634300080a0033", } -// L1blockABI is the input ABI used to generate the binding from. -// Deprecated: Use L1blockMetaData.ABI instead. -var L1blockABI = L1blockMetaData.ABI +// L1BlockABI is the input ABI used to generate the binding from. +// Deprecated: Use L1BlockMetaData.ABI instead. +var L1BlockABI = L1BlockMetaData.ABI -// L1blockBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use L1blockMetaData.Bin instead. -var L1blockBin = L1blockMetaData.Bin +// L1BlockBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use L1BlockMetaData.Bin instead. +var L1BlockBin = L1BlockMetaData.Bin -// DeployL1block deploys a new Ethereum contract, binding an instance of L1block to it. -func DeployL1block(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *L1block, error) { - parsed, err := L1blockMetaData.GetAbi() +// DeployL1Block deploys a new Ethereum contract, binding an instance of L1Block to it. +func DeployL1Block(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *L1Block, error) { + parsed, err := L1BlockMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -52,111 +52,111 @@ func DeployL1block(auth *bind.TransactOpts, backend bind.ContractBackend) (commo return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L1blockBin), backend) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L1BlockBin), backend) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &L1block{L1blockCaller: L1blockCaller{contract: contract}, L1blockTransactor: L1blockTransactor{contract: contract}, L1blockFilterer: L1blockFilterer{contract: contract}}, nil + return address, tx, &L1Block{L1BlockCaller: L1BlockCaller{contract: contract}, L1BlockTransactor: L1BlockTransactor{contract: contract}, L1BlockFilterer: L1BlockFilterer{contract: contract}}, nil } -// L1block is an auto generated Go binding around an Ethereum contract. -type L1block struct { - L1blockCaller // Read-only binding to the contract - L1blockTransactor // Write-only binding to the contract - L1blockFilterer // Log filterer for contract events +// L1Block is an auto generated Go binding around an Ethereum contract. +type L1Block struct { + L1BlockCaller // Read-only binding to the contract + L1BlockTransactor // Write-only binding to the contract + L1BlockFilterer // Log filterer for contract events } -// L1blockCaller is an auto generated read-only Go binding around an Ethereum contract. -type L1blockCaller struct { +// L1BlockCaller is an auto generated read-only Go binding around an Ethereum contract. +type L1BlockCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// L1blockTransactor is an auto generated write-only Go binding around an Ethereum contract. -type L1blockTransactor struct { +// L1BlockTransactor is an auto generated write-only Go binding around an Ethereum contract. +type L1BlockTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// L1blockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type L1blockFilterer struct { +// L1BlockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type L1BlockFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// L1blockSession is an auto generated Go binding around an Ethereum contract, +// L1BlockSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. -type L1blockSession struct { - Contract *L1block // Generic contract binding to set the session for +type L1BlockSession struct { + Contract *L1Block // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// L1blockCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// L1BlockCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. -type L1blockCallerSession struct { - Contract *L1blockCaller // Generic contract caller binding to set the session for +type L1BlockCallerSession struct { + Contract *L1BlockCaller // Generic contract caller binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session } -// L1blockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// L1BlockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. -type L1blockTransactorSession struct { - Contract *L1blockTransactor // Generic contract transactor binding to set the session for +type L1BlockTransactorSession struct { + Contract *L1BlockTransactor // Generic contract transactor binding to set the session for TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// L1blockRaw is an auto generated low-level Go binding around an Ethereum contract. -type L1blockRaw struct { - Contract *L1block // Generic contract binding to access the raw methods on +// L1BlockRaw is an auto generated low-level Go binding around an Ethereum contract. +type L1BlockRaw struct { + Contract *L1Block // Generic contract binding to access the raw methods on } -// L1blockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type L1blockCallerRaw struct { - Contract *L1blockCaller // Generic read-only contract binding to access the raw methods on +// L1BlockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type L1BlockCallerRaw struct { + Contract *L1BlockCaller // Generic read-only contract binding to access the raw methods on } -// L1blockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type L1blockTransactorRaw struct { - Contract *L1blockTransactor // Generic write-only contract binding to access the raw methods on +// L1BlockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type L1BlockTransactorRaw struct { + Contract *L1BlockTransactor // Generic write-only contract binding to access the raw methods on } -// NewL1block creates a new instance of L1block, bound to a specific deployed contract. -func NewL1block(address common.Address, backend bind.ContractBackend) (*L1block, error) { - contract, err := bindL1block(address, backend, backend, backend) +// NewL1Block creates a new instance of L1Block, bound to a specific deployed contract. +func NewL1Block(address common.Address, backend bind.ContractBackend) (*L1Block, error) { + contract, err := bindL1Block(address, backend, backend, backend) if err != nil { return nil, err } - return &L1block{L1blockCaller: L1blockCaller{contract: contract}, L1blockTransactor: L1blockTransactor{contract: contract}, L1blockFilterer: L1blockFilterer{contract: contract}}, nil + return &L1Block{L1BlockCaller: L1BlockCaller{contract: contract}, L1BlockTransactor: L1BlockTransactor{contract: contract}, L1BlockFilterer: L1BlockFilterer{contract: contract}}, nil } -// NewL1blockCaller creates a new read-only instance of L1block, bound to a specific deployed contract. -func NewL1blockCaller(address common.Address, caller bind.ContractCaller) (*L1blockCaller, error) { - contract, err := bindL1block(address, caller, nil, nil) +// NewL1BlockCaller creates a new read-only instance of L1Block, bound to a specific deployed contract. +func NewL1BlockCaller(address common.Address, caller bind.ContractCaller) (*L1BlockCaller, error) { + contract, err := bindL1Block(address, caller, nil, nil) if err != nil { return nil, err } - return &L1blockCaller{contract: contract}, nil + return &L1BlockCaller{contract: contract}, nil } -// NewL1blockTransactor creates a new write-only instance of L1block, bound to a specific deployed contract. -func NewL1blockTransactor(address common.Address, transactor bind.ContractTransactor) (*L1blockTransactor, error) { - contract, err := bindL1block(address, nil, transactor, nil) +// NewL1BlockTransactor creates a new write-only instance of L1Block, bound to a specific deployed contract. +func NewL1BlockTransactor(address common.Address, transactor bind.ContractTransactor) (*L1BlockTransactor, error) { + contract, err := bindL1Block(address, nil, transactor, nil) if err != nil { return nil, err } - return &L1blockTransactor{contract: contract}, nil + return &L1BlockTransactor{contract: contract}, nil } -// NewL1blockFilterer creates a new log filterer instance of L1block, bound to a specific deployed contract. -func NewL1blockFilterer(address common.Address, filterer bind.ContractFilterer) (*L1blockFilterer, error) { - contract, err := bindL1block(address, nil, nil, filterer) +// NewL1BlockFilterer creates a new log filterer instance of L1Block, bound to a specific deployed contract. +func NewL1BlockFilterer(address common.Address, filterer bind.ContractFilterer) (*L1BlockFilterer, error) { + contract, err := bindL1Block(address, nil, nil, filterer) if err != nil { return nil, err } - return &L1blockFilterer{contract: contract}, nil + return &L1BlockFilterer{contract: contract}, nil } -// bindL1block binds a generic wrapper to an already deployed contract. -func bindL1block(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(L1blockABI)) +// bindL1Block binds a generic wrapper to an already deployed contract. +func bindL1Block(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(L1BlockABI)) if err != nil { return nil, err } @@ -167,46 +167,46 @@ func bindL1block(address common.Address, caller bind.ContractCaller, transactor // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_L1block *L1blockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _L1block.Contract.L1blockCaller.contract.Call(opts, result, method, params...) +func (_L1Block *L1BlockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L1Block.Contract.L1BlockCaller.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_L1block *L1blockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _L1block.Contract.L1blockTransactor.contract.Transfer(opts) +func (_L1Block *L1BlockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L1Block.Contract.L1BlockTransactor.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_L1block *L1blockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _L1block.Contract.L1blockTransactor.contract.Transact(opts, method, params...) +func (_L1Block *L1BlockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L1Block.Contract.L1BlockTransactor.contract.Transact(opts, method, params...) } // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_L1block *L1blockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _L1block.Contract.contract.Call(opts, result, method, params...) +func (_L1Block *L1BlockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _L1Block.Contract.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_L1block *L1blockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _L1block.Contract.contract.Transfer(opts) +func (_L1Block *L1BlockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _L1Block.Contract.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_L1block *L1blockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _L1block.Contract.contract.Transact(opts, method, params...) +func (_L1Block *L1BlockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _L1Block.Contract.contract.Transact(opts, method, params...) } // DEPOSITORACCOUNT is a free data retrieval call binding the contract method 0xe591b282. // // Solidity: function DEPOSITOR_ACCOUNT() view returns(address) -func (_L1block *L1blockCaller) DEPOSITORACCOUNT(opts *bind.CallOpts) (common.Address, error) { +func (_L1Block *L1BlockCaller) DEPOSITORACCOUNT(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _L1block.contract.Call(opts, &out, "DEPOSITOR_ACCOUNT") + err := _L1Block.contract.Call(opts, &out, "DEPOSITOR_ACCOUNT") if err != nil { return *new(common.Address), err @@ -221,23 +221,23 @@ func (_L1block *L1blockCaller) DEPOSITORACCOUNT(opts *bind.CallOpts) (common.Add // DEPOSITORACCOUNT is a free data retrieval call binding the contract method 0xe591b282. // // Solidity: function DEPOSITOR_ACCOUNT() view returns(address) -func (_L1block *L1blockSession) DEPOSITORACCOUNT() (common.Address, error) { - return _L1block.Contract.DEPOSITORACCOUNT(&_L1block.CallOpts) +func (_L1Block *L1BlockSession) DEPOSITORACCOUNT() (common.Address, error) { + return _L1Block.Contract.DEPOSITORACCOUNT(&_L1Block.CallOpts) } // DEPOSITORACCOUNT is a free data retrieval call binding the contract method 0xe591b282. // // Solidity: function DEPOSITOR_ACCOUNT() view returns(address) -func (_L1block *L1blockCallerSession) DEPOSITORACCOUNT() (common.Address, error) { - return _L1block.Contract.DEPOSITORACCOUNT(&_L1block.CallOpts) +func (_L1Block *L1BlockCallerSession) DEPOSITORACCOUNT() (common.Address, error) { + return _L1Block.Contract.DEPOSITORACCOUNT(&_L1Block.CallOpts) } // Basefee is a free data retrieval call binding the contract method 0x5cf24969. // // Solidity: function basefee() view returns(uint256) -func (_L1block *L1blockCaller) Basefee(opts *bind.CallOpts) (*big.Int, error) { +func (_L1Block *L1BlockCaller) Basefee(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L1block.contract.Call(opts, &out, "basefee") + err := _L1Block.contract.Call(opts, &out, "basefee") if err != nil { return *new(*big.Int), err @@ -252,23 +252,23 @@ func (_L1block *L1blockCaller) Basefee(opts *bind.CallOpts) (*big.Int, error) { // Basefee is a free data retrieval call binding the contract method 0x5cf24969. // // Solidity: function basefee() view returns(uint256) -func (_L1block *L1blockSession) Basefee() (*big.Int, error) { - return _L1block.Contract.Basefee(&_L1block.CallOpts) +func (_L1Block *L1BlockSession) Basefee() (*big.Int, error) { + return _L1Block.Contract.Basefee(&_L1Block.CallOpts) } // Basefee is a free data retrieval call binding the contract method 0x5cf24969. // // Solidity: function basefee() view returns(uint256) -func (_L1block *L1blockCallerSession) Basefee() (*big.Int, error) { - return _L1block.Contract.Basefee(&_L1block.CallOpts) +func (_L1Block *L1BlockCallerSession) Basefee() (*big.Int, error) { + return _L1Block.Contract.Basefee(&_L1Block.CallOpts) } // Hash is a free data retrieval call binding the contract method 0x09bd5a60. // // Solidity: function hash() view returns(bytes32) -func (_L1block *L1blockCaller) Hash(opts *bind.CallOpts) ([32]byte, error) { +func (_L1Block *L1BlockCaller) Hash(opts *bind.CallOpts) ([32]byte, error) { var out []interface{} - err := _L1block.contract.Call(opts, &out, "hash") + err := _L1Block.contract.Call(opts, &out, "hash") if err != nil { return *new([32]byte), err @@ -283,23 +283,23 @@ func (_L1block *L1blockCaller) Hash(opts *bind.CallOpts) ([32]byte, error) { // Hash is a free data retrieval call binding the contract method 0x09bd5a60. // // Solidity: function hash() view returns(bytes32) -func (_L1block *L1blockSession) Hash() ([32]byte, error) { - return _L1block.Contract.Hash(&_L1block.CallOpts) +func (_L1Block *L1BlockSession) Hash() ([32]byte, error) { + return _L1Block.Contract.Hash(&_L1Block.CallOpts) } // Hash is a free data retrieval call binding the contract method 0x09bd5a60. // // Solidity: function hash() view returns(bytes32) -func (_L1block *L1blockCallerSession) Hash() ([32]byte, error) { - return _L1block.Contract.Hash(&_L1block.CallOpts) +func (_L1Block *L1BlockCallerSession) Hash() ([32]byte, error) { + return _L1Block.Contract.Hash(&_L1Block.CallOpts) } // Number is a free data retrieval call binding the contract method 0x8381f58a. // // Solidity: function number() view returns(uint256) -func (_L1block *L1blockCaller) Number(opts *bind.CallOpts) (*big.Int, error) { +func (_L1Block *L1BlockCaller) Number(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L1block.contract.Call(opts, &out, "number") + err := _L1Block.contract.Call(opts, &out, "number") if err != nil { return *new(*big.Int), err @@ -314,23 +314,23 @@ func (_L1block *L1blockCaller) Number(opts *bind.CallOpts) (*big.Int, error) { // Number is a free data retrieval call binding the contract method 0x8381f58a. // // Solidity: function number() view returns(uint256) -func (_L1block *L1blockSession) Number() (*big.Int, error) { - return _L1block.Contract.Number(&_L1block.CallOpts) +func (_L1Block *L1BlockSession) Number() (*big.Int, error) { + return _L1Block.Contract.Number(&_L1Block.CallOpts) } // Number is a free data retrieval call binding the contract method 0x8381f58a. // // Solidity: function number() view returns(uint256) -func (_L1block *L1blockCallerSession) Number() (*big.Int, error) { - return _L1block.Contract.Number(&_L1block.CallOpts) +func (_L1Block *L1BlockCallerSession) Number() (*big.Int, error) { + return _L1Block.Contract.Number(&_L1Block.CallOpts) } // Timestamp is a free data retrieval call binding the contract method 0xb80777ea. // // Solidity: function timestamp() view returns(uint256) -func (_L1block *L1blockCaller) Timestamp(opts *bind.CallOpts) (*big.Int, error) { +func (_L1Block *L1BlockCaller) Timestamp(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L1block.contract.Call(opts, &out, "timestamp") + err := _L1Block.contract.Call(opts, &out, "timestamp") if err != nil { return *new(*big.Int), err @@ -345,34 +345,34 @@ func (_L1block *L1blockCaller) Timestamp(opts *bind.CallOpts) (*big.Int, error) // Timestamp is a free data retrieval call binding the contract method 0xb80777ea. // // Solidity: function timestamp() view returns(uint256) -func (_L1block *L1blockSession) Timestamp() (*big.Int, error) { - return _L1block.Contract.Timestamp(&_L1block.CallOpts) +func (_L1Block *L1BlockSession) Timestamp() (*big.Int, error) { + return _L1Block.Contract.Timestamp(&_L1Block.CallOpts) } // Timestamp is a free data retrieval call binding the contract method 0xb80777ea. // // Solidity: function timestamp() view returns(uint256) -func (_L1block *L1blockCallerSession) Timestamp() (*big.Int, error) { - return _L1block.Contract.Timestamp(&_L1block.CallOpts) +func (_L1Block *L1BlockCallerSession) Timestamp() (*big.Int, error) { + return _L1Block.Contract.Timestamp(&_L1Block.CallOpts) } // SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. // // Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() -func (_L1block *L1blockTransactor) SetL1BlockValues(opts *bind.TransactOpts, _number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { - return _L1block.contract.Transact(opts, "setL1BlockValues", _number, _timestamp, _basefee, _hash) +func (_L1Block *L1BlockTransactor) SetL1BlockValues(opts *bind.TransactOpts, _number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { + return _L1Block.contract.Transact(opts, "setL1BlockValues", _number, _timestamp, _basefee, _hash) } // SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. // // Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() -func (_L1block *L1blockSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { - return _L1block.Contract.SetL1BlockValues(&_L1block.TransactOpts, _number, _timestamp, _basefee, _hash) +func (_L1Block *L1BlockSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { + return _L1Block.Contract.SetL1BlockValues(&_L1Block.TransactOpts, _number, _timestamp, _basefee, _hash) } // SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. // // Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() -func (_L1block *L1blockTransactorSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { - return _L1block.Contract.SetL1BlockValues(&_L1block.TransactOpts, _number, _timestamp, _basefee, _hash) +func (_L1Block *L1BlockTransactorSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { + return _L1Block.Contract.SetL1BlockValues(&_L1Block.TransactOpts, _number, _timestamp, _basefee, _hash) } diff --git a/opnode/test/geth.go b/opnode/test/geth.go index 30f069e354c7..cd5546be6194 100644 --- a/opnode/test/geth.go +++ b/opnode/test/geth.go @@ -3,6 +3,7 @@ package test import ( "context" "crypto/ecdsa" + "errors" "fmt" "math/big" "strconv" @@ -10,9 +11,11 @@ import ( "time" rollupEth "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/keystore" "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" @@ -22,6 +25,52 @@ import ( hdwallet "github.com/miguelmota/go-ethereum-hdwallet" ) +func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time.Duration) (*types.Receipt, error) { + timeoutCh := time.After(timeout) + 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: + return nil, errors.New("timeout") + case <-time.After(100 * time.Millisecond): + } + } +} + +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, errors.New("timeout") + } + } +} + func getGenesisInfo(client *ethclient.Client) (id rollupEth.BlockID, timestamp uint64) { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() @@ -44,9 +93,11 @@ func initL1Geth(cfg *SystemConfig, wallet *hdwallet.Wallet, genesis *core.Genesi Genesis: genesis, } nodeConfig := &node.Config{ - Name: "l1-geth", - WSHost: cfg.L1WsAddr, - WSPort: cfg.L1WsPort, + Name: "l1-geth", + WSHost: cfg.L1WsAddr, + WSPort: cfg.L1WsPort, + WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, + HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, } return createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{pk}) @@ -68,9 +119,11 @@ func initL2Geth(name, addr string, l2ChainID *big.Int, genesis *core.Genesis) (* return nil, nil, fmt.Errorf("failed to parse port from address: %w", err) } nodeConfig := &node.Config{ - Name: fmt.Sprintf("l2-geth-%v", name), - WSHost: host, - WSPort: int(port), + Name: fmt.Sprintf("l2-geth-%v", name), + WSHost: host, + WSPort: int(port), + WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, + HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, } return createGethNode(true, nodeConfig, ethConfig, nil) } @@ -112,6 +165,7 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri return nil, nil, err } + // Enable catalyst if l2 if l2 { if err := catalyst.Register(n, backend); err != nil { diff --git a/opnode/test/setup.go b/opnode/test/setup.go index bb5b37dd6e73..a1d701825bef 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -6,13 +6,16 @@ import ( "math/big" "time" + "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethclient" @@ -40,14 +43,31 @@ func deriveAccount(w accounts.Wallet, path string) accounts.Account { return account } +type L2OOContractConfig struct { + SubmissionFrequency *big.Int + L2StartTime *big.Int + L2BlockTime *big.Int + GenesisL2Output [32]byte + HistoricalTotalBlocks *big.Int +} + +type DepositContractConfig struct { + L2Oracle common.Address + FinalizationPeriod *big.Int +} + type SystemConfig struct { Mnemonic string Premine map[string]int // Derivation path -> amount in ETH (not wei) CliqueSignerDerivationPath string + L2OutputHDPath string BatchSubmitterHDPath string - DepositContractAddress common.Address + DeployerHDPath string L1InfoPredeployAddress common.Address + L2OOCfg L2OOContractConfig + DepositCFG DepositContractConfig + L1WsAddr string L1WsPort int L1ChainID *big.Int @@ -64,11 +84,13 @@ type System struct { wallet *hdwallet.Wallet // Connections to running nodes - nodes map[string]*node.Node - backends map[string]*eth.Ethereum - Clients map[string]*ethclient.Client - RolupGenesis rollup.Genesis - rollupNodes map[string]*rollupNode.OpNode + nodes map[string]*node.Node + backends map[string]*eth.Ethereum + Clients map[string]*ethclient.Client + RolupGenesis rollup.Genesis + rollupNodes map[string]*rollupNode.OpNode + L2OOContractAddr common.Address + DepositContractAddr common.Address } func precompileAlloc() core.GenesisAlloc { @@ -142,7 +164,18 @@ func (cfg SystemConfig) start() (*System, error) { if err != nil { return nil, err } - submitterAddress := crypto.PubkeyToAddress(bssPrivKey.PublicKey) + batchSubmitterAddr := crypto.PubkeyToAddress(bssPrivKey.PublicKey) + + // Create the L2 Outputsubmitter Address and set it here because it needs to be derived from the accounts + l2OOSubmitter, err := wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: cfg.L2OutputHDPath, + }, + }) + if err != nil { + return nil, err + } + l2OutputSubmitterAddr := crypto.PubkeyToAddress(l2OOSubmitter.PublicKey) // Genesis eth := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) @@ -158,7 +191,6 @@ func (cfg SystemConfig) start() (*System, error) { l2Alloc[addr] = core.GenesisAccount{Balance: balance} } - l1Alloc[cfg.DepositContractAddress] = core.GenesisAccount{Code: common.FromHex(deposit.DepositDeployedBin), Balance: common.Big0} l2Alloc[cfg.L1InfoPredeployAddress] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} genesisTimestamp := uint64(time.Now().Unix()) @@ -288,12 +320,59 @@ func (cfg SystemConfig) start() (*System, error) { } sys.cfg.RollupConfig.Genesis = sys.RolupGenesis - sys.cfg.RollupConfig.BatchSenderAddress = submitterAddress + sys.cfg.RollupConfig.BatchSenderAddress = batchSubmitterAddr + sys.cfg.L2OOCfg.L2StartTime = new(big.Int).SetUint64(l2GenesisTime) + + // Deploy Deposit Contract + deployerPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: sys.cfg.DeployerHDPath, + }, + }) + if err != nil { + return nil, err + } + + opts, err := bind.NewKeyedTransactorWithChainID(deployerPrivKey, cfg.L1ChainID) + if err != nil { + return nil, err + } + + // Deploy contracts + sys.L2OOContractAddr, _, _, err = l2oo.DeployL2OutputOracle( + opts, + l1Client, + sys.cfg.L2OOCfg.SubmissionFrequency, + sys.cfg.L2OOCfg.L2BlockTime, + sys.cfg.L2OOCfg.GenesisL2Output, + sys.cfg.L2OOCfg.HistoricalTotalBlocks, + sys.cfg.L2OOCfg.L2StartTime, + l2OutputSubmitterAddr, + ) + sys.cfg.DepositCFG.L2Oracle = sys.L2OOContractAddr + if err != nil { + return nil, err + } + var tx *types.Transaction + sys.DepositContractAddr, tx, _, err = deposit.DeployOptimismPortal( + opts, + l1Client, + sys.cfg.DepositCFG.L2Oracle, + sys.cfg.DepositCFG.FinalizationPeriod, + ) + if err != nil { + return nil, err + } + _, err = waitForTransaction(tx.Hash(), l1Client, 4*time.Second) + if err != nil { + return nil, fmt.Errorf("waiting for OptimismPortal: %w", err) + } // Rollup nodes for name, nodeConfig := range cfg.Nodes { c := nodeConfig c.Rollup = sys.cfg.RollupConfig + c.Rollup.DepositContractAddress = sys.DepositContractAddr if c.Sequencer { c.SubmitterPrivKey = bssPrivKey } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index ab15c9de6d42..c05988341199 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -2,7 +2,6 @@ package test import ( "context" - "errors" "fmt" "math/big" "testing" @@ -11,7 +10,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" - "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" @@ -24,8 +22,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" @@ -50,9 +46,19 @@ func defaultSystemConfig(t *testing.T) SystemConfig { l2OutputHDPath: 10000000, bssHDPath: 10000000, }, + DepositCFG: DepositContractConfig{ + FinalizationPeriod: big.NewInt(60 * 60 * 24), + }, + L2OOCfg: L2OOContractConfig{ + // L2 Start time is set based off of the L2 Genesis time + SubmissionFrequency: big.NewInt(2), + L2BlockTime: big.NewInt(1), + HistoricalTotalBlocks: big.NewInt(0), + }, + L2OutputHDPath: l2OutputHDPath, BatchSubmitterHDPath: bssHDPath, + DeployerHDPath: l2OutputHDPath, CliqueSignerDerivationPath: cliqueSignerHDPath, - DepositContractAddress: MockDepositContractAddr, L1InfoPredeployAddress: derive.L1InfoPredeployAddr, L1WsAddr: "127.0.0.1", L1WsPort: 9090, @@ -94,53 +100,6 @@ func defaultSystemConfig(t *testing.T) SystemConfig { } } -func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time.Duration) (*types.Receipt, error) { - timeoutCh := time.After(timeout) - 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: - return nil, errors.New("timeout") - case <-time.After(100 * time.Millisecond): - } - } -} - -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, errors.New("timeout") - } - } - -} - func TestL2OutputSubmitter(t *testing.T) { log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs @@ -156,40 +115,8 @@ func TestL2OutputSubmitter(t *testing.T) { require.Nil(t, err) rollupClient := rollupclient.NewRollupClient(rollupRPCClient) - // Deploy StateRootOracle - l2OutputPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ - URL: accounts.URL{ - Path: l2OutputHDPath, - }, - }) - require.Nil(t, err) - l2OutputAddr := crypto.PubkeyToAddress(l2OutputPrivKey.PublicKey) - - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - nonce, err := l1Client.NonceAt(ctx, l2OutputAddr, nil) - require.Nil(t, err) - - opts, err := bind.NewKeyedTransactorWithChainID(l2OutputPrivKey, cfg.L1ChainID) - require.Nil(t, err) - opts.Nonce = big.NewInt(int64(nonce)) - - submissionFrequency := big.NewInt(2) // 2 seconds - l2BlockTime := big.NewInt(1) // 1 seconds - l2ooAddr, tx, l2OutputOracle, err := l2oo.DeployL2OutputOracle( - opts, - l1Client, - submissionFrequency, - l2BlockTime, - [32]byte{}, - big.NewInt(0), - l2OutputAddr, - ) - require.Nil(t, err) - - ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - _, err = txmgr.WaitMined(ctx, l1Client, tx, time.Second, 1) + // StateRootOracle is already deployed + l2OutputOracle, err := l2oo.NewL2OutputOracleCaller(sys.L2OOContractAddr, l1Client) require.Nil(t, err) initialSroTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{}) @@ -200,7 +127,7 @@ func TestL2OutputSubmitter(t *testing.T) { L1EthRpc: "ws://127.0.0.1:9090", L2EthRpc: cfg.Nodes["sequencer"].L2NodeAddr, RollupRpc: fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPCListenAddr, cfg.Nodes["sequencer"].RPCListenPort), - L2OOAddress: l2ooAddr.String(), + L2OOAddress: sys.L2OOContractAddr.String(), PollInterval: 2 * time.Second, NumConfirmations: 1, ResubmissionTimeout: 3 * time.Second, @@ -239,7 +166,7 @@ func TestL2OutputSubmitter(t *testing.T) { // // NOTE: This assertion will change once the L2 output format is // finalized. - ctx, cancel = context.WithTimeout(context.Background(), time.Second) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() l2Output, err := rollupClient.OutputAtBlock(ctx, l2ooBlockNumber) require.Nil(t, err) @@ -285,7 +212,7 @@ func TestSystemE2E(t *testing.T) { fromAddr := common.HexToAddress("0x30ec912c5b1d14aa6d1cb9aa7a6682415c4f7eb0") // Find deposit contract - depositContract, err := deposit.NewDeposit(cfg.DepositContractAddress, l1Client) + depositContract, err := deposit.NewOptimismPortal(sys.DepositContractAddr, l1Client) require.Nil(t, err) l1Node := sys.nodes["l1"] @@ -366,7 +293,7 @@ func TestMintOnRevertedDeposit(t *testing.T) { l2Verif := sys.Clients["verifier"] // Find deposit contract - depositContract, err := deposit.NewDeposit(cfg.DepositContractAddress, l1Client) + depositContract, err := deposit.NewOptimismPortal(sys.DepositContractAddr, l1Client) require.Nil(t, err) l1Node := sys.nodes["l1"] diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 35f798a8ba74..63a2cec191b5 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: MIT -pragma solidity >=0.8.10; +pragma solidity 0.8.10; /* Library Imports */ import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; From c69fffd4b91be9e573ee75678772e3aecc35f321 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 12 Apr 2022 10:41:12 -0400 Subject: [PATCH 479/585] specs: Update output root derivation (#357) * specs: Update output root derivation * specs: Separate version from payload --- specs/glossary.md | 2 +- specs/proposals.md | 82 +++++++++++++++++++++++--------------------- specs/withdrawals.md | 3 +- 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index c4aeadce213a..8c194f583807 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -395,7 +395,7 @@ cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes [l2-output]: glossary.md#l2-output -A 32 byte value which commits to the current state of the L2 chain. +A 32 byte value which serves as a commitment to the current state of the L2 chain. cf. [Proposing L2 output commitments](proposals.md#l2-output-root-proposals-specification) diff --git a/specs/proposals.md b/specs/proposals.md index 286f9cb65cf7..f6da7585e575 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -1,7 +1,9 @@ # L2 Output Root Proposals Specification + [g-rollup-node]: glossary.md#rollup-node +[g-mpt]: glossary.md#merkle-patricia-trie @@ -23,7 +25,7 @@ proving any piece of data captured by the outputs. Proposers submit the output roots to L1 and can be contested with a fault proof, with a bond at stake if the proof is wrong. -*Note*: Although fault proof construction and verification [is implemented in Cannon][cannon], +_Note_: Although fault proof construction and verification [is implemented in Cannon][cannon], the fault proof game specification and integration of a output-root challenger into the [rollup-node][g-rollup-node] are part of later specification milestones. @@ -31,14 +33,15 @@ are part of later specification milestones. ## Proposing L2 Output Commitments -The proposer's role is to construct and submit output commitments on a configurable interval to a contract on , which -it does by running the [L2 output submitter](../l2os/). This service periodically queries the rollup - node's [`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived - from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is - described [below](#l2-output-commitment-construction). +The proposer's role is to construct and submit output roots, which are commitments made on a configurable interval, +to the `L2OutputOracle` contract running on L2. It does this by running the [L2 output submitter](../l2os/), a service +which periodically queries the rollup node's +[`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived +from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is +described [below](#l2-output-commitment-construction). If there is no newly finalized output, the service continues querying until it receives one. It then submits this -output, and the appropriate timestamp, to the [L2 Output Commitment](#l2-output-commitment-smart-contract) contract's +output, and the appropriate timestamp, to the [L2 Output Root](#l2-output-root-smart-contract) contract's `appendL2Output()` function. The timestamp MUST be the next multiple of the `SUBMISSION_INTERVAL` value. > **Note regarding future work:** In the initial version of the system, the proposer will be the same entity as the @@ -47,43 +50,44 @@ output, and the appropriate timestamp, to the [L2 Output Commitment](#l2-output- ## L2 Output Commitment Construction -This merkle-structure is defined with [SSZ], a type system for merkleization and serialization, used in -L1 (beacon-chain). However, we replace `sha256` with `keccak256` to save gas costs in the EVM. - -[SSZ]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md +The `output_root` is a 32 byte string, which is derived based on the a versioned scheme: -```python -class L2Output(Container): - state_root: Bytes32 - withdrawal_storage_root: Bytes32 # TODO: withdrawals specification work-in-progress - latest_block: ExecutionPayload # includes block hash - history_accumulator_root: Bytes32 # Not functional yet - extension: Bytes32 +```pseudocode +output_root = keccak256(version_byte || payload) ``` -The `state_root` is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts, -also found in `latest_block.state_root`: this field is frequently used and thus elevated closer to the L2 output root, -as opposed to retrieving it from the pre-image of the block in `latest_block`, -reducing the merkle proof depth and thus the cost of usage. +where: + +1. `version_byte` (`bytes32`) a simple version string which increments anytime the construction of the output root + is changed. + +2. `payload` (`bytes`) is a byte string of arbitrary length. + +In the initial version of the output commitment construction, the version is `bytes32(0)`, and the payload is defined +as: + +```pseudocode +payload = state_root || withdrawal_storage_root || latest_block +``` -The `withdrawal_storage_root` elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of L2 Withdrawal contract storage. -Instead of a MPT proof to the Withdrawal contract account in the account trie, -one can directly access the MPT storage trie root, thus reducing the verification cost of withdrawals on L1. +where the concatenated variables are: -The `latest_block` is an execution-layer block of L2, represented as the [`ExecutionPayload`][ExecutionPayload] SSZ type -defined in L1. There may be multiple blocks per L2 output root, only the latest is presented. +1. The `state_root` (`bytes32`) is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts, + also found in `latest_block.state_root`: this field is frequently used and thus elevated closer to the L2 output + root, as opposed to retrieving it from the pre-image of the block in `latest_block`, reducing the merkle proof depth + and thus the cost of usage. -[ExecutionPayload]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayload +1. The `withdrawal_storage_root` (`bytes32`) elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of [L2 Withdrawal + contract](./withdrawals.md#withdrawer-contract) storage. Instead of making an MPT proof for a withdrawal against the + state root (proving first the storage root of the L2 withdrawal contract against the state root, then the withdrawal + against that storage root), we can prove against the L2 withdrawal contract's storage root directly, thus reducing + the verification cost of withdrawals on L1. -The `history_accumulator_root` is a reserved field, elevating a storage variable of the L2 chain that maintains -the [SSZ] merkle root of an append-only `List[Bytes32, MAX_ITEM_COUNT]` (`keccak256` [SSZ] hash-tree-root), -where each item is defined as `keccak256(l2_block_hash ++ l2_state_root)`, one per block of the L2 chain. -While reserved, a zeroed `Bytes32` is used instead. -This is a work-in-progress, see [issue 181](https://github.com/ethereum-optimism/optimistic-specs/issues/181). -`MAX_ITEM_COUNT` and/or other parameters will be defined in the withdrawals milestone. +1. The `latest_block` (`bytes32`) is an L2 block, represented as the + [`ExecutionPayload`][executionpayload] SSZ type defined in L1. There may be multiple blocks per L2 output root, only + the latest is presented. -The `extension` is a zeroed `Bytes32`, to be substituted with a SSZ container to extend merkleized information in future -upgrades. This keeps the static merkle structure forwards-compatible. +[executionpayload]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayload ## L2 Output Oracle Smart Contract @@ -137,7 +141,7 @@ will not match that of the block with that number and the call will revert. ### Constants -| Name | Value | Unit | -| ---------------------- | ----- | ------- | +| Name | Value | Unit | +| --------------------- | ------ | ------- | | `SUBMISSION_INTERVAL` | `1800` | seconds | -| `L2_BLOCK_TIME` | `2` | seconds | +| `L2_BLOCK_TIME` | `2` | seconds | diff --git a/specs/withdrawals.md b/specs/withdrawals.md index 6f6aafa649e9..e8ed4f2667c2 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -9,7 +9,6 @@ [g-mpt]: glossary.md#merkle-patricia-trie [g-relayer]: glossary.md#withdrawals [g-execution-engine]: glossary.md#execution-engine -**Table of Contents** [Withdrawals][g-withdrawal] are cross domain transactions which are initiated on L2, and finalized by a transaction executed on L1. Notably, withdrawals may be used by and L2 account to call an L1 contract, or to transfer ETH from @@ -71,6 +70,8 @@ An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdra ## The L2 Withdrawer Contract +[withdrawer-contract]: #the-l2-withdrawer-contract + A withdrawal is initiated by calling the Withdrawer contract's `initiateWithdrawal` function. The Withdrawer is a simple predeploy contract at `0x4200000000000000000000000000000000000016` which stores messages to be withdrawn. From 8412d33b95c4596d03182de73219e53f46f09232 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 14 Apr 2022 03:53:27 +0200 Subject: [PATCH 480/585] opnode: libp2p setup --- go.mod | 67 +++ go.sum | 893 ++++++++++++++++++++++++++++++++++++- opnode/flags/flags.go | 4 +- opnode/flags/flags_test.go | 13 + opnode/flags/p2p_flags.go | 223 +++++++++ opnode/p2p/config.go | 332 ++++++++++++++ opnode/p2p/discovery.go | 42 ++ opnode/p2p/host.go | 104 +++++ 8 files changed, 1669 insertions(+), 9 deletions(-) create mode 100644 opnode/flags/p2p_flags.go create mode 100644 opnode/p2p/config.go create mode 100644 opnode/p2p/discovery.go create mode 100644 opnode/p2p/host.go diff --git a/go.mod b/go.mod index 6de2d10c47ba..2904b1b3e9a8 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,19 @@ require ( github.com/ethereum/go-ethereum v1.10.16 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.0 + github.com/ipfs/go-datastore v0.5.0 + github.com/ipfs/go-ds-leveldb v0.5.0 + github.com/libp2p/go-libp2p v0.18.1 + github.com/libp2p/go-libp2p-core v0.15.0 + github.com/libp2p/go-libp2p-mplex v0.6.0 + github.com/libp2p/go-libp2p-noise v0.3.0 + github.com/libp2p/go-libp2p-peerstore v0.6.0 + github.com/libp2p/go-libp2p-swarm v0.10.2 + github.com/libp2p/go-libp2p-tls v0.3.1 + github.com/libp2p/go-libp2p-yamux v0.9.0 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 + github.com/multiformats/go-multiaddr v0.5.0 + github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.5 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 @@ -14,49 +26,104 @@ require ( require ( github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/benbjohnson/clock v1.1.0 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect github.com/btcsuite/btcd/btcec/v2 v2.1.2 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 // indirect + github.com/coreos/go-systemd/v22 v22.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/docker/go-units v0.4.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect github.com/fjl/memsize v0.0.1 // indirect + github.com/flynn/noise v1.0.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/godbus/dbus/v5 v5.0.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/gopacket v1.1.19 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.0.3 // indirect + github.com/ipfs/go-cid v0.0.7 // indirect + github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/ipfs/go-log/v2 v2.5.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/koron/go-ssdp v0.0.2 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/libp2p/go-cidranger v1.1.0 // indirect + github.com/libp2p/go-conn-security-multistream v0.3.0 // indirect + github.com/libp2p/go-eventbus v0.2.1 // indirect + github.com/libp2p/go-flow-metrics v0.0.3 // indirect + github.com/libp2p/go-libp2p-asn-util v0.1.0 // indirect + github.com/libp2p/go-libp2p-blankhost v0.3.0 // indirect + github.com/libp2p/go-libp2p-nat v0.1.0 // indirect + github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect + github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 // indirect + github.com/libp2p/go-mplex v0.6.0 // indirect + github.com/libp2p/go-msgio v0.1.0 // indirect + github.com/libp2p/go-nat v0.1.0 // indirect + github.com/libp2p/go-netroute v0.2.0 // indirect + github.com/libp2p/go-openssl v0.0.7 // indirect + github.com/libp2p/go-stream-muxer-multistream v0.4.0 // indirect + github.com/libp2p/go-yamux/v3 v3.1.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/miekg/dns v1.1.43 // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.0.3 // indirect + github.com/multiformats/go-multicodec v0.4.1 // indirect + github.com/multiformats/go-multihash v0.0.15 // indirect + github.com/multiformats/go-multistream v0.2.2 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/tsdb v0.10.0 // indirect + github.com/raulk/clock v1.1.0 // indirect + github.com/raulk/go-watchdog v1.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rjeczalik/notify v0.9.2 // indirect github.com/rs/cors v1.8.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect github.com/stretchr/objx v0.1.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.19.1 // indirect golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect golang.org/x/text v0.3.7 // indirect diff --git a/go.sum b/go.sum index abbb2f3d723d..04c93470f102 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.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.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= 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= @@ -8,16 +10,40 @@ cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTj 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/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= @@ -37,20 +63,40 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt 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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= 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/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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 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= @@ -60,17 +106,23 @@ github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7 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/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 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/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd/btcec/v2 v2.1.2 h1:YoYoC9J0jwfukodSBMzZYUVQ8PTiYg4BnOWiJVzTmLs= github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -84,24 +136,52 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= 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/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= 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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= 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/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 h1:7grrpcfCtbZLsjtB0DgMuzs1umsJmpzaHMZ6cO6iAWw= +github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= @@ -109,6 +189,9 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 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/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= @@ -119,22 +202,42 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 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/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= +github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= +github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= 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-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 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/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8 h1:GrJtCdIozmrjTDrt/4PLwtVMkF3xYtgVVfnJb14gm+Y= github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= @@ -143,7 +246,14 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= +github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -153,16 +263,23 @@ github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x 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/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= 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-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 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-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= +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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +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 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -170,33 +287,59 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 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 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= 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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 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/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 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= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -211,39 +354,94 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.2/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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= 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/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 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= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= +github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= @@ -252,6 +450,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt 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/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 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= @@ -260,39 +459,94 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y 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/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= +github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-datastore v0.5.0 h1:rQicVCEacWyk4JZ6G5bD9TKR7lZEG1MWcG7UdWYrFAU= +github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= +github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= +github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= +github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= +github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= +github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= +github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= +github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= +github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 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/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= +github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= 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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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= @@ -301,11 +555,152 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F 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/libp2p/go-addr-util v0.1.0/go.mod h1:6I3ZYuFr2O/9D+SoyM0zEw0EF3YkldtTX406BpdQMqw= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= +github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= +github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= +github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= +github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-libp2p v0.18.1 h1:IK9EOGNO2ZghU4F+dx9c4xfhMNZr45x06CijJaZE/ms= +github.com/libp2p/go-libp2p v0.18.1/go.mod h1:ll44MqmrIFKpL3BwCexxzm+7RZ8exEtN96V1rRdMG7Y= +github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= +github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= +github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= +github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= +github.com/libp2p/go-libp2p-circuit v0.6.0 h1:rw/HlhmUB3OktS/Ygz6+2XABOmHKzZpPUuMNUMosj8w= +github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJfdCGv51mTmdpmM= +github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.11.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= +github.com/libp2p/go-libp2p-core v0.15.0 h1:hKpgy/bRVwO7Ah5x9u92Vo+gogAaOolafZF5kW0rVm0= +github.com/libp2p/go-libp2p-core v0.15.0/go.mod h1:agSaboYM4hzB1cWekgVReqV5M4g5M+2eNNejV+1EEhs= +github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= +github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= +github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= +github.com/libp2p/go-libp2p-nat v0.1.0 h1:vigUi2MEN+fwghe5ijpScxtbbDz+L/6y8XwlzYOJgSY= +github.com/libp2p/go-libp2p-nat v0.1.0/go.mod h1:DQzAG+QbDYjN1/C3B6vXucLtz3u9rEonLVPtZVzQqks= +github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= +github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= +github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= +github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnHd/VBjL4mY5A= +github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= +github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= +github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= +github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= +github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-quic-transport v0.16.1 h1:N/XqYXHurphPLDfXYhll8NyqzdZYQqAF4GIr7+SmLV8= +github.com/libp2p/go-libp2p-quic-transport v0.16.1/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-resource-manager v0.2.0 h1:Ul/k5d5StIpAtq7IapAEGh/2+0rwsJGXYJ6Kbzeedtc= +github.com/libp2p/go-libp2p-resource-manager v0.2.0/go.mod h1:K+eCkiapf+ey/LADO4TaMpMTP9/Qde/uLlrnRqV4PLQ= +github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= +github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= +github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= +github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= +github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= +github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= +github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= +github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= +github.com/libp2p/go-libp2p-testing v0.9.2 h1:dCpODRtRaDZKF8HXT9qqqgON+OMEB423Knrgeod8j84= +github.com/libp2p/go-libp2p-testing v0.9.2/go.mod h1:Td7kbdkWqYTJYQGTwzlgXwaqldraIanyjuRiAbK/XQU= +github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= +github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 h1:MSMe+tUfxpC9GArTz7a4G5zQKQgGh00Vio87d3j3xIg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= +github.com/libp2p/go-libp2p-yamux v0.8.1/go.mod h1:rUozF8Jah2dL9LLGyBaBeTQeARdwhefMCTQVQt6QobE= +github.com/libp2p/go-libp2p-yamux v0.9.0 h1:j+gnKykADCI/3cZlacOYBjQXDsncxgcwzJ1zw6Z6pts= +github.com/libp2p/go-libp2p-yamux v0.9.0/go.mod h1:tpJKkRH9LlHj0VQh9Y9RP1pmF7yCS9ixxY/oSv+hhhQ= +github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= +github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= +github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= +github.com/libp2p/go-msgio v0.1.0 h1:8Q7g/528ivAlfXTFWvWhVjTE8XG8sDTkRUKPYh9+5Q8= +github.com/libp2p/go-msgio v0.1.0/go.mod h1:eNlv2vy9V2X/kNldcZ+SShFE++o2Yjxwx6RAYsmgJnE= +github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= +github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= +github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= +github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= +github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-reuseport v0.1.0 h1:0ooKOx2iwyIkf339WCZ2HN3ujTDbkK0PjC7JVoP1AiM= +github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= +github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7CyD1zuN7xQT8gc= +github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= +github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= +github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= +github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= +github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-tcp-transport v0.5.1 h1:edOOs688VLZAozWC7Kj5/6HHXKNwi9M6wgRmmLa8M6Q= +github.com/libp2p/go-tcp-transport v0.5.1/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-ws-transport v0.6.0 h1:326XBL6Q+5CQ2KtjXz32+eGu02W/Kz2+Fm4SpXdr0q4= +github.com/libp2p/go-ws-transport v0.6.0/go.mod h1:dXqtI9e2JV9FtF1NOtWVZSKXh5zXvnuwPXfj8GPBbYU= +github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.1.0 h1:2johPiST4xsXsqQ/38C2MAERw0hJ+t8oehHWA8F2R3Q= +github.com/libp2p/go-yamux/v3 v3.1.0/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4= +github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= +github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= +github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 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/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= +github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= +github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= +github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -313,108 +708,314 @@ github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZb github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= github.com/miguelmota/go-ethereum-hdwallet v0.1.1/go.mod h1:f9m9uXokAHA6WNoYOPjj4AqjJS5pquQRiYYj/XSyPYc= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= +github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= +github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= +github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= +github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= +github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= +github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= +github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= +github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= +github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= +github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= +github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 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/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/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= 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/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= 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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/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-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/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-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +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-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/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/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= +github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= +github.com/raulk/go-watchdog v1.2.0 h1:konN75pw2BMmZ+AfuAm5rtFsWcJpKF3m02rKituuXNo= +github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 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/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.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/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/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 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/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -425,9 +1026,11 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= 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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= @@ -435,39 +1038,103 @@ github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYa github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 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/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +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= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-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/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -480,9 +1147,13 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -491,46 +1162,85 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20200904194848-62affa334b73/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +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.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= 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= @@ -538,47 +1248,93 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ 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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190219092855-153ac476189d/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-20190228124157-a34e9553db1e/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-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/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-20200124204421-9fbb57f87de9/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-20200602225109-6fdc65e7d980/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-20201214210602-f9fddec55a1e/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-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -590,6 +1346,7 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +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= @@ -599,15 +1356,21 @@ 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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/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-20181130052023-1c3d964395ce/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= @@ -624,14 +1387,43 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-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-20200103221440-774c71fcf114/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= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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= @@ -643,6 +1435,10 @@ 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.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 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= @@ -650,16 +1446,33 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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/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-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 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= @@ -669,35 +1482,91 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx 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-20200513103714-09dca8ec2884/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.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/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.28.1/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/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 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= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +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= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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= @@ -706,11 +1575,21 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C 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= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= 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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go index 692f672859e4..6c3886a8c547 100644 --- a/opnode/flags/flags.go +++ b/opnode/flags/flags.go @@ -104,7 +104,7 @@ var requiredFlags = []cli.Flag{ RPCListenPort, } -var optionalFlags = []cli.Flag{ +var optionalFlags = append([]cli.Flag{ L1TrustRPC, SequencingEnabledFlag, BatchSubmitterKeyFlag, @@ -112,7 +112,7 @@ var optionalFlags = []cli.Flag{ LogLevelFlag, LogFormatFlag, LogColorFlag, -} +}, p2pFlags...) // Flags contains the list of configuration options available to the binary. var Flags = append(requiredFlags, optionalFlags...) diff --git a/opnode/flags/flags_test.go b/opnode/flags/flags_test.go index ae0bc3d02e37..48d9f3598cea 100644 --- a/opnode/flags/flags_test.go +++ b/opnode/flags/flags_test.go @@ -26,3 +26,16 @@ func TestOptionalFlagsDontSetRequired(t *testing.T) { require.False(t, reqFlag.IsRequired()) } } + +// TestUniqueFlags asserts that all flag names are unique, to avoid accidental conflicts between the many flags. +func TestUniqueFlags(t *testing.T) { + seenCLI := make(map[string]struct{}) + for _, flag := range Flags { + name := flag.GetName() + if _, ok := seenCLI[name]; ok { + t.Errorf("duplicate flag %s", name) + continue + } + seenCLI[name] = struct{}{} + } +} diff --git a/opnode/flags/p2p_flags.go b/opnode/flags/p2p_flags.go new file mode 100644 index 000000000000..828770082e32 --- /dev/null +++ b/opnode/flags/p2p_flags.go @@ -0,0 +1,223 @@ +package flags + +import ( + "github.com/urfave/cli" + "time" +) + +func p2pEnv(v string) string { + return prefixEnvVar("P2P_" + v) +} + +var ( + DisableP2P = cli.BoolFlag{ + Name: "p2p.disable", + Usage: "Completely disable the P2P stack", + Required: false, + EnvVar: p2pEnv("DISABLE"), + } + NoDiscovery = cli.BoolFlag{ + Name: "p2p.no-discovery", + Usage: "Disable Discv5 (node discovery)", + Required: false, + EnvVar: p2pEnv("NO_DISCOVERY"), + } + P2PPrivPath = cli.StringFlag{ + Name: "p2p.priv.path", + Usage: "Read the hex-encoded 32-byte private key for the peer ID from this txt file. Created if not already exists." + + "Important to persist to keep the same network identity after restarting, maintaining the previous advertised identity.", + Required: false, + Value: "opnode_p2p_priv.txt", + EnvVar: p2pEnv("PRIV_PATH"), + } + P2PPrivRaw = cli.StringFlag{ + // sometimes it may be ok to not persist the peer priv key as file, and instead pass it directly. + Name: "p2p.priv.raw", + Usage: "The hex-encoded 32-byte private key for the peer ID", + Required: false, + Hidden: true, + Value: "", + EnvVar: p2pEnv("PRIV_RAW"), + } + ListenIP = cli.StringFlag{ + Name: "p2p.listen.ip", + Usage: "IP to bind LibP2P and Discv5 to", + Required: false, + Value: "0.0.0.0", + EnvVar: p2pEnv("LISTEN_IP"), + } + ListenTCPPort = cli.UintFlag{ + Name: "p2p.listen.tcp", + Usage: "TCP port to bind LibP2P to. Any available system port if set to 0.", + Required: false, + Value: 9222, + EnvVar: p2pEnv("LISTEN_TCP_PORT"), + } + ListenUDPPort = cli.UintFlag{ + Name: "p2p.listen.udp", + Usage: "UDP port to bind Discv5 to. Same as TCP port if left 0.", + Required: false, + Value: 0, // can simply match the TCP libp2p port + EnvVar: p2pEnv("LISTEN_UDP_PORT"), + } + AdvertiseIP = cli.StringFlag{ + Name: "p2p.advertise.ip", + Usage: "The IP address to advertise in Discv5, put into the ENR of the node", + Required: false, + // Ignored by default, nodes can discover their own external IP in the happy case, + // by communicating with bootnodes. Fixed IP is recommended for faster bootstrap though. + Value: "", + EnvVar: p2pEnv("ADVERTISE_IP"), + } + AdvertiseTCPPort = cli.UintFlag{ + Name: "p2p.advertise.tcp", + Usage: "The TCP port to advertise in Discv5, put into the ENR of the node. Set to p2p.listen.tcp value if 0.", + Required: false, + Value: 0, + EnvVar: p2pEnv("ADVERTISE_TCP"), + } + AdvertiseUDPPort = cli.UintFlag{ + Name: "p2p.advertise.udp", + Usage: "The UDP port to advertise in Discv5 as fallback if not determined by Discv5, put into the ENR of the node. Set to p2p.listen.udp value if 0.", + Required: false, + Value: 0, + EnvVar: p2pEnv("ADVERTISE_TCP"), + } + Bootnodes = cli.StringFlag{ + Name: "p2p.bootnodes", + Usage: "Comma-separated base64-format ENR list. Bootnodes to start discovering other node records from.", + Required: false, + Value: "", + EnvVar: p2pEnv("BOOTNODES"), + } + StaticPeers = cli.StringFlag{ + Name: "p2p.static", + Usage: "Comma-separated multiaddr-format peer list. Static connections to make and maintain, these peers will be regarded as trusted.", + Required: false, + Value: "", + EnvVar: p2pEnv("BOOTNODES"), + } + HostMux = cli.StringFlag{ + Name: "p2p.mux", + Usage: "Comma-separated list of multiplexing protocols in order of preference. At least 1 required. Options: 'yamux','mplex'.", + Hidden: true, + Required: false, + Value: "yamux,mplex", + EnvVar: p2pEnv("MUX"), + } + HostSecurity = cli.StringFlag{ + Name: "p2p.security", + Usage: "Comma-separated list of transport security protocols in order of preference. At least 1 required. Options: 'noise','tls'. Set to 'none' to disable.", + Hidden: true, + Required: false, + Value: "noise", + EnvVar: p2pEnv("SECURITY"), + } + PeersLo = cli.UintFlag{ + Name: "p2p.peers.lo", + Usage: "Low-tide peer count. The node actively searches for new peer connections if below this amount.", + Required: false, + Value: 20, + EnvVar: p2pEnv("PEERS_LO"), + } + PeersHi = cli.UintFlag{ + Name: "p2p.peers.hi", + Usage: "High-tide peer count. The node starts pruning peer connections slowly after reaching this number.", + Required: false, + Value: 30, + EnvVar: p2pEnv("PEERS_HI"), + } + PeersGrace = cli.DurationFlag{ + Name: "p2p.peers.grace", + Usage: "Grace period to keep a newly connected peer around, if it is not misbehaving.", + Required: false, + Value: 30 * time.Second, + EnvVar: p2pEnv("PEERS_GRACE"), + } + NAT = cli.StringFlag{ + Name: "p2p.nat", + Usage: "NAT options. Empty for dynamic defaults. 'none' to disable. Set to 'extip:IPHERE' to use a static IP. Or 'upnp', or 'pmp'. Used to inform LibP2P of the external IP to put into multiaddrs.", + Required: false, + Value: "", + EnvVar: p2pEnv("NAT"), + } + UserAgent = cli.StringFlag{ + Name: "p2p.useragent", + Usage: "User-agent string to share via LibP2P identify. If empty it defaults to 'optimism-VERSIONHERE'.", + Hidden: true, + Required: false, + Value: "", + EnvVar: p2pEnv("AGENT"), + } + TimeoutNegotiation = cli.DurationFlag{ + Name: "p2p.timeout.negotiation", + Usage: "Negotiation timeout, time for new peer connections to share their their supported p2p protocols", + Hidden: true, + Required: false, + Value: 10 * time.Second, + EnvVar: p2pEnv("TIMEOUT_NEGOTIATION"), + } + TimeoutAccept = cli.DurationFlag{ + Name: "p2p.timeout.accept", + Usage: "Accept timeout, time for connection to be accepted.", + Hidden: true, + Required: false, + Value: 10 * time.Second, + EnvVar: p2pEnv("TIMEOUT_ACCEPT"), + } + TimeoutDial = cli.DurationFlag{ + Name: "p2p.timeout.dial", + Usage: "Dial timeout for outgoing connection requests", + Hidden: true, + Required: false, + Value: 10 * time.Second, + EnvVar: p2pEnv("TIMEOUT_DIAL"), + } + PeerstorePath = cli.StringFlag{ + Name: "p2p.peerstore.path", + Usage: "Peerstore database location. Persisted peerstores help recover peers after restarts. " + + "Set to 'memory' to never persist the peerstore. Peerstore records will be pruned / expire as necessary. " + + "Warning: a copy of the priv network key of the local peer will be persisted here.", // TODO: bad design of libp2p, maybe we can avoid this from happening + Required: false, + TakesFile: true, + Value: "opnode_peerstore_db", + EnvVar: p2pEnv("PEERSTORE_PATH"), + } + DiscoveryPath = cli.StringFlag{ + Name: "p2p.discovery.path", + Usage: "Discovered ENRs are persisted in a database to recover from a restart without having to bootstrap the discovery process again. Set to 'memory' to never persist the peerstore.", + Required: false, + TakesFile: true, + Value: "opnode_discovery_db", + EnvVar: p2pEnv("DISCOVERY_PATH"), + } +) + +// None of these flags are strictly required. +// Some are hidden if they are too technical, or not recommended. +var p2pFlags = []cli.Flag{ + DisableP2P, + NoDiscovery, + P2PPrivPath, + P2PPrivRaw, + ListenIP, + ListenTCPPort, + ListenUDPPort, + AdvertiseIP, + AdvertiseTCPPort, + AdvertiseUDPPort, + Bootnodes, + StaticPeers, + HostMux, + HostSecurity, + PeersLo, + PeersHi, + PeersGrace, + NAT, + UserAgent, + TimeoutNegotiation, + TimeoutAccept, + TimeoutDial, + PeerstorePath, + DiscoveryPath, +} diff --git a/opnode/p2p/config.go b/opnode/p2p/config.go new file mode 100644 index 000000000000..396bcc83bc9d --- /dev/null +++ b/opnode/p2p/config.go @@ -0,0 +1,332 @@ +package p2p + +import ( + "crypto/ecdsa" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" + "github.com/ethereum/go-ethereum/p2p/enode" + ds "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/sync" + leveldb "github.com/ipfs/go-ds-leveldb" + core "github.com/libp2p/go-libp2p-core" + "github.com/libp2p/go-libp2p-core/crypto" + mplex "github.com/libp2p/go-libp2p-mplex" + noise "github.com/libp2p/go-libp2p-noise" + tls "github.com/libp2p/go-libp2p-tls" + yamux "github.com/libp2p/go-libp2p-yamux" + lconf "github.com/libp2p/go-libp2p/config" + "github.com/multiformats/go-multiaddr" + "github.com/urfave/cli" + "io/ioutil" + "net" + "os" + "strings" + "time" +) + +type Config struct { + Priv *ecdsa.PrivateKey + + DisableP2P bool + NoDiscovery bool + + ListenIP net.IP + ListenTCPPort uint16 + + // Port to bind discv5 to + ListenUDPPort uint16 + + AdvertiseIP net.IP + AdvertiseTCPPort uint16 + AdvertiseUDPPort uint16 + Bootnodes []*enode.Node + DiscoveryDB *enode.DB + + StaticPeers []core.Multiaddr + + HostMux []lconf.MsMuxC + HostSecurity []lconf.MsSecC + NoTransportSecurity bool + + PeersLo uint + PeersHi uint + PeersGrace time.Duration + + NAT string + + UserAgent string + + TimeoutNegotiation time.Duration + TimeoutAccept time.Duration + TimeoutDial time.Duration + + // Underlying store that hosts connection-gater and peerstore data. + Store ds.Batching +} + +func validatePort(p uint) (uint16, error) { + if p == 0 { + return 0, nil + } + if p >= (1 << 16) { + return 0, fmt.Errorf("port out of range: %d", p) + } + if p < 1024 { + return 0, fmt.Errorf("port is reserved for system: %d", p) + } + return uint16(p), nil +} + +func NewConfig(ctx *cli.Context) (*Config, error) { + conf := &Config{} + + if ctx.GlobalBool(flags.DisableP2P.Name) { + conf.DisableP2P = true + return conf, nil + } + + p, err := loadNetworkPrivKey(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load p2p priv key: %v", err) + } + conf.Priv = p + + if err := conf.loadListenOpts(ctx); err != nil { + return nil, fmt.Errorf("failed to load p2p listen options: %v", err) + } + + if err := conf.loadDiscoveryOpts(ctx); err != nil { + return nil, fmt.Errorf("failed to load p2p discovery options: %v", err) + } + + if err := conf.loadLibp2pOpts(ctx); err != nil { + return nil, fmt.Errorf("failed to load p2p options: %v", err) + } + + return conf, nil +} + +func (conf *Config) loadListenOpts(ctx *cli.Context) error { + listenIP := ctx.GlobalString(flags.ListenIP.Name) + if listenIP != "" { // optional + conf.ListenIP = net.ParseIP(listenIP) + if conf.ListenIP == nil { + return fmt.Errorf("failed to parse IP %q", listenIP) + } + } + var err error + conf.ListenTCPPort, err = validatePort(ctx.GlobalUint(flags.ListenTCPPort.Name)) + if err != nil { + return fmt.Errorf("bad listen TCP port: %v", err) + } + conf.ListenUDPPort, err = validatePort(ctx.GlobalUint(flags.ListenUDPPort.Name)) + if err != nil { + return fmt.Errorf("bad listen UDP port: %v", err) + } + return nil +} + +func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error { + if ctx.GlobalBool(flags.NoDiscovery.Name) { + conf.NoDiscovery = true + } + + var err error + conf.AdvertiseTCPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseTCPPort.Name)) + if err != nil { + return fmt.Errorf("bad advertised TCP port: %v", err) + } + conf.AdvertiseUDPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseUDPPort.Name)) + if err != nil { + return fmt.Errorf("bad advertised UDP port: %v", err) + } + adIP := ctx.GlobalString(flags.AdvertiseIP.Name) + if adIP != "" { // optional + conf.AdvertiseIP = net.ParseIP(adIP) + if conf.AdvertiseIP == nil { + return fmt.Errorf("failed to parse IP %q", adIP) + } + } + + dbPath := ctx.GlobalString(flags.DiscoveryPath.Name) + if dbPath == "" { + dbPath = "opnode_discovery_db" + } + if dbPath == "memory" { + dbPath = "" + } + conf.DiscoveryDB, err = enode.OpenDB(dbPath) + if err != nil { + return fmt.Errorf("failed to open discovery db: %v", err) + } + + records := strings.Split(ctx.GlobalString(flags.Bootnodes.Name), ",") + for i, recordB64 := range records { + nodeRecord, err := enode.Parse(enode.ValidSchemes, strings.TrimSpace(recordB64)) + if err != nil { + return fmt.Errorf("bootnode record %d (of %d) is invalid: %q err: %v", i, len(records), recordB64, err) + } + conf.Bootnodes = append(conf.Bootnodes, nodeRecord) + } + + return nil +} + +func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { + + addrs := strings.Split(ctx.GlobalString(flags.StaticPeers.Name), ",") + for i, addr := range addrs { + a, err := multiaddr.NewMultiaddr(addr) + if err != nil { + return fmt.Errorf("failed to parse multi addr of static peer %d (out of %d): %q err: %v", i, len(addrs), addr, err) + } + conf.StaticPeers = append(conf.StaticPeers, a) + } + + for _, v := range strings.Split(ctx.GlobalString(flags.HostMux.Name), ",") { + v = strings.ToLower(strings.TrimSpace(v)) + var mc lconf.MsMuxC + switch v { + case "yamux": + mtpt, err := lconf.MuxerConstructor(yamux.DefaultTransport) + if err != nil { + return err + } + mc = lconf.MsMuxC{MuxC: mtpt, ID: "/yamux/1.0.0"} + case "mplex": + mtpt, err := lconf.MuxerConstructor(mplex.DefaultTransport) + if err != nil { + return err + } + mc = lconf.MsMuxC{MuxC: mtpt, ID: "/mplex/6.7.0"} + default: + return fmt.Errorf("could not recognize mux %s", v) + } + conf.HostMux = append(conf.HostMux, mc) + } + + secArr := strings.Split(ctx.GlobalString(flags.HostMux.Name), ",") + for _, secOpt := range secArr { + var sc lconf.MsSecC + switch secOpt { + case "none": // no security, for debugging etc. + if len(conf.HostSecurity) > 0 || len(secArr) > 1 { + return errors.New("cannot mix secure transport protocols with no-security") + } + conf.NoTransportSecurity = true + case "noise": + stpt, err := lconf.SecurityConstructor(noise.New) + if err != nil { + return err + } + sc = lconf.MsSecC{SecC: stpt, ID: noise.ID} + case "tls": + stpt, err := lconf.SecurityConstructor(tls.New) + if err != nil { + return err + } + sc = lconf.MsSecC{SecC: stpt, ID: tls.ID} + default: + return fmt.Errorf("could not recognize security %s", secOpt) + } + conf.HostSecurity = append(conf.HostSecurity, sc) + } + + conf.PeersLo = ctx.GlobalUint(flags.PeersLo.Name) + conf.PeersHi = ctx.GlobalUint(flags.PeersHi.Name) + conf.PeersGrace = ctx.GlobalDuration(flags.PeersGrace.Name) + + // TODO parse NAT option + + conf.UserAgent = ctx.GlobalString(flags.UserAgent.Name) + conf.TimeoutNegotiation = ctx.GlobalDuration(flags.TimeoutNegotiation.Name) + conf.TimeoutAccept = ctx.GlobalDuration(flags.TimeoutAccept.Name) + conf.TimeoutDial = ctx.GlobalDuration(flags.TimeoutDial.Name) + + peerstorePath := ctx.GlobalString(flags.PeerstorePath.Name) + if peerstorePath == "" { + return errors.New("peerstore path must be specified, use 'memory' to explicitly not persist peer records") + } + + var err error + var store ds.Batching + if peerstorePath == "memory" { + store = sync.MutexWrap(ds.NewMapDatastore()) + } else { + store, err = leveldb.NewDatastore(peerstorePath, nil) // default leveldb options are fine + if err != nil { + return fmt.Errorf("failed to open leveldb db for peerstore: %v", err) + } + } + conf.Store = store + + return nil +} + +func loadNetworkPrivKey(ctx *cli.Context) (*ecdsa.PrivateKey, error) { + raw := ctx.GlobalString(flags.P2PPrivRaw.Name) + if raw != "" { + return parsePriv(raw) + } + keyPath := ctx.GlobalString(flags.P2PPrivPath.Name) + f, err := os.OpenFile(keyPath, os.O_RDONLY, 0600) + if os.IsNotExist(err) { + p, _, err := crypto.GenerateSecp256k1Key(rand.Reader) + if err != nil { + return nil, fmt.Errorf("failed to generate new p2p priv key: %v", err) + } + b, err := p.Raw() + if err != nil { + return nil, fmt.Errorf("failed to encode new p2p priv key: %v", err) + } + f, err := os.OpenFile(keyPath, os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + return nil, fmt.Errorf("failed to store new p2p priv key: %v", err) + } + defer f.Close() + if _, err := f.WriteString(hex.EncodeToString(b)); err != nil { + return nil, fmt.Errorf("failed to write new p2p priv key: %v", err) + } + return (*ecdsa.PrivateKey)((p).(*crypto.Secp256k1PrivateKey)), nil + } else { + defer f.Close() + data, err := ioutil.ReadAll(f) + if err != nil { + return nil, fmt.Errorf("failed to read priv key file: %v", err) + } + return parsePriv(string(data)) + } +} + +func parsePriv(data string) (*ecdsa.PrivateKey, error) { + if len(data) > 2 && data[:2] == "0x" { + data = data[2:] + } + b, err := hex.DecodeString(data) + if err != nil { + return nil, errors.New("p2p priv key is not formatted in hex chars") + } + p, err := crypto.UnmarshalSecp256k1PrivateKey(b) + return (*ecdsa.PrivateKey)((p).(*crypto.Secp256k1PrivateKey)), nil +} + +func (conf *Config) Check() error { + if conf.DisableP2P { + return nil + } + if conf.Store == nil { + return errors.New("p2p requires a persistent or in-memory peerstore, but found none") + } + if !conf.NoDiscovery { + if conf.DiscoveryDB == nil { + return errors.New("discovery requires a persistent or in-memory discv5 db, but found none") + } + } + if conf.PeersLo == 0 || conf.PeersHi == 0 || conf.PeersLo > conf.PeersHi { + return fmt.Errorf("peers lo/hi tides are invalid: %d, %d", conf.PeersLo, conf.PeersHi) + } + return nil +} diff --git a/opnode/p2p/discovery.go b/opnode/p2p/discovery.go new file mode 100644 index 000000000000..c13b5679097e --- /dev/null +++ b/opnode/p2p/discovery.go @@ -0,0 +1,42 @@ +package p2p + +import ( + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" + "net" +) + +func (conf *Config) Discovery(log log.Logger) (*enode.LocalNode, *discover.UDPv5, error) { + localNode := enode.NewLocalNode(conf.DiscoveryDB, conf.Priv) + if conf.AdvertiseIP != nil { + localNode.SetStaticIP(conf.AdvertiseIP) + } + if conf.AdvertiseUDPPort != 0 { + localNode.SetFallbackUDP(int(conf.AdvertiseUDPPort)) + } + + udpAddr := &net.UDPAddr{ + IP: conf.ListenIP, + Port: int(conf.ListenUDPPort), + } + + conn, err := net.ListenUDP("udp", udpAddr) + if err != nil { + return nil, nil, err + } + + cfg := discover.Config{ + PrivateKey: conf.Priv, + NetRestrict: nil, + Bootnodes: conf.Bootnodes, + Unhandled: nil, // Not used in dv5 + Log: log, + ValidSchemes: enode.ValidSchemes, + } + udpV5, err := discover.ListenV5(conn, localNode, cfg) + if err != nil { + return nil, nil, err + } + return localNode, udpV5, nil +} diff --git a/opnode/p2p/host.go b/opnode/p2p/host.go new file mode 100644 index 000000000000..a87763e221ef --- /dev/null +++ b/opnode/p2p/host.go @@ -0,0 +1,104 @@ +package p2p + +import ( + "context" + "fmt" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/metrics" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-peerstore/pstoreds" + "github.com/libp2p/go-libp2p-swarm" + basichost "github.com/libp2p/go-libp2p/p2p/host/basic" + "github.com/libp2p/go-libp2p/p2p/net/conngater" + "github.com/libp2p/go-libp2p/p2p/net/connmgr" + madns "github.com/multiformats/go-multiaddr-dns" + "time" +) + +func (conf *Config) Host() (host.Host, error) { + // We do some more effort than just calling libp2p.New() so we can: + // - configure the "swarm" setup, to use a more light one during testing + // - hook up new features as they come out + // - swap/customize components more easily + // - control the transport preferences / upgrades + + // we cast the ecdsa key type to the libp2p wrapper, to then use the libp2p pubkey and ID interfaces. + var priv crypto.PrivKey = (*crypto.Secp256k1PrivateKey)(conf.Priv) + pid, err := peer.IDFromPublicKey(priv.GetPublic()) + if err != nil { + return nil, fmt.Errorf("failed to derive pubkey from network priv key: %v", err) + } + + connManager, err := connmgr.NewConnManager( + int(conf.PeersLo), + int(conf.PeersHi), + connmgr.WithGracePeriod(conf.PeersGrace), + connmgr.WithSilencePeriod(time.Minute), + connmgr.WithEmergencyTrim(true)) + if err != nil { + return nil, fmt.Errorf("failed to setup connection manager: %v", err) + } + + bandwidthMetrics := metrics.NewBandwidthCounter() + + peerstore, err := pstoreds.NewPeerstore(context.Background(), conf.Store, pstoreds.DefaultOpts()) + if err != nil { + return nil, fmt.Errorf("failed to open peerstore: %v", err) + } + + connGtr, err := conngater.NewBasicConnectionGater(conf.Store) + if err != nil { + return nil, fmt.Errorf("failed to open connection gater: %v", err) + } + + // TODO: option to swap in the testing.GenSwarm(t, opts...) output here. + + // TODO: we can add swarm.WithResourceManager() to manage resources per peer better. + network, err := swarm.NewSwarm(pid, peerstore, + swarm.WithMetrics(bandwidthMetrics), + swarm.WithDialTimeout(conf.TimeoutDial), + swarm.WithConnectionGater(connGtr)) + if err != nil { + return nil, fmt.Errorf("failed to create libp2p network core: %v", err) + } + + // TODO: combine muxers + // TODO: combine secure transports + // TODO: create transport upgrader + // TODO: add tptu transport to network + + h, err := basichost.NewHost(network, &basichost.HostOpts{ + MultistreamMuxer: nil, + NegotiationTimeout: conf.TimeoutNegotiation, + AddrsFactory: nil, + // We can change / disable the DNS resolving of names in multi-addrs if we want to. Default is fine. + MultiaddrResolver: madns.DefaultResolver, + // The default NAT manager just tracks mappings. Auto-nat / fixed IP etc. options are separate. + NATManager: basichost.NewNATManager, + ConnManager: connManager, + // Ping is a small built-in libp2p protocol that helps us check/debug latency between peers. + EnablePing: true, + // We don't enable relay for now, nodes should just rely on real NAT methods instead + EnableRelayService: false, + RelayServiceOpts: nil, + // Explicitly set the user-agent, so we can differentiate from other Go libp2p users. + UserAgent: conf.UserAgent, + // We don't strictly need these, but no harm in enabling + DisableSignedPeerRecord: false, + // TODO: hole punching is new, need to review differences with NAT manager options + EnableHolePunching: false, + HolePunchingOptions: nil, + }) + if err != nil { + return nil, fmt.Errorf("failed to setup new host: %v", err) + } + + // TODO: do we want to immediately listen on the network? + //h.Network().Listen() + + // TODO: maybe setup autonat, the new libp2p one (not old deprecated autonat) + // https://github.com/libp2p/go-libp2p/tree/master/p2p/host/autonat + + return h, nil +} From 2111345a6a08239691669b7b92c797d8f88a19e6 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 14 Apr 2022 12:55:25 +0200 Subject: [PATCH 481/585] p2p flags, config, and libp2p + discv5 setup --- go.mod | 32 +++++++++ go.sum | 2 + opnode/flags/p2p_flags.go | 8 +-- opnode/p2p/config.go | 120 +++++++++++++++++++++++-------- opnode/p2p/discovery.go | 7 +- opnode/p2p/host.go | 146 ++++++++++++++++++++++---------------- opnode/p2p/host_test.go | 136 +++++++++++++++++++++++++++++++++++ 7 files changed, 355 insertions(+), 96 deletions(-) create mode 100644 opnode/p2p/host_test.go diff --git a/go.mod b/go.mod index 2904b1b3e9a8..14155f97dbec 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/libp2p/go-libp2p-swarm v0.10.2 github.com/libp2p/go-libp2p-tls v0.3.1 github.com/libp2p/go-libp2p-yamux v0.9.0 + github.com/libp2p/go-tcp-transport v0.5.1 github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/multiformats/go-multiaddr v0.5.0 github.com/multiformats/go-multiaddr-dns v0.3.1 @@ -27,10 +28,12 @@ require ( require ( github.com/VictoriaMetrics/fastcache v1.9.0 // indirect github.com/benbjohnson/clock v1.1.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect github.com/btcsuite/btcd/btcec/v2 v2.1.2 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cheekybits/genny v1.0.0 // indirect github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 // indirect github.com/coreos/go-systemd/v22 v22.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect @@ -43,12 +46,16 @@ require ( github.com/elastic/gosigar v0.12.0 // indirect github.com/fjl/memsize v0.0.1 // indirect github.com/flynn/noise v1.0.0 // indirect + github.com/francoispqt/gojay v1.2.13 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/godbus/dbus/v5 v5.0.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/uuid v1.3.0 // indirect @@ -62,6 +69,7 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect + github.com/klauspost/compress v1.13.6 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/koron/go-ssdp v0.0.2 // indirect github.com/libp2p/go-buffer-pool v0.0.2 // indirect @@ -73,18 +81,30 @@ require ( github.com/libp2p/go-libp2p-blankhost v0.3.0 // indirect github.com/libp2p/go-libp2p-nat v0.1.0 // indirect github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect + github.com/libp2p/go-libp2p-quic-transport v0.16.1 // indirect + github.com/libp2p/go-libp2p-testing v0.9.2 // indirect github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 // indirect github.com/libp2p/go-mplex v0.6.0 // indirect github.com/libp2p/go-msgio v0.1.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect github.com/libp2p/go-netroute v0.2.0 // indirect github.com/libp2p/go-openssl v0.0.7 // indirect + github.com/libp2p/go-reuseport v0.1.0 // indirect + github.com/libp2p/go-reuseport-transport v0.1.0 // indirect github.com/libp2p/go-stream-muxer-multistream v0.4.0 // indirect github.com/libp2p/go-yamux/v3 v3.1.0 // indirect + github.com/lucas-clemente/quic-go v0.25.0 // indirect + github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect + github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect + github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/miekg/dns v1.1.43 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect @@ -98,10 +118,16 @@ require ( github.com/multiformats/go-multihash v0.0.15 // indirect github.com/multiformats/go-multistream v0.2.2 // indirect github.com/multiformats/go-varint v0.0.6 // indirect + github.com/nxadm/tail v1.4.8 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.11.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 github.com/prometheus/tsdb v0.10.0 // indirect github.com/raulk/clock v1.1.0 // indirect github.com/raulk/go-watchdog v1.2.0 // indirect @@ -123,12 +149,18 @@ require ( go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.19.1 // indirect golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/mod v0.4.2 // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + golang.org/x/tools v0.1.5 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/grpc v1.40.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/urfave/cli.v1 v1.20.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 04c93470f102..eab315cdc38e 100644 --- a/go.sum +++ b/go.sum @@ -358,6 +358,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -735,6 +736,7 @@ github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= github.com/miguelmota/go-ethereum-hdwallet v0.1.1/go.mod h1:f9m9uXokAHA6WNoYOPjj4AqjJS5pquQRiYYj/XSyPYc= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= diff --git a/opnode/flags/p2p_flags.go b/opnode/flags/p2p_flags.go index 828770082e32..ad5b865c330b 100644 --- a/opnode/flags/p2p_flags.go +++ b/opnode/flags/p2p_flags.go @@ -1,8 +1,9 @@ package flags import ( - "github.com/urfave/cli" "time" + + "github.com/urfave/cli" ) func p2pEnv(v string) string { @@ -134,11 +135,10 @@ var ( Value: 30 * time.Second, EnvVar: p2pEnv("PEERS_GRACE"), } - NAT = cli.StringFlag{ + NAT = cli.BoolFlag{ Name: "p2p.nat", - Usage: "NAT options. Empty for dynamic defaults. 'none' to disable. Set to 'extip:IPHERE' to use a static IP. Or 'upnp', or 'pmp'. Used to inform LibP2P of the external IP to put into multiaddrs.", + Usage: "Enable NAT traversal with PMP/UPNP devices to learn external IP.", Required: false, - Value: "", EnvVar: p2pEnv("NAT"), } UserAgent = cli.StringFlag{ diff --git a/opnode/p2p/config.go b/opnode/p2p/config.go index 396bcc83bc9d..84d8a131b2a0 100644 --- a/opnode/p2p/config.go +++ b/opnode/p2p/config.go @@ -6,25 +6,30 @@ import ( "encoding/hex" "errors" "fmt" + "io/ioutil" + "net" + "os" + "strings" + "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" "github.com/ethereum/go-ethereum/p2p/enode" ds "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/sync" leveldb "github.com/ipfs/go-ds-leveldb" core "github.com/libp2p/go-libp2p-core" + "github.com/libp2p/go-libp2p-core/connmgr" "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/metrics" mplex "github.com/libp2p/go-libp2p-mplex" noise "github.com/libp2p/go-libp2p-noise" tls "github.com/libp2p/go-libp2p-tls" yamux "github.com/libp2p/go-libp2p-yamux" lconf "github.com/libp2p/go-libp2p/config" + "github.com/libp2p/go-libp2p/p2p/net/conngater" + cmgr "github.com/libp2p/go-libp2p/p2p/net/connmgr" "github.com/multiformats/go-multiaddr" "github.com/urfave/cli" - "io/ioutil" - "net" - "os" - "strings" - "time" ) type Config struct { @@ -55,7 +60,8 @@ type Config struct { PeersHi uint PeersGrace time.Duration - NAT string + // If true a NAT manager will host a NAT port mapping that is updated with PMP and UPNP by libp2p/go-nat + NAT bool UserAgent string @@ -65,6 +71,24 @@ type Config struct { // Underlying store that hosts connection-gater and peerstore data. Store ds.Batching + + ConnGater func(conf *Config) (connmgr.ConnectionGater, error) + ConnMngr func(conf *Config) (connmgr.ConnManager, error) + // nil to disable bandwidth metrics + BandwidthMetrics metrics.Reporter +} + +func DefaultConnGater(conf *Config) (connmgr.ConnectionGater, error) { + return conngater.NewBasicConnectionGater(conf.Store) +} + +func DefaultConnManager(conf *Config) (connmgr.ConnManager, error) { + return cmgr.NewConnManager( + int(conf.PeersLo), + int(conf.PeersHi), + cmgr.WithGracePeriod(conf.PeersGrace), + cmgr.WithSilencePeriod(time.Minute), + cmgr.WithEmergencyTrim(true)) } func validatePort(p uint) (uint16, error) { @@ -106,6 +130,9 @@ func NewConfig(ctx *cli.Context) (*Config, error) { return nil, fmt.Errorf("failed to load p2p options: %v", err) } + conf.ConnGater = DefaultConnGater + conf.ConnMngr = DefaultConnManager + return conf, nil } @@ -175,6 +202,38 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error { return nil } +func yamuxC() (lconf.MsMuxC, error) { + mtpt, err := lconf.MuxerConstructor(yamux.DefaultTransport) + if err != nil { + return lconf.MsMuxC{}, err + } + return lconf.MsMuxC{MuxC: mtpt, ID: "/yamux/1.0.0"}, nil +} + +func mplexC() (lconf.MsMuxC, error) { + mtpt, err := lconf.MuxerConstructor(mplex.DefaultTransport) + if err != nil { + return lconf.MsMuxC{}, err + } + return lconf.MsMuxC{MuxC: mtpt, ID: "/mplex/6.7.0"}, nil +} + +func noiseC() (lconf.MsSecC, error) { + stpt, err := lconf.SecurityConstructor(noise.New) + if err != nil { + return lconf.MsSecC{}, err + } + return lconf.MsSecC{SecC: stpt, ID: noise.ID}, nil +} + +func tlsC() (lconf.MsSecC, error) { + stpt, err := lconf.SecurityConstructor(tls.New) + if err != nil { + return lconf.MsSecC{}, err + } + return lconf.MsSecC{SecC: stpt, ID: tls.ID}, nil +} + func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { addrs := strings.Split(ctx.GlobalString(flags.StaticPeers.Name), ",") @@ -189,48 +248,41 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { for _, v := range strings.Split(ctx.GlobalString(flags.HostMux.Name), ",") { v = strings.ToLower(strings.TrimSpace(v)) var mc lconf.MsMuxC + var err error switch v { case "yamux": - mtpt, err := lconf.MuxerConstructor(yamux.DefaultTransport) - if err != nil { - return err - } - mc = lconf.MsMuxC{MuxC: mtpt, ID: "/yamux/1.0.0"} + mc, err = yamuxC() case "mplex": - mtpt, err := lconf.MuxerConstructor(mplex.DefaultTransport) - if err != nil { - return err - } - mc = lconf.MsMuxC{MuxC: mtpt, ID: "/mplex/6.7.0"} + mc, err = mplexC() default: return fmt.Errorf("could not recognize mux %s", v) } + if err != nil { + return fmt.Errorf("failed to make %s constructor: %v", v, err) + } conf.HostMux = append(conf.HostMux, mc) } secArr := strings.Split(ctx.GlobalString(flags.HostMux.Name), ",") - for _, secOpt := range secArr { + for _, v := range secArr { + v = strings.ToLower(strings.TrimSpace(v)) var sc lconf.MsSecC - switch secOpt { + var err error + switch v { case "none": // no security, for debugging etc. if len(conf.HostSecurity) > 0 || len(secArr) > 1 { return errors.New("cannot mix secure transport protocols with no-security") } conf.NoTransportSecurity = true case "noise": - stpt, err := lconf.SecurityConstructor(noise.New) - if err != nil { - return err - } - sc = lconf.MsSecC{SecC: stpt, ID: noise.ID} + sc, err = noiseC() case "tls": - stpt, err := lconf.SecurityConstructor(tls.New) - if err != nil { - return err - } - sc = lconf.MsSecC{SecC: stpt, ID: tls.ID} + sc, err = tlsC() default: - return fmt.Errorf("could not recognize security %s", secOpt) + return fmt.Errorf("could not recognize security %s", v) + } + if err != nil { + return fmt.Errorf("failed to make %s constructor: %v", v, err) } conf.HostSecurity = append(conf.HostSecurity, sc) } @@ -310,6 +362,10 @@ func parsePriv(data string) (*ecdsa.PrivateKey, error) { return nil, errors.New("p2p priv key is not formatted in hex chars") } p, err := crypto.UnmarshalSecp256k1PrivateKey(b) + if err != nil { + // avoid logging the priv key in the error, but hint at likely input length problem + return nil, fmt.Errorf("failed to parse priv key from %d bytes", len(b)) + } return (*ecdsa.PrivateKey)((p).(*crypto.Secp256k1PrivateKey)), nil } @@ -328,5 +384,11 @@ func (conf *Config) Check() error { if conf.PeersLo == 0 || conf.PeersHi == 0 || conf.PeersLo > conf.PeersHi { return fmt.Errorf("peers lo/hi tides are invalid: %d, %d", conf.PeersLo, conf.PeersHi) } + if conf.ConnMngr == nil { + return errors.New("need a connection manager") + } + if conf.ConnGater == nil { + return errors.New("need a connection gater") + } return nil } diff --git a/opnode/p2p/discovery.go b/opnode/p2p/discovery.go index c13b5679097e..c566660453dd 100644 --- a/opnode/p2p/discovery.go +++ b/opnode/p2p/discovery.go @@ -1,10 +1,11 @@ package p2p import ( + "net" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" - "net" ) func (conf *Config) Discovery(log log.Logger) (*enode.LocalNode, *discover.UDPv5, error) { @@ -38,5 +39,9 @@ func (conf *Config) Discovery(log log.Logger) (*enode.LocalNode, *discover.UDPv5 if err != nil { return nil, nil, err } + + // TODO: periodically we can pull the external IP from libp2p NAT service, + // and add it as a statement to keep the localNode accurate (if we trust the NAT device more than the discv5 statements) + return localNode, udpV5, nil } diff --git a/opnode/p2p/host.go b/opnode/p2p/host.go index a87763e221ef..08d412353703 100644 --- a/opnode/p2p/host.go +++ b/opnode/p2p/host.go @@ -3,102 +3,124 @@ package p2p import ( "context" "fmt" + "net" + "time" + "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/host" - "github.com/libp2p/go-libp2p-core/metrics" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-peerstore/pstoreds" - "github.com/libp2p/go-libp2p-swarm" + lconf "github.com/libp2p/go-libp2p/config" basichost "github.com/libp2p/go-libp2p/p2p/host/basic" - "github.com/libp2p/go-libp2p/p2p/net/conngater" - "github.com/libp2p/go-libp2p/p2p/net/connmgr" + tcp "github.com/libp2p/go-tcp-transport" + ma "github.com/multiformats/go-multiaddr" madns "github.com/multiformats/go-multiaddr-dns" - "time" ) func (conf *Config) Host() (host.Host, error) { - // We do some more effort than just calling libp2p.New() so we can: - // - configure the "swarm" setup, to use a more light one during testing - // - hook up new features as they come out - // - swap/customize components more easily - // - control the transport preferences / upgrades - // we cast the ecdsa key type to the libp2p wrapper, to then use the libp2p pubkey and ID interfaces. var priv crypto.PrivKey = (*crypto.Secp256k1PrivateKey)(conf.Priv) - pid, err := peer.IDFromPublicKey(priv.GetPublic()) + pub := priv.GetPublic() + pid, err := peer.IDFromPublicKey(pub) if err != nil { return nil, fmt.Errorf("failed to derive pubkey from network priv key: %v", err) } - connManager, err := connmgr.NewConnManager( - int(conf.PeersLo), - int(conf.PeersHi), - connmgr.WithGracePeriod(conf.PeersGrace), - connmgr.WithSilencePeriod(time.Minute), - connmgr.WithEmergencyTrim(true)) + ps, err := pstoreds.NewPeerstore(context.Background(), conf.Store, pstoreds.DefaultOpts()) if err != nil { - return nil, fmt.Errorf("failed to setup connection manager: %v", err) + return nil, fmt.Errorf("failed to open peerstore: %v", err) } - bandwidthMetrics := metrics.NewBandwidthCounter() - - peerstore, err := pstoreds.NewPeerstore(context.Background(), conf.Store, pstoreds.DefaultOpts()) - if err != nil { - return nil, fmt.Errorf("failed to open peerstore: %v", err) + if err := ps.AddPrivKey(pid, priv); err != nil { + return nil, fmt.Errorf("failed to set up peerstore with priv key: %v", err) + } + if err := ps.AddPubKey(pid, pub); err != nil { + return nil, fmt.Errorf("failed to set up peerstore with pub key: %v", err) } - connGtr, err := conngater.NewBasicConnectionGater(conf.Store) + connGtr, err := conf.ConnGater(conf) if err != nil { return nil, fmt.Errorf("failed to open connection gater: %v", err) } - // TODO: option to swap in the testing.GenSwarm(t, opts...) output here. + connMngr, err := conf.ConnMngr(conf) + if err != nil { + return nil, fmt.Errorf("failed to open connection manager: %v", err) + } - // TODO: we can add swarm.WithResourceManager() to manage resources per peer better. - network, err := swarm.NewSwarm(pid, peerstore, - swarm.WithMetrics(bandwidthMetrics), - swarm.WithDialTimeout(conf.TimeoutDial), - swarm.WithConnectionGater(connGtr)) + listenAddr, err := addrFromIPAndPort(conf.ListenIP, conf.ListenTCPPort) if err != nil { - return nil, fmt.Errorf("failed to create libp2p network core: %v", err) + return nil, fmt.Errorf("failed to make listen addr: %v", err) } + tcpTransport, err := lconf.TransportConstructor( + tcp.NewTCPTransport, + tcp.WithConnectionTimeout(time.Minute*60)) // break unused connections + if err != nil { + return nil, fmt.Errorf("failed to create TCP transport: %v", err) + } + // TODO: technically we can also run the node on websocket and QUIC transports. Maybe in the future? - // TODO: combine muxers - // TODO: combine secure transports - // TODO: create transport upgrader - // TODO: add tptu transport to network + var nat lconf.NATManagerC // disabled if nil + if conf.NAT { + nat = basichost.NewNATManager + } - h, err := basichost.NewHost(network, &basichost.HostOpts{ - MultistreamMuxer: nil, - NegotiationTimeout: conf.TimeoutNegotiation, - AddrsFactory: nil, - // We can change / disable the DNS resolving of names in multi-addrs if we want to. Default is fine. - MultiaddrResolver: madns.DefaultResolver, - // The default NAT manager just tracks mappings. Auto-nat / fixed IP etc. options are separate. - NATManager: basichost.NewNATManager, - ConnManager: connManager, - // Ping is a small built-in libp2p protocol that helps us check/debug latency between peers. - EnablePing: true, - // We don't enable relay for now, nodes should just rely on real NAT methods instead - EnableRelayService: false, - RelayServiceOpts: nil, + p2pConf := &lconf.Config{ // Explicitly set the user-agent, so we can differentiate from other Go libp2p users. UserAgent: conf.UserAgent, - // We don't strictly need these, but no harm in enabling - DisableSignedPeerRecord: false, + + PeerKey: priv, + Transports: []lconf.TptC{tcpTransport}, + Muxers: conf.HostMux, + SecurityTransports: conf.HostSecurity, + Insecure: conf.NoTransportSecurity, + PSK: nil, // TODO: expose private subnet option to CLI / testing + DialTimeout: conf.TimeoutDial, + // No relay services, direct connections between peers only. + RelayCustom: false, + Relay: false, + EnableRelayService: false, + RelayServiceOpts: nil, + // host will start and listen to network directly after construction from config. + ListenAddrs: []ma.Multiaddr{listenAddr}, + + AddrsFactory: nil, + ConnectionGater: connGtr, + ConnManager: connMngr, + ResourceManager: nil, // TODO use resource manager interface to manage resources per peer better. + NATManager: nat, + Peerstore: ps, + Reporter: conf.BandwidthMetrics, // may be nil if disabled + MultiaddrResolver: madns.DefaultResolver, + // Ping is a small built-in libp2p protocol that helps us check/debug latency between peers. + DisablePing: false, + Routing: nil, + EnableAutoRelay: false, // don't act as auto relay service + // Help peers with their NAT reachability status, but throttle to avoid too much work. + AutoNATConfig: lconf.AutoNATConfig{ + ForceReachability: nil, + EnableService: true, + ThrottleGlobalLimit: 10, + ThrottlePeerLimit: 5, + ThrottleInterval: time.Second * 60, + }, + // no static-relays, a "sentry" type infra with static peers and redundancy seems better + StaticRelayOpt: nil, + // TODO: hole punching is new, need to review differences with NAT manager options EnableHolePunching: false, HolePunchingOptions: nil, - }) - if err != nil { - return nil, fmt.Errorf("failed to setup new host: %v", err) } + return p2pConf.NewNode() +} - // TODO: do we want to immediately listen on the network? - //h.Network().Listen() - - // TODO: maybe setup autonat, the new libp2p one (not old deprecated autonat) - // https://github.com/libp2p/go-libp2p/tree/master/p2p/host/autonat - - return h, nil +// Creates a multi-addr to bind to. Does not contain a PeerID component (required for usage by external peers) +func addrFromIPAndPort(ip net.IP, port uint16) (ma.Multiaddr, error) { + ipScheme := "ip4" + if ip4 := ip.To4(); ip4 == nil { + ipScheme = "ip6" + } else { + ip = ip4 + } + return ma.NewMultiaddr(fmt.Sprintf("/%s/%s/tcp/%d", ipScheme, ip.String(), port)) } diff --git a/opnode/p2p/host_test.go b/opnode/p2p/host_test.go new file mode 100644 index 000000000000..0442d4a5e657 --- /dev/null +++ b/opnode/p2p/host_test.go @@ -0,0 +1,136 @@ +package p2p + +import ( + "context" + "crypto/ecdsa" + "crypto/rand" + "net" + "testing" + "time" + + ds "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/sync" + "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + tswarm "github.com/libp2p/go-libp2p-swarm/testing" + yamux "github.com/libp2p/go-libp2p-yamux" + lconf "github.com/libp2p/go-libp2p/config" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + "github.com/stretchr/testify/assert" +) + +func TestingConfig(t *testing.T) *Config { + p, _, err := crypto.GenerateSecp256k1Key(rand.Reader) + assert.NoError(t, err, "failed to generate new p2p priv key") + mtpt, err := lconf.MuxerConstructor(yamux.DefaultTransport) + assert.NoError(t, err) + mux := lconf.MsMuxC{MuxC: mtpt, ID: "/yamux/1.0.0"} + + return &Config{ + Priv: (*ecdsa.PrivateKey)((p).(*crypto.Secp256k1PrivateKey)), + DisableP2P: false, + NoDiscovery: true, // we statically peer during most tests. + ListenIP: net.IP{127, 0, 0, 1}, + ListenTCPPort: 0, // bind to any available port + StaticPeers: nil, + HostMux: []lconf.MsMuxC{mux}, + NoTransportSecurity: true, + PeersLo: 1, + PeersHi: 10, + PeersGrace: time.Second * 10, + NAT: false, + UserAgent: "optimism-testing", + TimeoutNegotiation: time.Second * 2, + TimeoutAccept: time.Second * 2, + TimeoutDial: time.Second * 2, + Store: sync.MutexWrap(ds.NewMapDatastore()), + ConnGater: func(conf *Config) (connmgr.ConnectionGater, error) { + return tswarm.DefaultMockConnectionGater(), nil + }, + ConnMngr: DefaultConnManager, + } +} + +// Simplified p2p test, to debug/test basic libp2p things with +func TestP2PSimple(t *testing.T) { + confA := TestingConfig(t) + confB := TestingConfig(t) + hostA, err := confA.Host() + assert.NoError(t, err, "failed to launch host A") + defer hostA.Close() + hostB, err := confB.Host() + assert.NoError(t, err, "failed to launch host B") + defer hostB.Close() + err = hostA.Connect(context.Background(), peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) + assert.NoError(t, err, "failed to connect to peer B from peer A") + assert.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) +} + +// Full setup, using negotiated transport security and muxes +func TestP2PFull(t *testing.T) { + pA, _, err := crypto.GenerateSecp256k1Key(rand.Reader) + assert.NoError(t, err, "failed to generate new p2p priv key") + pB, _, err := crypto.GenerateSecp256k1Key(rand.Reader) + assert.NoError(t, err, "failed to generate new p2p priv key") + + mplexC, err := mplexC() + assert.NoError(t, err) + yamuxC, err := yamuxC() + assert.NoError(t, err) + noiseC, err := noiseC() + assert.NoError(t, err) + tlsC, err := tlsC() + assert.NoError(t, err) + + confA := Config{ + Priv: (*ecdsa.PrivateKey)((pA).(*crypto.Secp256k1PrivateKey)), + DisableP2P: false, + NoDiscovery: true, + ListenIP: net.IP{127, 0, 0, 1}, + ListenTCPPort: 0, // bind to any available port + StaticPeers: nil, + HostMux: []lconf.MsMuxC{yamuxC, mplexC}, + HostSecurity: []lconf.MsSecC{noiseC, tlsC}, + NoTransportSecurity: false, + PeersLo: 1, + PeersHi: 10, + PeersGrace: time.Second * 10, + NAT: false, + UserAgent: "optimism-testing", + TimeoutNegotiation: time.Second * 2, + TimeoutAccept: time.Second * 2, + TimeoutDial: time.Second * 2, + Store: sync.MutexWrap(ds.NewMapDatastore()), + ConnGater: DefaultConnGater, + ConnMngr: DefaultConnManager, + } + // copy config A, and change the settings for B + confB := confA + confB.Priv = (*ecdsa.PrivateKey)((pB).(*crypto.Secp256k1PrivateKey)) + confB.Store = sync.MutexWrap(ds.NewMapDatastore()) + // TODO: maybe swap the order of sec/mux preferences, to test that negotiation works + + hostA, err := confA.Host() + assert.NoError(t, err) + defer hostA.Close() + hostB, err := confB.Host() + assert.NoError(t, err) + defer hostB.Close() + err = hostA.Connect(context.Background(), peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) + assert.NoError(t, err, "failed to connect to peer B from peer A") + assert.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) +} + +// Most tests should use mocknets instead of using the actual local host network +func TestP2PMocknet(t *testing.T) { + mnet, err := mocknet.FullMeshConnected(3) + assert.NoError(t, err, "failed to setup mocknet") + defer mnet.Close() + hosts := mnet.Hosts() + hostA, hostB, hostC := hosts[0], hosts[1], hosts[2] + assert.Equal(t, hostA.Network().Connectedness(hostB.ID()), network.Connected) + assert.Equal(t, hostA.Network().Connectedness(hostC.ID()), network.Connected) + assert.Equal(t, hostB.Network().Connectedness(hostC.ID()), network.Connected) +} From f427eddac87c611d8f2a3040bcdc46e99f1fd55d Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 14 Apr 2022 13:34:51 +0200 Subject: [PATCH 482/585] specs: initial rollup node p2p spec --- specs/rollup-node-p2p.md | 258 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 specs/rollup-node-p2p.md diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md new file mode 100644 index 000000000000..5b92731a03ab --- /dev/null +++ b/specs/rollup-node-p2p.md @@ -0,0 +1,258 @@ +# Rollup-node P2P interface + +The [rollup node](./rollup-node.md) has an optional peer-to-peer (P2P) network service to improve the latency between +the view of sequencers and the rest of the network by bypassing the L1 in the happy case, +without relying on a single centralized endpoint. + +This also enables faster historical sync to be bootstrapped by providing block headers to sync towards, +and only having to compare the L2 chain inputs to the L1 data as compared to processing everything one block at a time. + +The rollup node will *always* prioritize L1 and reorganize to match the canonical chain. +The L2 data retrieved via the P2P interface is strictly a speculative extension to improve the happy case performance. + +This also means that P2P behavior is a soft-rule: nodes keep each other in check with scoring and eventual banning +of malicious peers by identity or IP. Any behavior on the P2P layer does not affect the rollup security, at worst nodes +rely on higher-latency data from L1 to serve. + +In summary, the P2P stack looks like: + +- Discovery to find peers: [Discv5][discv5] +- Connections, peering, transport security, multi-plexing, gossip: [LibP2P][libp2p] +- Application-layer publishing and validation of gossiped messages like L2 blocks. + +This document only specifies the composition and configuration of these network libraries. +These components have their own standards, implementations in Go/Rust/Java/Nim/JS/more, +and are adopted by several other blockchains, most notably the [L1 consensus layer (Eth2)][eth2-p2p]. + +## P2P configuration + +### Identification + +Nodes have a **separate** network- and consensus-identity. +The network identity is a `secp256k1` key, used for both discovery and active LibP2P connections. + +Common representations of network identity: + +- `PeerID`: a LibP2P specific ID derived from the pubkey (through protobuf encoding, typing and hashing) +- `NodeID`: a Discv5 specific ID derived from the pubkey (through hashing, used in the DHT) +- `Multi-address`: an unsigned address, containing: IP, TCP port, PeerID +- `ENR`: a signed record used for discovery, containing: IP, TCP port, UDP port, signature (pubkey can be derived) + and L2 network identification. Generally encoded in base64. + +### Discv5 + +#### Structure + +The Ethereum Node Record (ENR) for an Optimism rollup node must contain the following values, identified by unique keys: + +- An IPv4 address (`ip` field) and/or IPv6 address (`ip6` field). +- A TCP port (`tcp` field) representing the local libp2p listening port. +- A UDP port (`udp` field) representing the local discv5 listening port. +- An Optimism (`optimism` field) L2 network identifier + +The `optimism` value is encoded as the concatenation of: + +- chain ID (`varint`) +- fork ID (`varint`) + +Note that DiscV5 is a shared DHT (Distributed Hash Table): the L1 consensus and execution nodes, +as well as testnet nodes, and even external IOT nodes, all communicate records in this large common DHT. +This makes it more difficult to censor the discovery of node records. + +The discovery process in Optimism is a pipeline of node records: + +1. Fill the table with `FINDNODES` if necessary (Performed by Discv5 library) +2. Pull additional records with searches to random Node IDs if necessary + (e.g. iterate [`RandomNodes()`][discv5-random-nodes] in Go implementation) +3. Pull records from the DiscV5 module when looking for peers +4. Check if the record contains the `optimism` entry, verify it matches the chain ID and current or future fork number +5. If not already connected, and not recently disconnected or put on deny-list, attempt to dial. + +### LibP2P + +#### Transport + +TCP transport. Additional transports are supported by LibP2P, but not required. + +#### Dialing + +Nodes should be publicly dialable, not rely on relay extensions, and able to dial both IPv4 and IPv6. + +#### NAT + +The listening endpoint must be publicly facing, but may be configured behind a NAT. +LibP2P will use PMP / UPNP based techniques to track the external IP of the node. +It is recommended to disable the above if the external IP is static and configured manually. + +#### Peer management + +The default is to maintain a peer count with a tide-system based on active peer count: + +- At "low tide" the node starts to actively search for additional peer connections. +- At "high tide" the node starts to prune active connections, + except those that are marked as trusted or have a grace period. + +Peers will have a grace period for a configurable amount of time after joining. +In emergency, when memory runs low, the node should start pruning more aggressively. + +Peer records can be persisted to disk to quickly reconnect with known peers after restarting the rollup node. + +The discovery process feeds the peerstore with peer records to connect to, tagged with a time-to-live (TTL). +The current P2P processes do not require selective topic-specific peer connections, +other than filtering for the basic network participation requirement. + +Peers may be banned if their performance score is too low, or if an objectively malicious action was detected. + +Banned peers will be persisted to the same data-store as the peerstore records. + +TODO: the connection gater does currently not gate by IP address on the dial Accept-callback. + +#### Transport security + +[Libp2p-noise][libp2p-noise], `XX` handshake, with the the `secp256k1` P2P identity, as popularized in Eth2. +The TLS option is available as well, but `noise` should be prioritized in negotiation. + +#### Protocol negotiation + +[Multistream-select 1.0][multistream-select] (`/multistream/1.0.0`) is an interactive protocol +used to negotiate sub-protocols supported in LibP2P peers. Multistream-select 2.0 may be used in the future. + +#### Identify + +LibP2P offers a minimal identification module to share client version and programming language. +This is optional and can be disabled for enhanced privacy. +It also includes the same protocol negotiation information, which can speed up initial connections. + +#### Ping + +LibP2P includes a simple ping protocol to track latency between connections. +This should be enabled to help provide insight into the network health. + +#### Multiplexing + +For async communication over different channels over the same connection, multiplexing is used. +[mplex][mplex] (`/mplex/6.7.0`) is required, and [yamux][yamux] (`/yamux/1.0.0`) is recommended but optional + +#### GossipSub + +[GossipSub 1.1](gossipsub) (`/meshsub/1.1.0`, i.e. with peer-scoring extension) is a pubsub protocol for mesh-networks, +deployed on L1 consensus (Eth2) and other protocols such as Filecoin, offering lots of customization options. + +##### Content-based message identification + +Messages are deduplicated, and filtered through application-layer signature verification. +Thus origin-stamping is disabled and published messages must only contain application data, +enforced through a [`StrictNoSign` Signature Policy][signature-policy] + +This provides greater privacy, and allows sequencers (consensus identity) to maintain +multiple network identities for redundancy. + +##### Message compression and limits + +The application contents are compressed with [snappy][snappy] single-block-compression +(as opposed to frame-compression), and constrained to 10 MiB. + +##### Message ID computation + +[Same as L1][l1-message-id], with recognition of compression: + +- If `message.data` has a valid snappy decompression, set `message-id` to the first 20 bytes of the `SHA256` hash of + the concatenation of `MESSAGE_DOMAIN_VALID_SNAPPY` with the snappy decompressed message data, + i.e. `SHA256(MESSAGE_DOMAIN_VALID_SNAPPY + snappy_decompress(message.data))[:20]`. +- Otherwise, set `message-id` to the first 20 bytes of the `SHA256` hash of + the concatenation of `MESSAGE_DOMAIN_INVALID_SNAPPY` with the raw message data, + i.e. `SHA256(MESSAGE_DOMAIN_INVALID_SNAPPY + message.data)[:20]`. + +#### Heartbeat and parameters + +GossipSub [parameters][gossip-parameters]: + +- `D` (topic stable mesh target count): 8 +- `D_low` (topic stable mesh low watermark): 6 +- `D_high` (topic stable mesh high watermark): 12 +- `D_lazy` (gossip target): 6 +- `heartbeat_interval` (frequency of heartbeat, seconds): 0.5 +- `fanout_ttl` (ttl for fanout maps for topics we are not subscribed to but have published to, seconds): 24 +- `mcache_len` (number of windows to retain full messages in cache for `IWANT` responses): 12 +- `mcache_gossip` (number of windows to gossip about): 3 +- `seen_ttl` (number of heartbeat intervals to retain message IDs): 40 + +Notable differences from L1 consensus (Eth2): + +- `seen_ttl` does not need to cover a full L1 epoch (6.4 minutes), but rather just a small window covering latest blocks +- `fanout_ttl`: adjusted to lower than `seen_ttl` +- `mcache_len`: a larger number of heartbeats can be retained since the gossip is much less noisy. +- `heartbeat_interval`: faster interval to reduce latency, bandwidth should still be reasonable since + there are far fewer messages to gossip about each interval than on L1 which uses an interval of 0.7 seconds. + +#### Topic configuration + +Topics have string identifiers and are communicated with messages and subscriptions. +`/optimism/chain_id/hardfork_version/Name` + +- `chain_id`: replace with decimal representation of chain ID +- `hardfork_version`: replace with decimal representation of hardfork +- `Name`: topic application-name + +Note that the topic encoding depends on the topic, unlike L1, +since there are less topics, and all are snappy-compressed. + +## Gossip Topics + +### `blocks` + +The primary topic of the L2, to distribute blocks to other nodes faster than proxying through L1 would. + +#### Block encoding + +TODO: encode execution payload (SSZ or RLP), with sequencer identifier and signature. + +TODO: signature type and verification (`secp256k1` like transactions, with some different signature domain) + +#### Block validation + +To ensure malicious peers get scored based on application behavior the validation signals +`ACCEPT` (valid), `IGNORE` (like inactivity) or `REJECT` (score penalties). + +In order of operation: + +- `[REJECT]` if the encoding or compression is not valid +- `[REJECT]` if the block timestamp is older than 20 seconds in the past + (graceful boundary for worst-case propagation and clock skew) +- `[REJECT]` if the block timestamp is more than 5 seconds into the future (graceful boundary for clock skew) +- `[REJECT]` if the signature by the sequencer is not valid +- `[REJECT]` if more than 5 blocks have been seen with the same block height +- `[IGNORE]` if a conflicting block was already seen on L1. + It may not be malicious due to racing between L1 confirmation and L2 propagation, but should be filtered out. + +The block is signed by the corresponding sequencer, to filter malicious messages. +The sequencer model is singular but may change to multiple sequencers in the future. +A default sequencer pubkey is distributed with rollup nodes and should be configurable. + +##### Block processing + +A node may apply the block to their local engine ahead of L1 availability, if it ensures that: + +- The application of the block is reversible, in case of a conflict with delayed L1 information +- The subsequent forkchoice-update ensures this block is recognized as "unsafe" + (see [`engine_forkchoiceUpdatedV1`](./exec-engine.md#engine_forkchoiceupdatedv1)) + +##### Block topic scoring parameters + +TODO: GossipSub per-topic scoring to fine-tune incentives for ideal propagation delay and bandwidth usage. + +---- + +[libp2p]: https://libp2p.io/ +[discv5]: https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md +[discv5-random-nodes]: https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.10.12/p2p/discover#UDPv5.RandomNodes +[eth2-p2p]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md +[libp2p-noise]: https://github.com/libp2p/specs/tree/master/noise +[multistream-select]: https://github.com/multiformats/multistream-select/ +[mplex]: https://github.com/libp2p/specs/tree/master/mplex +[yamux]: https://github.com/hashicorp/yamux/blob/master/spec.md +[gossipsub]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md +[signature-policy]: https://github.com/libp2p/specs/blob/master/pubsub/README.md#signature-policy-options +[snappy]: https://github.com/google/snappy +[l1-message-id]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#topics-and-messages +[gossip-parameters]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.0.md#parameters From bf721409fb4ef8d8c98323c1b3f3199a76a14d8a Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 14 Apr 2022 14:35:48 -0400 Subject: [PATCH 483/585] specs: Fix definition of output root --- specs/proposals.md | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/specs/proposals.md b/specs/proposals.md index f6da7585e575..b5d41adb7f12 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -67,28 +67,24 @@ In the initial version of the output commitment construction, the version is `by as: ```pseudocode -payload = state_root || withdrawal_storage_root || latest_block +payload = state_root || withdrawal_storage_root || latest_block_hash ``` -where the concatenated variables are: +where: + +1. The `latest_block_hash` (`bytes32`) is the block hash for the latest L2 block. -1. The `state_root` (`bytes32`) is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts, - also found in `latest_block.state_root`: this field is frequently used and thus elevated closer to the L2 output - root, as opposed to retrieving it from the pre-image of the block in `latest_block`, reducing the merkle proof depth - and thus the cost of usage. +1. The `state_root` (`bytes32`) is the Merkle-Patricia-Trie ([MPT][g-mpt]) root of all execution-layer accounts. + This value is frequently used and thus elevated closer to the L2 output root, which removes the need to prove its + inclusion in the pre-image of the `latest_block_hash`. This reduces the merkle proof depth and cost of accessing the + L2 state root on L1. -1. The `withdrawal_storage_root` (`bytes32`) elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of [L2 Withdrawal +1. The `withdrawal_storage_root` (`bytes32`) elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of the [L2 Withdrawal contract](./withdrawals.md#withdrawer-contract) storage. Instead of making an MPT proof for a withdrawal against the state root (proving first the storage root of the L2 withdrawal contract against the state root, then the withdrawal against that storage root), we can prove against the L2 withdrawal contract's storage root directly, thus reducing the verification cost of withdrawals on L1. -1. The `latest_block` (`bytes32`) is an L2 block, represented as the - [`ExecutionPayload`][executionpayload] SSZ type defined in L1. There may be multiple blocks per L2 output root, only - the latest is presented. - -[executionpayload]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayload - ## L2 Output Oracle Smart Contract L2 blocks are produced at a constant rate of `L2_BLOCK_TIME` (2 seconds). From 1f6ba1f1a36b0876ecb91fbdd762027db651c961 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Fri, 15 Apr 2022 10:33:07 -0700 Subject: [PATCH 484/585] solidity: fail if updated gas snapshot isn't included A new gas snapshot can be generated by running `forge snapshot` --- .github/workflows/solidity-ci.yml | 25 ++++++++++++++----------- packages/contracts/.gas-snapshot | 6 +++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/solidity-ci.yml b/.github/workflows/solidity-ci.yml index d89b82e90ec8..b771e73b5faf 100644 --- a/.github/workflows/solidity-ci.yml +++ b/.github/workflows/solidity-ci.yml @@ -3,9 +3,9 @@ name: Contracts lint, test and static analysis on: push: branches: - - 'main' - - 'staging' - - 'feat/*' + - "main" + - "staging" + - "feat/*" pull_request: workflow_dispatch: @@ -13,9 +13,9 @@ env: PYTEST_ADDOPTS: "--color=yes" defaults: - run: - shell: bash - working-directory: ./packages/contracts + run: + shell: bash + working-directory: ./packages/contracts jobs: yarn-test: @@ -28,8 +28,8 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: '14' - cache: 'yarn' + node-version: "14" + cache: "yarn" - run: yarn install - name: Lint @@ -54,6 +54,9 @@ jobs: - name: Test with Forge run: yarn test:forge + - name: Gas snapshot + run: forge snapshot && git diff --exit-code + slither: runs-on: ubuntu-latest name: Slither @@ -64,14 +67,14 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: '14' - cache: 'yarn' + node-version: "14" + cache: "yarn" - run: yarn install - name: Set up Python 3.8 uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: "3.8" - name: Install Slither run: pip3 install slither-analyzer diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 7fad498aa87b..25898faf9ebd 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -23,10 +23,10 @@ L2OutputOracleTest:test_getL2Output() (gas: 15073) L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9610) L2OutputOracleTest:test_nextTimestamp() (gas: 11943) L2OutputOracleTest_Constructor:test_constructor() (gas: 29122) -OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24175) +OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24183) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43988) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 203784) -WithdawerBurnTest:test_burn() (gas: 50289) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200059) +WithdawerBurnTest:test_burn() (gas: 50276) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71947) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72412) From 3154314ebe9a102686c93f18a88910e18a46f5a7 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sun, 17 Apr 2022 11:49:08 +0200 Subject: [PATCH 485/585] p2p setup: implement review suggestions, fix toc, fix lint --- opnode/flags/p2p_flags.go | 7 ++++--- opnode/p2p/config.go | 4 +--- specs/rollup-node-p2p.md | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/opnode/flags/p2p_flags.go b/opnode/flags/p2p_flags.go index ad5b865c330b..fbf8d5def7de 100644 --- a/opnode/flags/p2p_flags.go +++ b/opnode/flags/p2p_flags.go @@ -27,9 +27,10 @@ var ( Name: "p2p.priv.path", Usage: "Read the hex-encoded 32-byte private key for the peer ID from this txt file. Created if not already exists." + "Important to persist to keep the same network identity after restarting, maintaining the previous advertised identity.", - Required: false, - Value: "opnode_p2p_priv.txt", - EnvVar: p2pEnv("PRIV_PATH"), + Required: false, + Value: "opnode_p2p_priv.txt", + EnvVar: p2pEnv("PRIV_PATH"), + TakesFile: true, } P2PPrivRaw = cli.StringFlag{ // sometimes it may be ok to not persist the peer priv key as file, and instead pass it directly. diff --git a/opnode/p2p/config.go b/opnode/p2p/config.go index 84d8a131b2a0..01d0ecfe15a3 100644 --- a/opnode/p2p/config.go +++ b/opnode/p2p/config.go @@ -290,9 +290,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { conf.PeersLo = ctx.GlobalUint(flags.PeersLo.Name) conf.PeersHi = ctx.GlobalUint(flags.PeersHi.Name) conf.PeersGrace = ctx.GlobalDuration(flags.PeersGrace.Name) - - // TODO parse NAT option - + conf.NAT = ctx.GlobalBool(flags.NAT.Name) conf.UserAgent = ctx.GlobalString(flags.UserAgent.Name) conf.TimeoutNegotiation = ctx.GlobalDuration(flags.TimeoutNegotiation.Name) conf.TimeoutAccept = ctx.GlobalDuration(flags.TimeoutAccept.Name) diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index 5b92731a03ab..c1cace6925c5 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -8,7 +8,8 @@ This also enables faster historical sync to be bootstrapped by providing block h and only having to compare the L2 chain inputs to the L1 data as compared to processing everything one block at a time. The rollup node will *always* prioritize L1 and reorganize to match the canonical chain. -The L2 data retrieved via the P2P interface is strictly a speculative extension to improve the happy case performance. +The L2 data retrieved via the P2P interface is strictly a speculative extension, also known as the "unsafe" chain, +to improve the happy case performance. This also means that P2P behavior is a soft-rule: nodes keep each other in check with scoring and eventual banning of malicious peers by identity or IP. Any behavior on the P2P layer does not affect the rollup security, at worst nodes @@ -17,13 +18,46 @@ rely on higher-latency data from L1 to serve. In summary, the P2P stack looks like: - Discovery to find peers: [Discv5][discv5] -- Connections, peering, transport security, multi-plexing, gossip: [LibP2P][libp2p] +- Connections, peering, transport security, multiplexing, gossip: [LibP2P][libp2p] - Application-layer publishing and validation of gossiped messages like L2 blocks. This document only specifies the composition and configuration of these network libraries. These components have their own standards, implementations in Go/Rust/Java/Nim/JS/more, and are adopted by several other blockchains, most notably the [L1 consensus layer (Eth2)][eth2-p2p]. + + +**Table of Contents** + +- [P2P configuration](#p2p-configuration) + - [Identification](#identification) + - [Discv5](#discv5) + - [Structure](#structure) + - [LibP2P](#libp2p) + - [Transport](#transport) + - [Dialing](#dialing) + - [NAT](#nat) + - [Peer management](#peer-management) + - [Transport security](#transport-security) + - [Protocol negotiation](#protocol-negotiation) + - [Identify](#identify) + - [Ping](#ping) + - [Multiplexing](#multiplexing) + - [GossipSub](#gossipsub) + - [Content-based message identification](#content-based-message-identification) + - [Message compression and limits](#message-compression-and-limits) + - [Message ID computation](#message-id-computation) + - [Heartbeat and parameters](#heartbeat-and-parameters) + - [Topic configuration](#topic-configuration) +- [Gossip Topics](#gossip-topics) + - [`blocks`](#blocks) + - [Block encoding](#block-encoding) + - [Block validation](#block-validation) + - [Block processing](#block-processing) + - [Block topic scoring parameters](#block-topic-scoring-parameters) + + + ## P2P configuration ### Identification From 2d62a30b8f53b2cd6f3d41d7c80dba66325c55b4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sun, 17 Apr 2022 12:02:29 +0200 Subject: [PATCH 486/585] opnode/p2p: test with require instead of assert --- opnode/p2p/host_test.go | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/opnode/p2p/host_test.go b/opnode/p2p/host_test.go index 0442d4a5e657..c346e6a5ed91 100644 --- a/opnode/p2p/host_test.go +++ b/opnode/p2p/host_test.go @@ -18,14 +18,14 @@ import ( yamux "github.com/libp2p/go-libp2p-yamux" lconf "github.com/libp2p/go-libp2p/config" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestingConfig(t *testing.T) *Config { p, _, err := crypto.GenerateSecp256k1Key(rand.Reader) - assert.NoError(t, err, "failed to generate new p2p priv key") + require.NoError(t, err, "failed to generate new p2p priv key") mtpt, err := lconf.MuxerConstructor(yamux.DefaultTransport) - assert.NoError(t, err) + require.NoError(t, err) mux := lconf.MsMuxC{MuxC: mtpt, ID: "/yamux/1.0.0"} return &Config{ @@ -58,31 +58,31 @@ func TestP2PSimple(t *testing.T) { confA := TestingConfig(t) confB := TestingConfig(t) hostA, err := confA.Host() - assert.NoError(t, err, "failed to launch host A") + require.NoError(t, err, "failed to launch host A") defer hostA.Close() hostB, err := confB.Host() - assert.NoError(t, err, "failed to launch host B") + require.NoError(t, err, "failed to launch host B") defer hostB.Close() err = hostA.Connect(context.Background(), peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) - assert.NoError(t, err, "failed to connect to peer B from peer A") - assert.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) + require.NoError(t, err, "failed to connect to peer B from peer A") + require.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) } // Full setup, using negotiated transport security and muxes func TestP2PFull(t *testing.T) { pA, _, err := crypto.GenerateSecp256k1Key(rand.Reader) - assert.NoError(t, err, "failed to generate new p2p priv key") + require.NoError(t, err, "failed to generate new p2p priv key") pB, _, err := crypto.GenerateSecp256k1Key(rand.Reader) - assert.NoError(t, err, "failed to generate new p2p priv key") + require.NoError(t, err, "failed to generate new p2p priv key") mplexC, err := mplexC() - assert.NoError(t, err) + require.NoError(t, err) yamuxC, err := yamuxC() - assert.NoError(t, err) + require.NoError(t, err) noiseC, err := noiseC() - assert.NoError(t, err) + require.NoError(t, err) tlsC, err := tlsC() - assert.NoError(t, err) + require.NoError(t, err) confA := Config{ Priv: (*ecdsa.PrivateKey)((pA).(*crypto.Secp256k1PrivateKey)), @@ -113,24 +113,24 @@ func TestP2PFull(t *testing.T) { // TODO: maybe swap the order of sec/mux preferences, to test that negotiation works hostA, err := confA.Host() - assert.NoError(t, err) + require.NoError(t, err) defer hostA.Close() hostB, err := confB.Host() - assert.NoError(t, err) + require.NoError(t, err) defer hostB.Close() err = hostA.Connect(context.Background(), peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) - assert.NoError(t, err, "failed to connect to peer B from peer A") - assert.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) + require.NoError(t, err, "failed to connect to peer B from peer A") + require.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) } // Most tests should use mocknets instead of using the actual local host network func TestP2PMocknet(t *testing.T) { mnet, err := mocknet.FullMeshConnected(3) - assert.NoError(t, err, "failed to setup mocknet") + require.NoError(t, err, "failed to setup mocknet") defer mnet.Close() hosts := mnet.Hosts() hostA, hostB, hostC := hosts[0], hosts[1], hosts[2] - assert.Equal(t, hostA.Network().Connectedness(hostB.ID()), network.Connected) - assert.Equal(t, hostA.Network().Connectedness(hostC.ID()), network.Connected) - assert.Equal(t, hostB.Network().Connectedness(hostC.ID()), network.Connected) + require.Equal(t, hostA.Network().Connectedness(hostB.ID()), network.Connected) + require.Equal(t, hostA.Network().Connectedness(hostC.ID()), network.Connected) + require.Equal(t, hostB.Network().Connectedness(hostC.ID()), network.Connected) } From 4974d347fa87aebcaf4476d9cc0e344732b4e5e2 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 19 Apr 2022 03:43:17 -0400 Subject: [PATCH 487/585] contracts: Fix reentrancy attack in WithdrawalsRelay (#378) --- packages/contracts/.gas-snapshot | 2 +- packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 25898faf9ebd..fcec3a71e595 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -26,7 +26,7 @@ L2OutputOracleTest_Constructor:test_constructor() (gas: 29122) OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24183) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43988) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200059) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200133) WithdawerBurnTest:test_burn() (gas: 50276) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71947) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72412) diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol index 0b36d92d3d55..bd9a3cd923db 100644 --- a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol +++ b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol @@ -137,6 +137,7 @@ abstract contract WithdrawalsRelay { if (finalizedWithdrawals[withdrawalHash] == true) { revert WithdrawalAlreadyFinalized(); } + finalizedWithdrawals[withdrawalHash] = true; l2Sender = _sender; // Make the call. @@ -146,7 +147,6 @@ abstract contract WithdrawalsRelay { // All withdrawals are immediately finalized. If the ability to replay a transaction is // required, that support can be provided in external contracts. - finalizedWithdrawals[withdrawalHash] = true; emit WithdrawalFinalized(withdrawalHash); } } From 84fc6ed76e6debeedba8ada887d25c6fd3f16afc Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 19 Apr 2022 04:49:38 -0400 Subject: [PATCH 488/585] contracts: Output oracle improvements (#370) * contracts: Use correct uppercase for immutables * itest: shorten submission interval for faster devnet tests * contracts: Ensure submission interval is multiple of block time * itest: Simplify withdrawals spec * itest: Increase withdrawal finalization timeout * itest: Bump withdrawal timeout to +5 minutes * Bump timeout * Bump again * Add gas snap Co-authored-by: Matthew Slipper --- packages/contracts/.gas-snapshot | 28 ++++----- .../contracts/contracts/L1/L2OutputOracle.sol | 33 ++++++---- .../L1/abstracts/WithdrawalsRelay.sol | 2 +- .../contracts/test/L2OutputOracle.t.sol | 8 +-- .../deploy/000-L2OutputOracle.deploy.ts | 10 +-- .../test/000_withdrawals.spec.ts | 63 +++++++++++-------- 6 files changed, 80 insertions(+), 64 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index fcec3a71e595..f120c32fde52 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -11,22 +11,22 @@ L1BLockTest:test_basefee() (gas: 7509) L1BLockTest:test_hash() (gas: 7508) L1BLockTest:test_number() (gas: 7509) L1BLockTest:test_timestamp() (gas: 7463) -L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20947) -L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19066) -L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 20979) -L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18307) -L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21227) -L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13090) -L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49528) -L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14893) -L2OutputOracleTest:test_getL2Output() (gas: 15073) -L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9610) -L2OutputOracleTest:test_nextTimestamp() (gas: 11943) -L2OutputOracleTest_Constructor:test_constructor() (gas: 29122) +L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20924) +L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19043) +L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 20956) +L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18284) +L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21204) +L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13112) +L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49505) +L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14959) +L2OutputOracleTest:test_getL2Output() (gas: 15027) +L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9632) +L2OutputOracleTest:test_nextTimestamp() (gas: 11965) +L2OutputOracleTest_Constructor:test_constructor() (gas: 29123) OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24183) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43988) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43965) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200133) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200110) WithdawerBurnTest:test_burn() (gas: 50276) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71947) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72412) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 63a2cec191b5..63314a6ce59b 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -23,16 +23,16 @@ contract L2OutputOracle is Ownable { **********************/ /// @notice The interval in seconds at which checkpoints must be submitted. - uint256 public immutable submissionInterval; + uint256 public immutable SUBMISSION_INTERVAL; /// @notice The time between blocks on L2. - uint256 public immutable l2BlockTime; + uint256 public immutable L2_BLOCK_TIME; /// @notice The number of blocks in the chain before the first block in this contract. - uint256 public immutable historicalTotalBlocks; + uint256 public immutable HISTORICAL_TOTAL_BLOCKS; /// @notice The timestamp of the first L2 block recorded in this contract. - uint256 public immutable startingBlockTimestamp; + uint256 public immutable STARTING_BLOCK_TIMESTAMP; /// @notice The timestamp of the most recent L2 block recorded in this contract. uint256 public latestBlockTimestamp; @@ -62,12 +62,17 @@ contract L2OutputOracle is Ownable { uint256 _startingBlockTimestamp, address sequencer ) { - submissionInterval = _submissionInterval; - l2BlockTime = _l2BlockTime; + require( + _submissionInterval % _l2BlockTime == 0, + "Submission Interval must be a multiple of L2 Block Time" + ); + + SUBMISSION_INTERVAL = _submissionInterval; + L2_BLOCK_TIME = _l2BlockTime; l2Outputs[_startingBlockTimestamp] = _genesisL2Output; // solhint-disable not-rely-on-time - historicalTotalBlocks = _historicalTotalBlocks; + HISTORICAL_TOTAL_BLOCKS = _historicalTotalBlocks; latestBlockTimestamp = _startingBlockTimestamp; // solhint-disable not-rely-on-time - startingBlockTimestamp = _startingBlockTimestamp; // solhint-disable not-rely-on-time + STARTING_BLOCK_TIMESTAMP = _startingBlockTimestamp; // solhint-disable not-rely-on-time _transferOwnership(sequencer); } @@ -121,7 +126,7 @@ contract L2OutputOracle is Ownable { * @notice Computes the timestamp of the next L2 block that needs to be checkpointed. */ function nextTimestamp() public view returns (uint256) { - return latestBlockTimestamp + submissionInterval; + return latestBlockTimestamp + SUBMISSION_INTERVAL; } /** @@ -139,14 +144,16 @@ contract L2OutputOracle is Ownable { */ function computeL2BlockNumber(uint256 _l2timestamp) external view returns (uint256) { require( - _l2timestamp >= startingBlockTimestamp, + _l2timestamp >= STARTING_BLOCK_TIMESTAMP, "Timestamp prior to startingBlockTimestamp" ); - // For the first block recorded (ie. _l2timestamp = startingBlockTimestamp), the - // L2BlockNumber should be historicalTotalBlocks + 1. + // For the first block recorded (ie. _l2timestamp = STARTING_BLOCK_TIMESTAMP), the + // L2BlockNumber should be HISTORICAL_TOTAL_BLOCKS + 1. unchecked { return - historicalTotalBlocks + 1 + ((_l2timestamp - startingBlockTimestamp) / l2BlockTime); + HISTORICAL_TOTAL_BLOCKS + + 1 + + ((_l2timestamp - STARTING_BLOCK_TIMESTAMP) / L2_BLOCK_TIME); } } } diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol index bd9a3cd923db..047ae010ef06 100644 --- a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol +++ b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol @@ -98,7 +98,7 @@ abstract contract WithdrawalsRelay { WithdrawalVerifier.OutputRootProof calldata _outputRootProof, bytes calldata _withdrawalProof ) external { - // Check that the timestamp is 7 days old. + // Check that the timestamp is sufficiently finalized. unchecked { if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { revert NotYetFinal(); diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 2fffc0481963..4cf987532aa1 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -47,11 +47,11 @@ contract L2OutputOracle_Initializer is DSTest { contract L2OutputOracleTest_Constructor is L2OutputOracle_Initializer { function test_constructor() external { assertEq(oracle.owner(), sequencer); - assertEq(oracle.submissionInterval(), submissionInterval); - assertEq(oracle.l2BlockTime(), l2BlockTime); - assertEq(oracle.historicalTotalBlocks(), historicalTotalBlocks); + assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval); + assertEq(oracle.L2_BLOCK_TIME(), l2BlockTime); + assertEq(oracle.HISTORICAL_TOTAL_BLOCKS(), historicalTotalBlocks); assertEq(oracle.latestBlockTimestamp(), startingBlockTimestamp); - assertEq(oracle.startingBlockTimestamp(), startingBlockTimestamp); + assertEq(oracle.STARTING_BLOCK_TIMESTAMP(), startingBlockTimestamp); assertEq(oracle.getL2Output(startingBlockTimestamp), genesisL2Output); } } diff --git a/packages/contracts/deploy/000-L2OutputOracle.deploy.ts b/packages/contracts/deploy/000-L2OutputOracle.deploy.ts index 3cbae9f12cf0..2f88bed91c28 100644 --- a/packages/contracts/deploy/000-L2OutputOracle.deploy.ts +++ b/packages/contracts/deploy/000-L2OutputOracle.deploy.ts @@ -18,12 +18,12 @@ const deployFn: DeployFunction = async (hre) => { await deploy('L2OutputOracle', { from: deployer, args: [ - 15, - 2, - `0x${'00'.repeat(32)}`, - 0, + 6, // submission interval + 2, // l2 block time + `0x${'00'.repeat(32)}`, // genesis output + 0, // historical blocks process.env.L2OO_STARTING_BLOCK_TIMESTAMP, - '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', + '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // sequencer ], log: true, waitConfirmations: 1, diff --git a/packages/integration-tests/test/000_withdrawals.spec.ts b/packages/integration-tests/test/000_withdrawals.spec.ts index eac36382b3f6..8aa193f932df 100644 --- a/packages/integration-tests/test/000_withdrawals.spec.ts +++ b/packages/integration-tests/test/000_withdrawals.spec.ts @@ -121,38 +121,47 @@ describe('Withdrawals', () => { l2OOracleArtifact.abi, ).connect(recipient) - const nextTimestamp = (await oracle.nextTimestamp()).toNumber() - const difference = burnBlock.timestamp - nextTimestamp - this.timeout(difference * 1000 + 60000) - - let targetOutputTimestamp: number - await awaitCondition( - async () => { - const nextTimestamp = (await oracle.nextTimestamp()).toNumber() - const difference = burnBlock.timestamp - nextTimestamp - logger.info('Waiting for timestamp', { - burnTS: burnBlock.timestamp, - nextTS: nextTimestamp, - difference: difference, - }) - // update this number on each iteration. When the condition is met, this will be the - // timestamp we want to prove against. - targetOutputTimestamp = nextTimestamp - return nextTimestamp > burnBlock.timestamp - }, - 2000, - 100, - ) + // Calculate the target output timestamp to make the withdrawal proof against. ie. the first + // output with a timestamp greater than the burn block timestamp + const submissionInterval = (await oracle.SUBMISSION_INTERVAL()).toNumber() + const startingBlockTimestamp = (await oracle.STARTING_BLOCK_TIMESTAMP()).toNumber() + let nextTimestamp = (await oracle.nextTimestamp()).toNumber() + let targetOutputTimestamp + if (burnBlock.timestamp < nextTimestamp) { + // Just use the next timestamp + targetOutputTimestamp = nextTimestamp + } else { + // Calculate the first timestamp greater than the burnBlock which will be appended. + targetOutputTimestamp = + Math.ceil( + (burnBlock.timestamp - startingBlockTimestamp) + / submissionInterval + ) + * submissionInterval + + startingBlockTimestamp + } + + // Set the timeout based on the diff between latest output and target output timestamp + let latestBlockTimestamp = (await oracle.latestBlockTimestamp()).toNumber() + let difference = targetOutputTimestamp - latestBlockTimestamp + this.timeout(difference * 5000) let output: string await awaitCondition(async () => { output = await oracle.getL2Output(targetOutputTimestamp) - logger.info('Waiting for output submission', { - targetTimestamp: targetOutputTimestamp, - output, - }) + latestBlockTimestamp = (await oracle.latestBlockTimestamp()).toNumber() + if(targetOutputTimestamp - latestBlockTimestamp < difference){ + // Only log when a new output has been appended + difference = targetOutputTimestamp - latestBlockTimestamp + logger.info('Waiting for output submission', { + targetTimestamp: targetOutputTimestamp, + latestOracleTS: latestBlockTimestamp, + difference, + output, + }) + } return output != constants.HashZero - }, 2000, 100) + }, 2000, 240) // suppress compilation errors since Typescript cannot detect // that awaitCondition above will throw if it times out. From ebb51833994e4e4f7bcadc49f602474b0b31165b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 19 Apr 2022 06:07:52 -0400 Subject: [PATCH 489/585] Clean up withdrawals itest (#372) * contracts: Use correct uppercase for immutables * itest: shorten submission interval for faster devnet tests * contracts: Ensure submission interval is multiple of block time * itest: Simplify withdrawals spec * itest: Increase withdrawal finalization timeout * itest: Bump withdrawal timeout to +5 minutes * itest: Extract logic into getTargetOutput * Update 000_withdrawals.spec.ts Co-authored-by: Matthew Slipper --- .../test/000_withdrawals.spec.ts | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/packages/integration-tests/test/000_withdrawals.spec.ts b/packages/integration-tests/test/000_withdrawals.spec.ts index 8aa193f932df..27572483bdf9 100644 --- a/packages/integration-tests/test/000_withdrawals.spec.ts +++ b/packages/integration-tests/test/000_withdrawals.spec.ts @@ -15,8 +15,36 @@ import winston from 'winston' const withdrawerArtifact = require('../../contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json') const l2OOracleArtifact = require('../../contracts/artifacts/contracts/L1/L2OutputOracle.sol/L2OutputOracle.json') -const counterArtifact = require('../artifacts/Counter.sol/Counter.json') -const multiDepositorArtifact = require('../artifacts/MultiDepositor.sol/MultiDepositor.json') + + +/** + * Calculates the target output timestamp to make the withdrawal proof against. ie. the first + * output with a timestamp greater than the burn block timestamp. + * @param {Contract} oracle Address of the L2 Output Oracle. + * @param {number} withdrawalTimestamp L2 timestamp of the block the withdrawal was made in. + */ +const getTargetOutput = async (oracle: Contract, withdrawalTimestamp: number) => { + const submissionInterval = (await oracle.SUBMISSION_INTERVAL()).toNumber() + const startingBlockTimestamp = (await oracle.STARTING_BLOCK_TIMESTAMP()).toNumber() + let nextTimestamp = (await oracle.nextTimestamp()).toNumber() + let targetOutputTimestamp + if (withdrawalTimestamp < nextTimestamp) { + // Just use the next timestamp + targetOutputTimestamp = nextTimestamp + } else { + // Calculate the first timestamp greater than the burnBlock which will be appended. + targetOutputTimestamp = + Math.ceil( + (withdrawalTimestamp - startingBlockTimestamp) + / submissionInterval + ) + * submissionInterval + + startingBlockTimestamp + } + + return targetOutputTimestamp +} + describe('Withdrawals', () => { let logger: winston.Logger @@ -121,27 +149,9 @@ describe('Withdrawals', () => { l2OOracleArtifact.abi, ).connect(recipient) - // Calculate the target output timestamp to make the withdrawal proof against. ie. the first - // output with a timestamp greater than the burn block timestamp - const submissionInterval = (await oracle.SUBMISSION_INTERVAL()).toNumber() - const startingBlockTimestamp = (await oracle.STARTING_BLOCK_TIMESTAMP()).toNumber() - let nextTimestamp = (await oracle.nextTimestamp()).toNumber() - let targetOutputTimestamp - if (burnBlock.timestamp < nextTimestamp) { - // Just use the next timestamp - targetOutputTimestamp = nextTimestamp - } else { - // Calculate the first timestamp greater than the burnBlock which will be appended. - targetOutputTimestamp = - Math.ceil( - (burnBlock.timestamp - startingBlockTimestamp) - / submissionInterval - ) - * submissionInterval - + startingBlockTimestamp - } - - // Set the timeout based on the diff between latest output and target output timestamp + const targetOutputTimestamp = await getTargetOutput(oracle, burnBlock.timestamp) + + // Set the timeout based on the diff between latest output and target output timestamp. let latestBlockTimestamp = (await oracle.latestBlockTimestamp()).toNumber() let difference = targetOutputTimestamp - latestBlockTimestamp this.timeout(difference * 5000) @@ -165,7 +175,6 @@ describe('Withdrawals', () => { // suppress compilation errors since Typescript cannot detect // that awaitCondition above will throw if it times out. - targetOutputTimestamp = targetOutputTimestamp! output = output! const blocksSinceBurn = Math.floor((targetOutputTimestamp - burnBlock.timestamp) / 2) From bc50f1b66ac3ba0ce6783bcb24e7019d836d8bda Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Sat, 16 Apr 2022 15:41:49 +0200 Subject: [PATCH 490/585] fix dead anchor link --- specs/deposits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index f067ee0d9367..b0fa19f26ac7 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -203,7 +203,7 @@ The contract has the following solidity interface, and can be interacted with ac #### L1 Attributes Predeployed Contract: Reference Implementation -[l1-attr-ref-implem]: #l1-attributes-predeployed-contract--reference-implementation +[l1-attr-ref-implem]: #l1-attributes-predeployed-contract-reference-implementation A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. From 7dfafff080ba8f8f2da14fcfb4a5bfd4f029d74e Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Sat, 16 Apr 2022 15:46:46 +0200 Subject: [PATCH 491/585] higher difficulty rather than number --- opnode/rollup/sync/start.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index d0d01e16f36a..7391c59070fc 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -2,9 +2,9 @@ // // The Ethereum chain is a DAG of blocks with the root block being the genesis block. At any given // time, the head (or tip) of the chain can change if an offshoot/branch of the chain has a higher -// number. This is known as a re-organization of the canonical chain. Each block points to a parent -// block and the node is responsible for deciding which block is the head and thus the mapping from -// block number to canonical block. +// total difficulty. This is known as a re-organization of the canonical chain. Each block points to +// a parent block and the node is responsible for deciding which block is the head and thus the +// mapping from block number to canonical block. // // The Optimism (L2) chain has similar properties, but also retains references to the Ethereum (L1) // chain. Each L2 block retains a reference to an L1 block (its "L1 origin", i.e. L1 block From 737dcac777a81d1f8c208376b2f7add7567fbaf0 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Sat, 16 Apr 2022 18:05:49 +0200 Subject: [PATCH 492/585] 'L1 attributes block' is not a thing + add link --- specs/rollup-node.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 33be6323a702..695bf43fb39c 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -391,14 +391,16 @@ meaning the head of the L1 chain changes to a block that is not the child of the descendant of an ancestor of the previous head. In that case, the rollup driver must first search for the common L1 ancestor, and can re-derive the L2 chain from that L1 block and onward. -The rollup node maintains two heads of the L2 Chain: the unsafe head (often called head) and the safe head. -Each L2 block has an L1 Attributes block that it references in the L1 Info deposit transaction. -The unsafe head is the head of the L2 chain. It's L1 Attributes should be canonical or potentially extending the -canonical chain (if the rollup node has not yet seen the L1 block that it is based upon). -The safe head is the the last L2 block of the last epoch whose sequencing window is complete -(i.e. the epoch with number `L1Head.number` - `SEQUENCING_WINDOW_SIZE`). - -Steps during a reorg +The rollup node maintains two heads of the L2 Chain: the unsafe head (often called head) and the safe head. Each L2 +block has an L1 origin block (corresponding to its epoch) that it references in the [L1 attributes deposited +transaction][l1-attr-deposit]. The unsafe head is the head of the L2 chain. Its L1 origin block should be canonical or +potentially extending the canonical chain (if the rollup node has not yet seen the L1 block that it is based upon). The +safe head is the the last L2 block of the last epoch whose sequencing window is complete (i.e. the epoch with number +`L1Head.number` - `SEQUENCING_WINDOW_SIZE`). + +[l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction + +Steps during a reorg: 1. Set "unsafe head" to equal the l2 head we retrieved, just as default 2. Set "latest block" to equal the l2 head we retrieved, also just as default From 1f351a8ced67813a20b554e52ae117a35bd79e4c Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 19 Apr 2022 12:49:25 +0200 Subject: [PATCH 493/585] try to align sentences with lines --- specs/rollup-node.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 695bf43fb39c..258d9f477746 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -391,12 +391,13 @@ meaning the head of the L1 chain changes to a block that is not the child of the descendant of an ancestor of the previous head. In that case, the rollup driver must first search for the common L1 ancestor, and can re-derive the L2 chain from that L1 block and onward. -The rollup node maintains two heads of the L2 Chain: the unsafe head (often called head) and the safe head. Each L2 -block has an L1 origin block (corresponding to its epoch) that it references in the [L1 attributes deposited -transaction][l1-attr-deposit]. The unsafe head is the head of the L2 chain. Its L1 origin block should be canonical or -potentially extending the canonical chain (if the rollup node has not yet seen the L1 block that it is based upon). The -safe head is the the last L2 block of the last epoch whose sequencing window is complete (i.e. the epoch with number -`L1Head.number` - `SEQUENCING_WINDOW_SIZE`). +The rollup node maintains two heads of the L2 Chain: the unsafe head (often called head) and the safe head. +Each L2 block has an L1 origin block (corresponding to its epoch) that it references in the +[L1 attributes deposited transaction][l1-attr-deposit]. The unsafe head is the head of the L2 chain. +Its L1 origin block should be canonical or potentially extending the canonical chain +(if the rollup node has not yet seen the L1 block that it is based upon). +The safe head is the the last L2 block of the last epoch whose sequencing window is complete +(i.e. the epoch with number `L1Head.number` - `SEQUENCING_WINDOW_SIZE`). [l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction From 23a337b162ed02706aefc54724c48e686b8d09c1 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 19 Apr 2022 05:40:57 -0600 Subject: [PATCH 494/585] ci: Add automated docker builds for opnode and l2 output submitter (#369) --- .circleci/config.yml | 57 ++++++++++++++++++++++++++++++++++++++++ ops/Dockerfile.l2os | 6 +---- ops/Dockerfile.opnode | 3 +-- ops/docker-compose.yml | 10 +++++++ ops/l2os-entrypoint.sh | 14 ---------- ops/opnode-entrypoint.sh | 12 --------- 6 files changed, 69 insertions(+), 33 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 ops/l2os-entrypoint.sh delete mode 100644 ops/opnode-entrypoint.sh diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000000..4f4e4d776988 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,57 @@ +version: 2.1 + + +jobs: + build-dockerfile: + docker: + - image: cimg/base:2022.04 + parameters: + image-name: + description: Image name + type: string + image-tag: + description: Image tag + type: string + target: + description: Dockerfile target + type: string + default: "" + dockerfile: + description: Dockerfile to use + type: string + steps: + - checkout + - setup_remote_docker: + version: 19.03.13 + - run: + name: Build + command: | + echo "$DOCKER_PASS" | docker login -u "$DOCKER_USERNAME" --password-stdin + docker build -t "ethereumoptimism/<>:<>" -f <> <<#parameters.target>>--target <><> . + docker push "ethereumoptimism/<>:<>" + +workflows: + main: + jobs: + - build-dockerfile: + context: + - optimism + filters: + branches: + only: + - main + image-name: opnode + image-tag: develop + dockerfile: ops/Dockerfile.opnode + name: Build opnode + - build-dockerfile: + context: + - optimism + filters: + branches: + only: + - main + image-name: l2os + image-tag: develop + dockerfile: ops/Dockerfile.l2os + name: Build L2 output submitter diff --git a/ops/Dockerfile.l2os b/ops/Dockerfile.l2os index 7626cc48416b..4cadc3577864 100644 --- a/ops/Dockerfile.l2os +++ b/ops/Dockerfile.l2os @@ -7,7 +7,6 @@ COPY go.mod /app/go.mod COPY go.sum /app/go.sum WORKDIR /app -COPY ./ops/l2os-entrypoint.sh /app/l2os-entrypoint.sh COPY ./l2os /app/l2os COPY ./opnode /app/opnode @@ -15,9 +14,6 @@ RUN make l2os FROM alpine:3.15 -RUN apk add --no-cache curl jq - COPY --from=builder /app/bin/l2os /usr/local/bin -COPY --from=builder /app/l2os-entrypoint.sh /l2os-entrypoint.sh -ENTRYPOINT ["/bin/sh", "/l2os-entrypoint.sh"] +CMD ["l2os"] diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode index 832a960c883f..ba07689d1d04 100644 --- a/ops/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -13,6 +13,5 @@ RUN make opnode FROM alpine:3.15 COPY --from=builder /app/bin/op /usr/local/bin -COPY ./ops/opnode-entrypoint.sh /opnode-entrypoint.sh -ENTRYPOINT ["/bin/sh", "/opnode-entrypoint.sh"] +CMD ["op"] diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 7d313babbe95..6765a6af6ea7 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -36,6 +36,16 @@ services: build: context: ../ dockerfile: ./ops/Dockerfile.opnode + command: + - op + - --l1=ws://l1:8546 + - --l2=ws://l2:8546 + - --sequencing.enabled + - --rollup.config=/rollup.json + - --batchsubmitter.key=/config/bss-key.txt + - --l2.eth=http://l2:8545 + - --rpc.addr=0.0.0.0 + - --rpc.port=8545 ports: - "7545:8545" volumes: diff --git a/ops/l2os-entrypoint.sh b/ops/l2os-entrypoint.sh deleted file mode 100644 index 1990c0bec182..000000000000 --- a/ops/l2os-entrypoint.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -set -exu - -curl \ - --fail \ - --retry 10 \ - --retry-delay 2 \ - --retry-connrefused \ - -X POST \ - -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ - http://l1:8545 - -exec l2os diff --git a/ops/opnode-entrypoint.sh b/ops/opnode-entrypoint.sh deleted file mode 100644 index a0ce96ebe7d2..000000000000 --- a/ops/opnode-entrypoint.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -set -exu - -exec op \ - --l1 ws://l1:8546 \ - --l2 ws://l2:8546 \ - --sequencing.enabled \ - --rollup.config /rollup.json \ - --batchsubmitter.key /config/bss-key.txt \ - --l2.eth http://l2:8545 \ - --rpc.addr 0.0.0.0 \ - --rpc.port 8545 From d13dab5c1accab03253294d818c09a5f7a1f8366 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 18 Apr 2022 10:30:26 -0400 Subject: [PATCH 495/585] contracts: Add deleteL2Output function --- packages/contracts/.gas-snapshot | 31 +++++++------ .../contracts/contracts/L1/L2OutputOracle.sol | 17 +++++++ .../contracts/test/L2OutputOracle.t.sol | 46 +++++++++++++++++++ 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index f120c32fde52..101ded5fa8fe 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -11,22 +11,25 @@ L1BLockTest:test_basefee() (gas: 7509) L1BLockTest:test_hash() (gas: 7508) L1BLockTest:test_number() (gas: 7509) L1BLockTest:test_timestamp() (gas: 7463) -L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20924) -L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19043) -L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 20956) -L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18284) -L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21204) -L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13112) -L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49505) -L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14959) -L2OutputOracleTest:test_getL2Output() (gas: 15027) -L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9632) -L2OutputOracleTest:test_nextTimestamp() (gas: 11965) -L2OutputOracleTest_Constructor:test_constructor() (gas: 29123) +L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20880) +L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19077) +L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 21023) +L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18306) +L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21226) +L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13134) +L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18381) +L2OutputOracleTest:testCannot_deleteL2Output_ifWrongOutput() (gas: 25541) +L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49539) +L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14981) +L2OutputOracleTest:test_deleteL2Output() (gas: 32908) +L2OutputOracleTest:test_getL2Output() (gas: 15093) +L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9654) +L2OutputOracleTest:test_nextTimestamp() (gas: 12009) +L2OutputOracleTest_Constructor:test_constructor() (gas: 29100) OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24183) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43965) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43987) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200110) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200132) WithdawerBurnTest:test_burn() (gas: 50276) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71947) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72412) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 63314a6ce59b..8121d0e51284 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -18,6 +18,9 @@ contract L2OutputOracle is Ownable { /// @notice Emitted when an output is appended. event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + /// @notice Emitted when an output is deleted. + event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + /********************** * Contract Variables * **********************/ @@ -122,6 +125,20 @@ contract L2OutputOracle is Ownable { emit l2OutputAppended(_l2Output, _l2timestamp); } + /** + * @notice Deletes the most recent output. + * @param _l2Output The value of the most recent output. Used to prevent erroneously deleting + * the wrong root + */ + function deleteL2Output(bytes32 _l2Output) external onlyOwner { + bytes32 outputToDelete = l2Outputs[latestBlockTimestamp]; + require(_l2Output == outputToDelete, "Can only delete the most recent output."); + emit l2OutputDeleted(outputToDelete, latestBlockTimestamp); + + delete l2Outputs[latestBlockTimestamp]; + latestBlockTimestamp = latestBlockTimestamp - SUBMISSION_INTERVAL; + } + /** * @notice Computes the timestamp of the next L2 block that needs to be checkpointed. */ diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 4cf987532aa1..435385ec758e 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -226,4 +226,50 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // This will fail when foundry no longer returns zerod block hashes oracle.appendL2Output(nonZeroHash, nextTimestamp, l1BlockHash, l1BlockNumber - 1); } + + /**************** + * Delete Tests * + ****************/ + + event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + function test_deleteL2Output() external { + uint256 latestBlockTimestamp = oracle.latestBlockTimestamp(); + bytes32 outputToDelete = oracle.getL2Output(latestBlockTimestamp); + bytes32 newLatestOutput = oracle.getL2Output(latestBlockTimestamp - submissionInterval); + + vm.prank(sequencer); + vm.expectEmit(true, true, false, false); + emit l2OutputDeleted(outputToDelete, latestBlockTimestamp); + oracle.deleteL2Output(outputToDelete); + + // validate latestBlockTimestamp has been reduced + uint256 latestBlockTimestampAfter = oracle.latestBlockTimestamp(); + assertEq( + latestBlockTimestamp - submissionInterval, + latestBlockTimestampAfter + ); + + // validate that the new latest output is as expected. + assertEq( + newLatestOutput, + oracle.getL2Output(latestBlockTimestampAfter) + ); + } + + function testCannot_deleteL2Output_ifNotSequencer() external { + uint256 latestBlockTimestamp = oracle.latestBlockTimestamp(); + bytes32 outputToDelete = oracle.getL2Output(latestBlockTimestamp); + + vm.expectRevert("Ownable: caller is not the owner"); + oracle.deleteL2Output(outputToDelete); + } + + function testCannot_deleteL2Output_ifWrongOutput() external { + uint256 previousBlockTimestamp = oracle.latestBlockTimestamp() - submissionInterval; + bytes32 outputToDelete = oracle.getL2Output(previousBlockTimestamp); + + vm.prank(sequencer); + vm.expectRevert("Can only delete the most recent output."); + oracle.deleteL2Output(outputToDelete); + } } From 5769ea8ba42fafe6706f630c6163226bf2b43cb9 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 19 Apr 2022 23:04:46 -0400 Subject: [PATCH 496/585] specs: Add deleteL2Output --- specs/proposals.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/specs/proposals.md b/specs/proposals.md index b5d41adb7f12..5861f0afe95a 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -44,6 +44,9 @@ If there is no newly finalized output, the service continues querying until it r output, and the appropriate timestamp, to the [L2 Output Root](#l2-output-root-smart-contract) contract's `appendL2Output()` function. The timestamp MUST be the next multiple of the `SUBMISSION_INTERVAL` value. +The proposer may also delete the most recent output root by calling the `deleteL2Output()` function. +The function can be called repeatedly if it is necessary to roll back the state further. + > **Note regarding future work:** In the initial version of the system, the proposer will be the same entity as the > sequencer, which is a trusted role. In the future proposers will need to submit a bond in order to post L2 output > roots, and some or all of this bond may be taken in the event of a faulty proposal. @@ -111,6 +114,12 @@ function appendL2Output( uint256 _l1Blocknumber ) +/** + * @notice Deletes the most recent output. + * @param _l2Output The value of the most recent output. Used to prevent erroneously deleting + * the wrong root + */ +function deleteL2Output(bytes32 _l2Output) external /** * Computes the timestamp of the next L2 block that needs to be checkpointed. From 93ac3187795abd7bdadf10e59d71c813d5dcc239 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 20 Apr 2022 03:48:32 -0600 Subject: [PATCH 497/585] ci: Update Docker version in CircleCi (#381) We ran into this on the monorepo too. Alpine 3.14 removes the `faccessat2` syscall. This caused "operation not permitted" errors while building. Upgrading Circle's Docker version fixes this. See https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0#faccessat2 for more information. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4f4e4d776988..9a7fe3d476b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,7 +22,7 @@ jobs: steps: - checkout - setup_remote_docker: - version: 19.03.13 + version: 20.10.12 - run: name: Build command: | From 64e1796cda42d13c14cafb2eb59a0cfe83aff196 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Wed, 20 Apr 2022 03:01:45 -0700 Subject: [PATCH 498/585] contracts: reuse code (#380) * contracts: reuse the library to compute withdrawal hash The `WithdrawalVerifier` has a method to compute the withdrawal hash as part of a library. Use this library in both the L1 and L2 contracts so that code can be reused. * contracts: gas snapshot --- packages/contracts/.gas-snapshot | 4 ++-- .../contracts/L1/abstracts/WithdrawalsRelay.sol | 2 +- packages/contracts/contracts/L2/Withdrawer.sol | 10 ++++++++-- .../{L1 => }/libraries/Lib_WithdrawalVerifier.sol | 2 +- .../contracts/contracts/test/WithdrawalsRelay.t.sol | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) rename packages/contracts/contracts/{L1 => }/libraries/Lib_WithdrawalVerifier.sol (96%) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index f120c32fde52..c7ed371683d0 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -28,5 +28,5 @@ WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProo WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200110) WithdawerBurnTest:test_burn() (gas: 50276) -WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71947) -WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72412) +WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 72023) +WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72488) diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol index 047ae010ef06..179a52e2c031 100644 --- a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol +++ b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.10; import { L2OutputOracle } from "../L2OutputOracle.sol"; /* Library Imports */ -import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; +import { WithdrawalVerifier } from "../../libraries/Lib_WithdrawalVerifier.sol"; /** * @title WithdrawalsRelay diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index dc01de87b18e..803088320ae0 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.10; import { AddressAliasHelper } from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; /* Interaction imports */ import { Burner } from "./Burner.sol"; @@ -70,8 +71,13 @@ contract Withdrawer { if (msg.sender != tx.origin) { from = AddressAliasHelper.undoL1ToL2Alias(msg.sender); } - bytes32 withdrawalHash = keccak256( - abi.encode(nonce, msg.sender, _target, msg.value, _gasLimit, _data) + bytes32 withdrawalHash = WithdrawalVerifier._deriveWithdrawalHash( + nonce, + msg.sender, + _target, + msg.value, + _gasLimit, + _data ); withdrawals[withdrawalHash] = true; diff --git a/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol similarity index 96% rename from packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol rename to packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol index 3655f85d8549..0346d29c87c1 100644 --- a/packages/contracts/contracts/L1/libraries/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.10; /* Library Imports */ import { Lib_SecureMerkleTrie -} from "../../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; +} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; /** * @title WithdrawalVerifier diff --git a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol index 2155ae91b4a9..26525d5caa36 100644 --- a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol +++ b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol @@ -7,7 +7,7 @@ import { Vm } from "../../lib/forge-std/src/Vm.sol"; /* Target contract dependencies */ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -import { WithdrawalVerifier } from "../L1/libraries/Lib_WithdrawalVerifier.sol"; +import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; /* Target contract */ import { WithdrawalsRelay } from "../L1/abstracts/WithdrawalsRelay.sol"; From 54a8ffa45e64393b7f9ae75874f12478fc0c5288 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 26 Apr 2022 09:35:01 -0700 Subject: [PATCH 499/585] opnode: Better parsing of the TransactionDepositedEvent (#382) This now asserts that the offset for the bytes field of the event is the correct value rather than the previous incorrect check. This check is not fully necessary, but good to have to validate that the data is well formed. --- opnode/rollup/derive/payload_attributes.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 161e9e10dedf..fdd5df531af5 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -125,10 +125,13 @@ func UnmarshalLogEvent(ev *types.Log) (*types.DepositTx, error) { dep.To = &to } offset += 32 + // dynamic fields are encoded in three parts. The fixed size portion is the offset of the start of the + // data. The first 32 bytes of a `bytes` object is the length of the bytes. Then are the actual bytes + // padded out to 32 byte increments. var dataOffset uint256.Int dataOffset.SetBytes(ev.Data[offset : offset+32]) offset += 32 - if dataOffset.Eq(uint256.NewInt(128)) { + if !dataOffset.Eq(uint256.NewInt(offset)) { return nil, fmt.Errorf("incorrect data offset: %v", dataOffset[0]) } From 1255731adf1b4bc2901ec8b822766384f93836c6 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Tue, 26 Apr 2022 22:51:33 +0200 Subject: [PATCH 500/585] Makefile,ops: docker compose up instead of run to make devnet-down work, and fix makefile label (#385) --- Makefile | 4 ++-- ops/devnet-up.sh | 8 +++----- ops/docker-compose.yml | 3 ++- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 1edf093b2c9b..faea4c67e4b9 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ devnet-up: devnet-down: @(cd ./ops && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose stop) -.PHONY: devnet-stop +.PHONY: devnet-down devnet-clean: rm -rf ./packages/contracts/deployments/devnetL1 @@ -66,4 +66,4 @@ devnet-genesis: l2os: go build -o ./bin/l2os ./l2os/cmd/l2os -.PHONY: l2os \ No newline at end of file +.PHONY: l2os diff --git a/ops/devnet-up.sh b/ops/devnet-up.sh index f06fadf716a0..fa17d0220a7a 100644 --- a/ops/devnet-up.sh +++ b/ops/devnet-up.sh @@ -137,10 +137,8 @@ jq ". | .genesis.l1.hash = \"$(echo $L1_GENESIS | jq -r '.result.hash')\"" < ./o # Bring up everything else. cd ops -echo "Bringing up rollup node..." -docker-compose up -d opnode -echo "Bringing up output submitter..." -docker-compose run -e L2OO_ADDRESS="$L2OO_ADDRESS" -d --name ops-l2os-1 l2os +echo "Bringing up devnet..." +L2OO_ADDRESS="$L2OO_ADDRESS" docker-compose up -d l2os cd ../ -echo "Devnet ready." \ No newline at end of file +echo "Devnet ready." diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 6765a6af6ea7..c65376a14aeb 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -69,4 +69,5 @@ services: OUTPUT_SUBMITTER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 OUTPUT_SUBMITTER_RESUBMISSION_TIMEOUT: 30s OUTPUT_SUBMITTER_MNEMONIC: test test test test test test test test test test test junk - OUTPUT_SUBMITTER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" \ No newline at end of file + OUTPUT_SUBMITTER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" + L2OO_ADDRESS: "${L2OO_ADDRESS}" From 431274830a0c6db6edd0ed417764ef6db6bb80fd Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Tue, 26 Apr 2022 16:43:57 -0700 Subject: [PATCH 501/585] opnode: Do not drop all deposits on parsing error (#383) * Change deposit gasLimit from uint256 to uint64 This prevents the user from setting a gas limit that the rollup node is not able to parse. * opnode: Do not drop all deposits on parsing error Only drop the affected deposit. This does mean loss of funds, but this is also a case that should never happen. In addition, halting the chain means that while funds are safe, we are exposed to a denial of service attack if it would be possible to cause a parsing error from the deposit feed contract. --- opnode/contracts/deposit/deposit_feed_raw.go | 474 ++++++++++++------ opnode/rollup/derive/payload_attributes.go | 32 +- .../rollup/derive/payload_attributes_test.go | 4 +- opnode/rollup/driver/step.go | 14 +- opnode/test/system_test.go | 4 +- packages/contracts/.gas-snapshot | 20 +- .../contracts/L1/abstracts/DepositFeed.sol | 4 +- .../contracts/test/DepositFeed.t.sol | 4 +- .../contracts/test/OptimismPortal.t.sol | 2 +- .../contracts/MultiDepositor.sol | 2 +- specs/deposits.md | 2 +- 11 files changed, 369 insertions(+), 193 deletions(-) diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/opnode/contracts/deposit/deposit_feed_raw.go index a94c2ee60513..1ae6a191af2c 100644 --- a/opnode/contracts/deposit/deposit_feed_raw.go +++ b/opnode/contracts/deposit/deposit_feed_raw.go @@ -362,7 +362,7 @@ func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method s // DepositFeedMetaData contains all meta data concerning the DepositFeed contract. var DepositFeedMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", } // DepositFeedABI is the input ABI used to generate the binding from. @@ -511,24 +511,24 @@ func (_DepositFeed *DepositFeedTransactorRaw) Transact(opts *bind.TransactOpts, return _DepositFeed.Contract.contract.Transact(opts, method, params...) } -// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. // -// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_DepositFeed *DepositFeedTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_DepositFeed *DepositFeedTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { return _DepositFeed.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) } -// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. // -// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_DepositFeed *DepositFeedSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_DepositFeed *DepositFeedSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { return _DepositFeed.Contract.DepositTransaction(&_DepositFeed.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) } -// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. // -// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_DepositFeed *DepositFeedTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_DepositFeed *DepositFeedTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { return _DepositFeed.Contract.DepositTransaction(&_DepositFeed.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) } @@ -605,15 +605,15 @@ type DepositFeedTransactionDeposited struct { To common.Address Mint *big.Int Value *big.Int - GasLimit *big.Int + GasLimit uint64 IsCreation bool Data []byte Raw types.Log // Blockchain specific contextual infos } -// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. // -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) func (_DepositFeed *DepositFeedFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DepositFeedTransactionDepositedIterator, error) { var fromRule []interface{} @@ -632,9 +632,9 @@ func (_DepositFeed *DepositFeedFilterer) FilterTransactionDeposited(opts *bind.F return &DepositFeedTransactionDepositedIterator{contract: _DepositFeed.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil } -// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. // -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) func (_DepositFeed *DepositFeedFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *DepositFeedTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} @@ -678,9 +678,9 @@ func (_DepositFeed *DepositFeedFilterer) WatchTransactionDeposited(opts *bind.Wa }), nil } -// ParseTransactionDeposited is a log parse operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// ParseTransactionDeposited is a log parse operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. // -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) func (_DepositFeed *DepositFeedFilterer) ParseTransactionDeposited(log types.Log) (*DepositFeedTransactionDeposited, error) { event := new(DepositFeedTransactionDeposited) if err := _DepositFeed.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { @@ -692,8 +692,8 @@ func (_DepositFeed *DepositFeedFilterer) ParseTransactionDeposited(log types.Log // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620012f2380380620012f2833981810160405281019062000038919062000260565b620000586200004c620000b460201b60201c565b620000bc60201b60201c565b85608081815250508460a081815250508360026000848152602001908152602001600020819055508260c08181525050816001819055508160e08181525050620000a881620000bc60201b60201c565b505050505050620002fc565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6200019a8162000185565b8114620001a657600080fd5b50565b600081519050620001ba816200018f565b92915050565b6000819050919050565b620001d581620001c0565b8114620001e157600080fd5b50565b600081519050620001f581620001ca565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022882620001fb565b9050919050565b6200023a816200021b565b81146200024657600080fd5b50565b6000815190506200025a816200022f565b92915050565b60008060008060008060c0878903121562000280576200027f62000180565b5b60006200029089828a01620001a9565b9650506020620002a389828a01620001a9565b9550506040620002b689828a01620001e4565b9450506060620002c989828a01620001a9565b9350506080620002dc89828a01620001a9565b92505060a0620002ef89828a0162000249565b9150509295509295509295565b60805160a05160c05160e051610f9962000359600039600081816102b30152818161033701526106b001526000818161036b01526106d4015260008181610316015261066f01526000818161058b01526106f80152610f996000f3fe6080604052600436106100a75760003560e01c806393991af31161006457806393991af31461019d578063a25ae557146101c8578063c5095d6814610205578063c90ec2da14610230578063e1a41bcf1461025b578063f2fde38b14610286576100a7565b806302e51345146100ac5780630c1952d3146100e95780632518810414610114578063357e951f14610130578063715018a61461015b5780638da5cb5b14610172575b600080fd5b3480156100b857600080fd5b506100d360048036038101906100ce9190610919565b6102af565b6040516100e09190610955565b60405180910390f35b3480156100f557600080fd5b506100fe610393565b60405161010b9190610955565b60405180910390f35b61012e600480360381019061012991906109a6565b610399565b005b34801561013c57600080fd5b50610145610587565b6040516101529190610955565b60405180910390f35b34801561016757600080fd5b506101706105bc565b005b34801561017e57600080fd5b50610187610644565b6040516101949190610a4e565b60405180910390f35b3480156101a957600080fd5b506101b261066d565b6040516101bf9190610955565b60405180910390f35b3480156101d457600080fd5b506101ef60048036038101906101ea9190610919565b610691565b6040516101fc9190610a78565b60405180910390f35b34801561021157600080fd5b5061021a6106ae565b6040516102279190610955565b60405180910390f35b34801561023c57600080fd5b506102456106d2565b6040516102529190610955565b60405180910390f35b34801561026757600080fd5b506102706106f6565b60405161027d9190610955565b60405180910390f35b34801561029257600080fd5b506102ad60048036038101906102a89190610abf565b61071a565b005b60007f0000000000000000000000000000000000000000000000000000000000000000821015610314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030b90610b6f565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161036657610365610b8f565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6103a1610812565b73ffffffffffffffffffffffffffffffffffffffff166103bf610644565b73ffffffffffffffffffffffffffffffffffffffff1614610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040c90610c0a565b60405180910390fd5b428310610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e90610c9c565b60405180910390fd5b61045f610587565b83146104a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049790610d2e565b60405180910390fd5b6000801b8414156104e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104dd90610d9a565b60405180910390fd5b6000801b82146105345781814014610533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052a90610e2c565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546105b79190610e7b565b905090565b6105c4610812565b73ffffffffffffffffffffffffffffffffffffffff166105e2610644565b73ffffffffffffffffffffffffffffffffffffffff1614610638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062f90610c0a565b60405180910390fd5b610642600061081a565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610722610812565b73ffffffffffffffffffffffffffffffffffffffff16610740610644565b73ffffffffffffffffffffffffffffffffffffffff1614610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078d90610c0a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fd90610f43565b60405180910390fd5b61080f8161081a565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6108f6816108e3565b811461090157600080fd5b50565b600081359050610913816108ed565b92915050565b60006020828403121561092f5761092e6108de565b5b600061093d84828501610904565b91505092915050565b61094f816108e3565b82525050565b600060208201905061096a6000830184610946565b92915050565b6000819050919050565b61098381610970565b811461098e57600080fd5b50565b6000813590506109a08161097a565b92915050565b600080600080608085870312156109c0576109bf6108de565b5b60006109ce87828801610991565b94505060206109df87828801610904565b93505060406109f087828801610991565b9250506060610a0187828801610904565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a3882610a0d565b9050919050565b610a4881610a2d565b82525050565b6000602082019050610a636000830184610a3f565b92915050565b610a7281610970565b82525050565b6000602082019050610a8d6000830184610a69565b92915050565b610a9c81610a2d565b8114610aa757600080fd5b50565b600081359050610ab981610a93565b92915050565b600060208284031215610ad557610ad46108de565b5b6000610ae384828501610aaa565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610b59602983610aec565b9150610b6482610afd565b604082019050919050565b60006020820190508181036000830152610b8881610b4c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610bf4602083610aec565b9150610bff82610bbe565b602082019050919050565b60006020820190508181036000830152610c2381610be7565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610c86602183610aec565b9150610c9182610c2a565b604082019050919050565b60006020820190508181036000830152610cb581610c79565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610d18602e83610aec565b9150610d2382610cbc565b604082019050919050565b60006020820190508181036000830152610d4781610d0b565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610d84601d83610aec565b9150610d8f82610d4e565b602082019050919050565b60006020820190508181036000830152610db381610d77565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610e16603983610aec565b9150610e2182610dba565b604082019050919050565b60006020820190508181036000830152610e4581610e09565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e86826108e3565b9150610e91836108e3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ec657610ec5610e4c565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610f2d602683610aec565b9150610f3882610ed1565b604082019050919050565b60006020820190508181036000830152610f5c81610f20565b905091905056fea2646970667358221220980520f45819a707ff13a09b23bdace7cce468e4b8e92e7fd2f480d56c85cb7664736f6c634300080a0033", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620016eb380380620016eb8339818101604052810190620000389190620002b3565b620000586200004c6200010760201b60201c565b6200010f60201b60201c565b600085876200006891906200037e565b14620000ab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000a2906200043d565b60405180910390fd5b85608081815250508460a081815250508360026000848152602001908152602001600020819055508260c08181525050816001819055508160e08181525050620000fb816200010f60201b60201c565b5050505050506200045f565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b620001ed81620001d8565b8114620001f957600080fd5b50565b6000815190506200020d81620001e2565b92915050565b6000819050919050565b620002288162000213565b81146200023457600080fd5b50565b60008151905062000248816200021d565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200027b826200024e565b9050919050565b6200028d816200026e565b81146200029957600080fd5b50565b600081519050620002ad8162000282565b92915050565b60008060008060008060c08789031215620002d357620002d2620001d3565b5b6000620002e389828a01620001fc565b9650506020620002f689828a01620001fc565b95505060406200030989828a0162000237565b94505060606200031c89828a01620001fc565b93505060806200032f89828a01620001fc565b92505060a06200034289828a016200029c565b9150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006200038b82620001d8565b91506200039883620001d8565b925082620003ab57620003aa6200034f565b5b828206905092915050565b600082825260208201905092915050565b7f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560008201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000602082015250565b600062000425603783620003b6565b91506200043282620003c7565b604082019050919050565b60006020820190508181036000830152620004588162000416565b9050919050565b60805160a05160c05160e051611228620004c36000396000818161031a0152818161039e015261077e0152600081816103d201526108940152600081816102f4015261037d0152600081816107110152818161074b01526107a201526112286000f3fe6080604052600436106100c15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b14610236578063a25ae55714610261578063a4771aad1461029e578063f2fde38b146102c9576100c1565b806341840fa6146101c9578063529933df146101f4578063715018a61461021f576100c1565b80622134cc146100c657806302e51345146100f15780630c1952d31461012e57806325188104146101595780632b5d15d914610175578063357e951f1461019e575b600080fd5b3480156100d257600080fd5b506100db6102f2565b6040516100e89190610a93565b60405180910390f35b3480156100fd57600080fd5b5061011860048036038101906101139190610adf565b610316565b6040516101259190610a93565b60405180910390f35b34801561013a57600080fd5b506101436103fa565b6040516101509190610a93565b60405180910390f35b610173600480360381019061016e9190610b42565b610400565b005b34801561018157600080fd5b5061019c60048036038101906101979190610ba9565b6105ee565b005b3480156101aa57600080fd5b506101b3610747565b6040516101c09190610a93565b60405180910390f35b3480156101d557600080fd5b506101de61077c565b6040516101eb9190610a93565b60405180910390f35b34801561020057600080fd5b506102096107a0565b6040516102169190610a93565b60405180910390f35b34801561022b57600080fd5b506102346107c4565b005b34801561024257600080fd5b5061024b61084c565b6040516102589190610c17565b60405180910390f35b34801561026d57600080fd5b5061028860048036038101906102839190610adf565b610875565b6040516102959190610c41565b60405180910390f35b3480156102aa57600080fd5b506102b3610892565b6040516102c09190610a93565b60405180910390f35b3480156102d557600080fd5b506102f060048036038101906102eb9190610c88565b6108b6565b005b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f000000000000000000000000000000000000000000000000000000000000000082101561037b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161037290610d38565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008303816103cd576103cc610d58565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6104086109ae565b73ffffffffffffffffffffffffffffffffffffffff1661042661084c565b73ffffffffffffffffffffffffffffffffffffffff161461047c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047390610dd3565b60405180910390fd5b4283106104be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b590610e65565b60405180910390fd5b6104c6610747565b8314610507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104fe90610ef7565b60405180910390fd5b6000801b84141561054d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161054490610f63565b60405180910390fd5b6000801b821461059b578181401461059a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059190610ff5565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b6105f66109ae565b73ffffffffffffffffffffffffffffffffffffffff1661061461084c565b73ffffffffffffffffffffffffffffffffffffffff161461066a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161066190610dd3565b60405180910390fd5b60006002600060015481526020019081526020016000205490508082146106c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106bd90611087565b60405180910390fd5b600154817f36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f26660405160405180910390a3600260006001548152602001908152602001600020600090557f000000000000000000000000000000000000000000000000000000000000000060015461073d91906110d6565b6001819055505050565b60007f0000000000000000000000000000000000000000000000000000000000000000600154610777919061110a565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6107cc6109ae565b73ffffffffffffffffffffffffffffffffffffffff166107ea61084c565b73ffffffffffffffffffffffffffffffffffffffff1614610840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083790610dd3565b60405180910390fd5b61084a60006109b6565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6108be6109ae565b73ffffffffffffffffffffffffffffffffffffffff166108dc61084c565b73ffffffffffffffffffffffffffffffffffffffff1614610932576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161092990610dd3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156109a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610999906111d2565b60405180910390fd5b6109ab816109b6565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b610a8d81610a7a565b82525050565b6000602082019050610aa86000830184610a84565b92915050565b600080fd5b610abc81610a7a565b8114610ac757600080fd5b50565b600081359050610ad981610ab3565b92915050565b600060208284031215610af557610af4610aae565b5b6000610b0384828501610aca565b91505092915050565b6000819050919050565b610b1f81610b0c565b8114610b2a57600080fd5b50565b600081359050610b3c81610b16565b92915050565b60008060008060808587031215610b5c57610b5b610aae565b5b6000610b6a87828801610b2d565b9450506020610b7b87828801610aca565b9350506040610b8c87828801610b2d565b9250506060610b9d87828801610aca565b91505092959194509250565b600060208284031215610bbf57610bbe610aae565b5b6000610bcd84828501610b2d565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610c0182610bd6565b9050919050565b610c1181610bf6565b82525050565b6000602082019050610c2c6000830184610c08565b92915050565b610c3b81610b0c565b82525050565b6000602082019050610c566000830184610c32565b92915050565b610c6581610bf6565b8114610c7057600080fd5b50565b600081359050610c8281610c5c565b92915050565b600060208284031215610c9e57610c9d610aae565b5b6000610cac84828501610c73565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610d22602983610cb5565b9150610d2d82610cc6565b604082019050919050565b60006020820190508181036000830152610d5181610d15565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610dbd602083610cb5565b9150610dc882610d87565b602082019050919050565b60006020820190508181036000830152610dec81610db0565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610e4f602183610cb5565b9150610e5a82610df3565b604082019050919050565b60006020820190508181036000830152610e7e81610e42565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610ee1602e83610cb5565b9150610eec82610e85565b604082019050919050565b60006020820190508181036000830152610f1081610ed4565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610f4d601d83610cb5565b9150610f5882610f17565b602082019050919050565b60006020820190508181036000830152610f7c81610f40565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610fdf603983610cb5565b9150610fea82610f83565b604082019050919050565b6000602082019050818103600083015261100e81610fd2565b9050919050565b7f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060008201527f6f75747075742e00000000000000000000000000000000000000000000000000602082015250565b6000611071602783610cb5565b915061107c82611015565b604082019050919050565b600060208201905081810360008301526110a081611064565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006110e182610a7a565b91506110ec83610a7a565b9250828210156110ff576110fe6110a7565b5b828203905092915050565b600061111582610a7a565b915061112083610a7a565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115611155576111546110a7565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006111bc602683610cb5565b91506111c782611160565b604082019050919050565b600060208201905081810360008301526111eb816111af565b905091905056fea2646970667358221220c4ef1d00f7f2659b0bb4c745bd02e768e44edce52f60d1b4607f3f90d6b2b7d664736f6c634300080a0033", } // L2OutputOracleABI is the input ABI used to generate the binding from. @@ -863,12 +863,12 @@ func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transact(opts *bind.Transact return _L2OutputOracle.Contract.contract.Transact(opts, method, params...) } -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. // -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) { +// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) HISTORICALTOTALBLOCKS(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp) + err := _L2OutputOracle.contract.Call(opts, &out, "HISTORICAL_TOTAL_BLOCKS") if err != nil { return *new(*big.Int), err @@ -880,57 +880,88 @@ func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.Cal } -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. // -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { - return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) HISTORICALTOTALBLOCKS() (*big.Int, error) { + return _L2OutputOracle.Contract.HISTORICALTOTALBLOCKS(&_L2OutputOracle.CallOpts) } -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. // -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { - return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) HISTORICALTOTALBLOCKS() (*big.Int, error) { + return _L2OutputOracle.Contract.HISTORICALTOTALBLOCKS(&_L2OutputOracle.CallOpts) } -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { +// Solidity: function L2_BLOCK_TIME() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) L2BLOCKTIME(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) + err := _L2OutputOracle.contract.Call(opts, &out, "L2_BLOCK_TIME") if err != nil { - return *new([32]byte), err + return *new(*big.Int), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err } -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { - return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +// Solidity: function L2_BLOCK_TIME() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) L2BLOCKTIME() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BLOCKTIME(&_L2OutputOracle.CallOpts) } -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { - return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +// Solidity: function L2_BLOCK_TIME() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) L2BLOCKTIME() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BLOCKTIME(&_L2OutputOracle.CallOpts) +} + +// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. +// +// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) STARTINGBLOCKTIMESTAMP(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "STARTING_BLOCK_TIMESTAMP") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. // -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) { + return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts) +} + +// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. +// +// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) { + return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts) +} + +// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. +// +// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) SUBMISSIONINTERVAL(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "historicalTotalBlocks") + err := _L2OutputOracle.contract.Call(opts, &out, "SUBMISSION_INTERVAL") if err != nil { return *new(*big.Int), err @@ -942,26 +973,26 @@ func (_L2OutputOracle *L2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.Ca } -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. // -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) HistoricalTotalBlocks() (*big.Int, error) { - return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) SUBMISSIONINTERVAL() (*big.Int, error) { + return _L2OutputOracle.Contract.SUBMISSIONINTERVAL(&_L2OutputOracle.CallOpts) } -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. // -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) HistoricalTotalBlocks() (*big.Int, error) { - return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) SUBMISSIONINTERVAL() (*big.Int, error) { + return _L2OutputOracle.Contract.SUBMISSIONINTERVAL(&_L2OutputOracle.CallOpts) } -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. // -// Solidity: function l2BlockTime() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "l2BlockTime") + err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp) if err != nil { return *new(*big.Int), err @@ -973,18 +1004,49 @@ func (_L2OutputOracle *L2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (* } -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. // -// Solidity: function l2BlockTime() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) L2BlockTime() (*big.Int, error) { - return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) } -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. // -// Solidity: function l2BlockTime() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) L2BlockTime() (*big.Int, error) { - return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) } // LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. @@ -1080,68 +1142,6 @@ func (_L2OutputOracle *L2OutputOracleCallerSession) Owner() (common.Address, err return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) } -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) StartingBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "startingBlockTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) StartingBlockTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) -} - -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) StartingBlockTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) -} - -// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. -// -// Solidity: function submissionInterval() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) SubmissionInterval(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "submissionInterval") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. -// -// Solidity: function submissionInterval() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) SubmissionInterval() (*big.Int, error) { - return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) -} - -// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. -// -// Solidity: function submissionInterval() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) SubmissionInterval() (*big.Int, error) { - return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) -} - // AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. // // Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() @@ -1163,6 +1163,27 @@ func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) } +// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// +// Solidity: function deleteL2Output(bytes32 _l2Output) returns() +func (_L2OutputOracle *L2OutputOracleTransactor) DeleteL2Output(opts *bind.TransactOpts, _l2Output [32]byte) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "deleteL2Output", _l2Output) +} + +// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// +// Solidity: function deleteL2Output(bytes32 _l2Output) returns() +func (_L2OutputOracle *L2OutputOracleSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { + return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) +} + +// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// +// Solidity: function deleteL2Output(bytes32 _l2Output) returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { + return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) +} + // RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. // // Solidity: function renounceOwnership() returns() @@ -1511,6 +1532,159 @@ func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.L return event, nil } +// L2OutputOracleL2OutputDeletedIterator is returned from FilterL2OutputDeleted and is used to iterate over the raw logs and unpacked data for L2OutputDeleted events raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputDeletedIterator struct { + Event *L2OutputOracleL2OutputDeleted // 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 *L2OutputOracleL2OutputDeletedIterator) 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(L2OutputOracleL2OutputDeleted) + 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(L2OutputOracleL2OutputDeleted) + 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 *L2OutputOracleL2OutputDeletedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *L2OutputOracleL2OutputDeletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// L2OutputOracleL2OutputDeleted represents a L2OutputDeleted event raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputDeleted struct { + L2Output [32]byte + L2timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterL2OutputDeleted is a free log retrieval operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputDeleted(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputDeletedIterator, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) + if err != nil { + return nil, err + } + return &L2OutputOracleL2OutputDeletedIterator{contract: _L2OutputOracle.contract, event: "l2OutputDeleted", logs: logs, sub: sub}, nil +} + +// WatchL2OutputDeleted is a free log subscription operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputDeleted, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) + 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(L2OutputOracleL2OutputDeleted) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", 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 +} + +// ParseL2OutputDeleted is a log parse operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputDeleted(log types.Log) (*L2OutputOracleL2OutputDeleted, error) { + event := new(L2OutputOracleL2OutputDeleted) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + // LibBytesUtilsMetaData contains all meta data concerning the LibBytesUtils contract. var LibBytesUtilsMetaData = &bind.MetaData{ ABI: "[]", @@ -2378,8 +2552,8 @@ func (_LibSecureMerkleTrie *LibSecureMerkleTrieTransactorRaw) Transact(opts *bin // OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. var OptimismPortalMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60c060405261dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005357600080fd5b506040516200306b3803806200306b83398181016040528101906200007991906200017a565b81818173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050806080818152505050505050620001c1565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000f382620000c6565b9050919050565b60006200010782620000e6565b9050919050565b6200011981620000fa565b81146200012557600080fd5b50565b60008151905062000139816200010e565b92915050565b6000819050919050565b62000154816200013f565b81146200016057600080fd5b50565b600081519050620001748162000149565b92915050565b60008060408385031215620001945762000193620000c1565b5b6000620001a48582860162000128565b9250506020620001b78582860162000163565b9150509250929050565b60805160a051612e76620001f5600039600081816102b2015261037801526000818161031a01526106720152612e766000f3fe6080604052600436106100585760003560e01c80621c2ff6146100835780639bf62d82146100ae578063a14238e7146100d9578063eecf1c3614610116578063fa92670c1461013f578063ff61cc931461015b5761007e565b3661007e5761007c3334617530600060405180602001604052806000815250610186565b005b600080fd5b34801561008f57600080fd5b506100986102b0565b6040516100a59190611bd9565b60405180910390f35b3480156100ba57600080fd5b506100c36102d4565b6040516100d09190611c15565b60405180910390f35b3480156100e557600080fd5b5061010060048036038101906100fb9190611c7a565b6102f8565b60405161010d9190611cc2565b60405180910390f35b34801561012257600080fd5b5061013d60048036038101906101389190611dc8565b610318565b005b61015960048036038101906101549190612041565b610186565b005b34801561016757600080fd5b50610170610670565b60405161017d91906120e7565b60405180910390f35b8180156101c05750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156101f7576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461023b5761023833610694565b90505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad34888888886040516102a095949392919061218a565b60405180910390a3505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915054906101000a900460ff1681565b7f00000000000000000000000000000000000000000000000000000000000000008401421015610374576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a25ae557866040518263ffffffff1660e01b81526004016103cf91906120e7565b602060405180830381865afa1580156103ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041091906121f9565b905061041b846106b4565b8114610453576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104648d8d8d8d8d8d8d6106fa565b90506000151561047a828760400135878761073c565b151514156104b4576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600115156001600083815260200190815260200160002060009054906101000a900460ff1615151415610513576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161057f929190612256565b600060405180830381858888f193505050503d80600081146105bd576040519150601f19603f3d011682016040523d82523d6000602084013e6105c2565b606091505b5050905061dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600180600084815260200190815260200160002060006101000a81548160ff021916908315150217905550817f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f60405160405180910390a25050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600073111100000000000000000000000000000000111182019050919050565b600081600001358260200135836040013584606001356040516020016106dd949392919061227e565b604051602081830303815290604052805190602001209050919050565b60008787878787878760405160200161071997969594939291906122f0565b604051602081830303815290604052805190602001209050979650505050505050565b60008085600160405160200161075392919061235a565b60405160208183030381529060405280519060200120905061080f8160405160200161077f91906123a4565b6040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508861081a565b915050949350505050565b6000806108268661083f565b90506108348186868661086f565b915050949350505050565b6060818051906020012060405160200161085991906123a4565b6040516020818303038152906040529050919050565b600080600061087f8786866108a2565b915091508180156108965750610895868261097b565b5b92505050949350505050565b6000606060006108b185610996565b905060008060006108c3848a89610a8b565b925092509250600080835114905080806108da5750815b610919576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109109061241c565b60405180910390fd5b6000816109355760405180602001604052806000815250610965565b61096486600187610946919061246b565b815181106109575761095661249f565b5b6020026020010151610efc565b5b9050818197509750505050505050935093915050565b60008180519060200120838051906020012014905092915050565b606060006109a383610f3d565b90506000815167ffffffffffffffff8111156109c2576109c1611f16565b5b6040519080825280602002602001820160405280156109fb57816020015b6109e8611b26565b8152602001906001900390816109e05790505b50905060005b8251811015610a80576000610a2f848381518110610a2257610a2161249f565b5b6020026020010151610f57565b90506040518060400160405280828152602001610a4b83610f3d565b815250838381518110610a6157610a6061249f565b5b6020026020010181905250508080610a78906124ce565b915050610a01565b508092505050919050565b60006060600080600090506000610aa187610fed565b90506000869050600080610ab3611b26565b60005b8c51811015610eac578c8181518110610ad257610ad161249f565b5b602002602001015191508284610ae89190612517565b9350600187610af79190612517565b96506000841415610b54578482600001518051906020012014610b4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b46906125b9565b60405180910390fd5b610c03565b602082600001515110610bb3578482600001518051906020012014610bae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba590612625565b60405180910390fd5b610c02565b84610bc18360000151611192565b14610c01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf890612691565b60405180910390fd5b5b5b60016010610c119190612517565b8260200151511415610c8c578551841415610c2b57610eac565b6000868581518110610c4057610c3f61249f565b5b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c6c57610c6b61249f565b5b60200260200101519050610c7f816111cc565b9650600194505050610e99565b60028260200151511415610e5e576000610ca58361120a565b9050600081600081518110610cbd57610cbc61249f565b5b602001015160f81c60f81b60f81c90506000600282610cdc91906126ed565b6002610ce8919061271e565b90506000610cf9848360ff16611243565b90506000610d078b8a611243565b90506000610d158383611284565b9050600260ff168560ff161480610d325750600360ff168560ff16145b15610d8f57808351148015610d475750808251145b15610d5b57808a610d589190612517565b99505b608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b600060ff168560ff161480610daa5750600160ff168560ff16145b15610e235782518114610deb57608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b610e138860200151600181518110610e0657610e0561249f565b5b60200260200101516111cc565b9a50809850505050505050610e99565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e55906127c4565b60405180910390fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9090612830565b60405180910390fd5b8080610ea4906124ce565b915050610ab6565b506000608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168514905086610ee58786611243565b829950995099505050505050505093509350939050565b6060610f3682602001516001846020015151610f18919061246b565b81518110610f2957610f2861249f565b5b6020026020010151610f57565b9050919050565b6060610f50610f4b83611347565b611375565b9050919050565b60606000806000610f678561156c565b92509250925060006001811115610f8157610f80612850565b5b816001811115610f9457610f93612850565b5b14610fd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fcb906128cb565b60405180910390fd5b610fe385602001518484611885565b9350505050919050565b6060600060028351610fff91906128eb565b67ffffffffffffffff81111561101857611017611f16565b5b6040519080825280601f01601f19166020018201604052801561104a5781602001600182028036833780820191505090505b50905060005b835181101561118857600484828151811061106e5761106d61249f565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c826002836110ab91906128eb565b815181106110bc576110bb61249f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506010848281518110611100576110ff61249f565b5b602001015160f81c60f81b60f81c61111891906126ed565b60f81b82600160028461112b91906128eb565b6111359190612517565b815181106111465761114561249f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080611180906124ce565b915050611050565b5080915050919050565b60006020825110156111b057600060208301519050809150506111c7565b818060200190518101906111c491906121f9565b90505b919050565b600060606020836000015110156111ed576111e68361198b565b90506111f9565b6111f683610f57565b90505b61120281611192565b915050919050565b606061123c611237836020015160008151811061122a5761122961249f565b5b6020026020010151610f57565b610fed565b9050919050565b6060825182106112645760405180602001604052806000815250905061127e565b61127b8383848651611276919061246b565b61199d565b90505b92915050565b600080600090505b80845111801561129c5750808351115b801561132557508281815181106112b6576112b561249f565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112f6576112f561249f565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b1561133d578080611335906124ce565b91505061128c565b8091505092915050565b61134f611b40565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606000806113838461156c565b925050915060018081111561139b5761139a612850565b5b8160018111156113ae576113ad612850565b5b146113ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e590612991565b60405180910390fd5b6000602067ffffffffffffffff81111561140b5761140a611f16565b5b60405190808252806020026020018201604052801561144457816020015b611431611b40565b8152602001906001900390816114295790505b5090506000808490505b866000015181101561155c576020821061149d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149490612a23565b60405180910390fd5b6000806114db6040518060400160405280858c600001516114be919061246b565b8152602001858c602001516114d39190612517565b81525061156c565b5091509150604051806040016040528083836114f79190612517565b8152602001848b6020015161150c9190612517565b8152508585815181106115225761152161249f565b5b602002602001018190525060018461153a9190612517565b935080826115489190612517565b836115539190612517565b9250505061144e565b8183528295505050505050919050565b6000806000808460000151116115b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ae90612a8f565b60405180910390fd5b6000846020015190506000815160001a9050607f81116115e457600060016000945094509450505061187e565b60b781116116565760006080826115fb919061246b565b905080876000015111611643576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163a90612afb565b60405180910390fd5b600181600095509550955050505061187e565b60bf811161173757600060b78261166d919061246b565b9050808760000151116116b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ac90612b67565b60405180910390fd5b6000816020036101000a600185015104905080826116d39190612517565b886000015111611718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170f90612bd3565b60405180910390fd5b8160016117259190612517565b8160009650965096505050505061187e565b60f781116117a957600060c08261174e919061246b565b905080876000015111611796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178d90612c3f565b60405180910390fd5b600181600195509550955050505061187e565b600060f7826117b8919061246b565b905080876000015111611800576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f790612cab565b60405180910390fd5b6000816020036101000a6001850151049050808261181e9190612517565b886000015111611863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185a90612d17565b60405180910390fd5b8160016118709190612517565b816001965096509650505050505b9193909250565b606060008267ffffffffffffffff8111156118a3576118a2611f16565b5b6040519080825280601f01601f1916602001820160405280156118d55781602001600182028036833780820191505090505b5090506000815114156118eb5780915050611984565b600084866118f99190612517565b9050600060208301905060005b6020866119139190612d37565b81101561194f578251825260208361192b9190612517565b925060208261193a9190612517565b91508080611947906124ce565b915050611906565b506000600160208781611965576119646126be565b5b066020036101000a039050808251168119845116178252839450505050505b9392505050565b606061199682611b09565b9050919050565b606081601f836119ad9190612517565b10156119ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e590612db4565b60405180910390fd5b8282846119fb9190612517565b1015611a3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a3390612db4565b60405180910390fd5b8183611a489190612517565b84511015611a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8290612e20565b60405180910390fd5b6060821560008114611aac5760405191506000825260208201604052611afd565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611aea5780518352602083019250602081019050611acd565b50868552601f19601f8301166040525050505b50809150509392505050565b6060611b1f826020015160008460000151611885565b9050919050565b604051806040016040528060608152602001606081525090565b604051806040016040528060008152602001600081525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611b9f611b9a611b9584611b5a565b611b7a565b611b5a565b9050919050565b6000611bb182611b84565b9050919050565b6000611bc382611ba6565b9050919050565b611bd381611bb8565b82525050565b6000602082019050611bee6000830184611bca565b92915050565b6000611bff82611b5a565b9050919050565b611c0f81611bf4565b82525050565b6000602082019050611c2a6000830184611c06565b92915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b611c5781611c44565b8114611c6257600080fd5b50565b600081359050611c7481611c4e565b92915050565b600060208284031215611c9057611c8f611c3a565b5b6000611c9e84828501611c65565b91505092915050565b60008115159050919050565b611cbc81611ca7565b82525050565b6000602082019050611cd76000830184611cb3565b92915050565b6000819050919050565b611cf081611cdd565b8114611cfb57600080fd5b50565b600081359050611d0d81611ce7565b92915050565b611d1c81611bf4565b8114611d2757600080fd5b50565b600081359050611d3981611d13565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611d6457611d63611d3f565b5b8235905067ffffffffffffffff811115611d8157611d80611d44565b5b602083019150836001820283011115611d9d57611d9c611d49565b5b9250929050565b600080fd5b600060808284031215611dbf57611dbe611da4565b5b81905092915050565b60008060008060008060008060008060006101808c8e031215611dee57611ded611c3a565b5b6000611dfc8e828f01611cfe565b9b50506020611e0d8e828f01611d2a565b9a50506040611e1e8e828f01611d2a565b9950506060611e2f8e828f01611cfe565b9850506080611e408e828f01611cfe565b97505060a08c013567ffffffffffffffff811115611e6157611e60611c3f565b5b611e6d8e828f01611d4e565b965096505060c0611e808e828f01611cfe565b94505060e0611e918e828f01611da9565b9350506101608c013567ffffffffffffffff811115611eb357611eb2611c3f565b5b611ebf8e828f01611d4e565b92509250509295989b509295989b9093969950565b611edd81611ca7565b8114611ee857600080fd5b50565b600081359050611efa81611ed4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611f4e82611f05565b810181811067ffffffffffffffff82111715611f6d57611f6c611f16565b5b80604052505050565b6000611f80611c30565b9050611f8c8282611f45565b919050565b600067ffffffffffffffff821115611fac57611fab611f16565b5b611fb582611f05565b9050602081019050919050565b82818337600083830152505050565b6000611fe4611fdf84611f91565b611f76565b90508281526020810184848401111561200057611fff611f00565b5b61200b848285611fc2565b509392505050565b600082601f83011261202857612027611d3f565b5b8135612038848260208601611fd1565b91505092915050565b600080600080600060a0868803121561205d5761205c611c3a565b5b600061206b88828901611d2a565b955050602061207c88828901611cfe565b945050604061208d88828901611cfe565b935050606061209e88828901611eeb565b925050608086013567ffffffffffffffff8111156120bf576120be611c3f565b5b6120cb88828901612013565b9150509295509295909350565b6120e181611cdd565b82525050565b60006020820190506120fc60008301846120d8565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561213c578082015181840152602081019050612121565b8381111561214b576000848401525b50505050565b600061215c82612102565b612166818561210d565b935061217681856020860161211e565b61217f81611f05565b840191505092915050565b600060a08201905061219f60008301886120d8565b6121ac60208301876120d8565b6121b960408301866120d8565b6121c66060830185611cb3565b81810360808301526121d88184612151565b90509695505050505050565b6000815190506121f381611c4e565b92915050565b60006020828403121561220f5761220e611c3a565b5b600061221d848285016121e4565b91505092915050565b600081905092915050565b600061223d8385612226565b935061224a838584611fc2565b82840190509392505050565b6000612263828486612231565b91508190509392505050565b61227881611c44565b82525050565b6000608082019050612293600083018761226f565b6122a0602083018661226f565b6122ad604083018561226f565b6122ba606083018461226f565b95945050505050565b60006122cf838561210d565b93506122dc838584611fc2565b6122e583611f05565b840190509392505050565b600060c082019050612305600083018a6120d8565b6123126020830189611c06565b61231f6040830188611c06565b61232c60608301876120d8565b61233960808301866120d8565b81810360a083015261234c8184866122c3565b905098975050505050505050565b600060408201905061236f600083018561226f565b61237c60208301846120d8565b9392505050565b6000819050919050565b61239e61239982611c44565b612383565b82525050565b60006123b0828461238d565b60208201915081905092915050565b600082825260208201905092915050565b7f50726f76696465642070726f6f6620697320696e76616c69642e000000000000600082015250565b6000612406601a836123bf565b9150612411826123d0565b602082019050919050565b60006020820190508181036000830152612435816123f9565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061247682611cdd565b915061248183611cdd565b9250828210156124945761249361243c565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006124d982611cdd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561250c5761250b61243c565b5b600182019050919050565b600061252282611cdd565b915061252d83611cdd565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125625761256161243c565b5b828201905092915050565b7f496e76616c696420726f6f742068617368000000000000000000000000000000600082015250565b60006125a36011836123bf565b91506125ae8261256d565b602082019050919050565b600060208201905081810360008301526125d281612596565b9050919050565b7f496e76616c6964206c6172676520696e7465726e616c20686173680000000000600082015250565b600061260f601b836123bf565b915061261a826125d9565b602082019050919050565b6000602082019050818103600083015261263e81612602565b9050919050565b7f496e76616c696420696e7465726e616c206e6f64652068617368000000000000600082015250565b600061267b601a836123bf565b915061268682612645565b602082019050919050565b600060208201905081810360008301526126aa8161266e565b9050919050565b600060ff82169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006126f8826126b1565b9150612703836126b1565b925082612713576127126126be565b5b828206905092915050565b6000612729826126b1565b9150612734836126b1565b9250828210156127475761274661243c565b5b828203905092915050565b7f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060008201527f7072656669780000000000000000000000000000000000000000000000000000602082015250565b60006127ae6026836123bf565b91506127b982612752565b604082019050919050565b600060208201905081810360008301526127dd816127a1565b9050919050565b7f526563656976656420616e20756e706172736561626c65206e6f64652e000000600082015250565b600061281a601d836123bf565b9150612825826127e4565b602082019050919050565b600060208201905081810360008301526128498161280d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f496e76616c696420524c502062797465732076616c75652e0000000000000000600082015250565b60006128b56018836123bf565b91506128c08261287f565b602082019050919050565b600060208201905081810360008301526128e4816128a8565b9050919050565b60006128f682611cdd565b915061290183611cdd565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561293a5761293961243c565b5b828202905092915050565b7f496e76616c696420524c50206c6973742076616c75652e000000000000000000600082015250565b600061297b6017836123bf565b915061298682612945565b602082019050919050565b600060208201905081810360008301526129aa8161296e565b9050919050565b7f50726f766964656420524c50206c6973742065786365656473206d6178206c6960008201527f7374206c656e6774682e00000000000000000000000000000000000000000000602082015250565b6000612a0d602a836123bf565b9150612a18826129b1565b604082019050919050565b60006020820190508181036000830152612a3c81612a00565b9050919050565b7f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000600082015250565b6000612a796018836123bf565b9150612a8482612a43565b602082019050919050565b60006020820190508181036000830152612aa881612a6c565b9050919050565b7f496e76616c696420524c502073686f727420737472696e672e00000000000000600082015250565b6000612ae56019836123bf565b9150612af082612aaf565b602082019050919050565b60006020820190508181036000830152612b1481612ad8565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00600082015250565b6000612b51601f836123bf565b9150612b5c82612b1b565b602082019050919050565b60006020820190508181036000830152612b8081612b44565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000600082015250565b6000612bbd6018836123bf565b9150612bc882612b87565b602082019050919050565b60006020820190508181036000830152612bec81612bb0565b9050919050565b7f496e76616c696420524c502073686f7274206c6973742e000000000000000000600082015250565b6000612c296017836123bf565b9150612c3482612bf3565b602082019050919050565b60006020820190508181036000830152612c5881612c1c565b9050919050565b7f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000600082015250565b6000612c95601d836123bf565b9150612ca082612c5f565b602082019050919050565b60006020820190508181036000830152612cc481612c88565b9050919050565b7f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000600082015250565b6000612d016016836123bf565b9150612d0c82612ccb565b602082019050919050565b60006020820190508181036000830152612d3081612cf4565b9050919050565b6000612d4282611cdd565b9150612d4d83611cdd565b925082612d5d57612d5c6126be565b5b828204905092915050565b7f736c6963655f6f766572666c6f77000000000000000000000000000000000000600082015250565b6000612d9e600e836123bf565b9150612da982612d68565b602082019050919050565b60006020820190508181036000830152612dcd81612d91565b9050919050565b7f736c6963655f6f75744f66426f756e6473000000000000000000000000000000600082015250565b6000612e0a6011836123bf565b9150612e1582612dd4565b602082019050919050565b60006020820190508181036000830152612e3981612dfd565b905091905056fea2646970667358221220476f1b0a95f0a876e335daed5cca410381992c0577e2b5bd936c3a5060def44964736f6c634300080a0033", + ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60c060405261dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005357600080fd5b50604051620030ba380380620030ba83398181016040528101906200007991906200017a565b81818173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050806080818152505050505050620001c1565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000f382620000c6565b9050919050565b60006200010782620000e6565b9050919050565b6200011981620000fa565b81146200012557600080fd5b50565b60008151905062000139816200010e565b92915050565b6000819050919050565b62000154816200013f565b81146200016057600080fd5b50565b600081519050620001748162000149565b92915050565b60008060408385031215620001945762000193620000c1565b5b6000620001a48582860162000128565b9250506020620001b78582860162000163565b9150509250929050565b60805160a051612ec5620001f5600039600081816102b2015261037801526000818161031a01526106720152612ec56000f3fe6080604052600436106100585760003560e01c80621c2ff6146100835780639bf62d82146100ae578063a14238e7146100d9578063e9e05c4214610116578063eecf1c3614610132578063ff61cc931461015b5761007e565b3661007e5761007c3334617530600060405180602001604052806000815250610186565b005b600080fd5b34801561008f57600080fd5b506100986102b0565b6040516100a59190611bd9565b60405180910390f35b3480156100ba57600080fd5b506100c36102d4565b6040516100d09190611c15565b60405180910390f35b3480156100e557600080fd5b5061010060048036038101906100fb9190611c7a565b6102f8565b60405161010d9190611cc2565b60405180910390f35b610130600480360381019061012b9190611ef1565b610186565b005b34801561013e57600080fd5b506101596004803603810190610154919061200c565b610318565b005b34801561016757600080fd5b50610170610670565b60405161017d9190612127565b60405180910390f35b8180156101c05750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156101f7576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461023b5761023833610694565b90505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102a09594939291906121d9565b60405180910390a3505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915054906101000a900460ff1681565b7f00000000000000000000000000000000000000000000000000000000000000008401421015610374576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a25ae557866040518263ffffffff1660e01b81526004016103cf9190612127565b602060405180830381865afa1580156103ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104109190612248565b905061041b846106b4565b8114610453576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104648d8d8d8d8d8d8d6106fa565b90506000151561047a828760400135878761073c565b151514156104b4576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600115156001600083815260200190815260200160002060009054906101000a900460ff1615151415610513576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b6040516105aa9291906122a5565b600060405180830381858888f193505050503d80600081146105e8576040519150601f19603f3d011682016040523d82523d6000602084013e6105ed565b606091505b5050905061dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550817f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f60405160405180910390a25050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600073111100000000000000000000000000000000111182019050919050565b600081600001358260200135836040013584606001356040516020016106dd94939291906122cd565b604051602081830303815290604052805190602001209050919050565b600087878787878787604051602001610719979695949392919061233f565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016107539291906123a9565b60405160208183030381529060405280519060200120905061080f8160405160200161077f91906123f3565b6040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508861081a565b915050949350505050565b6000806108268661083f565b90506108348186868661086f565b915050949350505050565b6060818051906020012060405160200161085991906123f3565b6040516020818303038152906040529050919050565b600080600061087f8786866108a2565b915091508180156108965750610895868261097b565b5b92505050949350505050565b6000606060006108b185610996565b905060008060006108c3848a89610a8b565b925092509250600080835114905080806108da5750815b610919576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109109061246b565b60405180910390fd5b6000816109355760405180602001604052806000815250610965565b6109648660018761094691906124ba565b81518110610957576109566124ee565b5b6020026020010151610efc565b5b9050818197509750505050505050935093915050565b60008180519060200120838051906020012014905092915050565b606060006109a383610f3d565b90506000815167ffffffffffffffff8111156109c2576109c1611dc6565b5b6040519080825280602002602001820160405280156109fb57816020015b6109e8611b26565b8152602001906001900390816109e05790505b50905060005b8251811015610a80576000610a2f848381518110610a2257610a216124ee565b5b6020026020010151610f57565b90506040518060400160405280828152602001610a4b83610f3d565b815250838381518110610a6157610a606124ee565b5b6020026020010181905250508080610a789061251d565b915050610a01565b508092505050919050565b60006060600080600090506000610aa187610fed565b90506000869050600080610ab3611b26565b60005b8c51811015610eac578c8181518110610ad257610ad16124ee565b5b602002602001015191508284610ae89190612566565b9350600187610af79190612566565b96506000841415610b54578482600001518051906020012014610b4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4690612608565b60405180910390fd5b610c03565b602082600001515110610bb3578482600001518051906020012014610bae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba590612674565b60405180910390fd5b610c02565b84610bc18360000151611192565b14610c01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf8906126e0565b60405180910390fd5b5b5b60016010610c119190612566565b8260200151511415610c8c578551841415610c2b57610eac565b6000868581518110610c4057610c3f6124ee565b5b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c6c57610c6b6124ee565b5b60200260200101519050610c7f816111cc565b9650600194505050610e99565b60028260200151511415610e5e576000610ca58361120a565b9050600081600081518110610cbd57610cbc6124ee565b5b602001015160f81c60f81b60f81c90506000600282610cdc919061273c565b6002610ce8919061276d565b90506000610cf9848360ff16611243565b90506000610d078b8a611243565b90506000610d158383611284565b9050600260ff168560ff161480610d325750600360ff168560ff16145b15610d8f57808351148015610d475750808251145b15610d5b57808a610d589190612566565b99505b608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b600060ff168560ff161480610daa5750600160ff168560ff16145b15610e235782518114610deb57608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b610e138860200151600181518110610e0657610e056124ee565b5b60200260200101516111cc565b9a50809850505050505050610e99565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5590612813565b60405180910390fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e909061287f565b60405180910390fd5b8080610ea49061251d565b915050610ab6565b506000608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168514905086610ee58786611243565b829950995099505050505050505093509350939050565b6060610f3682602001516001846020015151610f1891906124ba565b81518110610f2957610f286124ee565b5b6020026020010151610f57565b9050919050565b6060610f50610f4b83611347565b611375565b9050919050565b60606000806000610f678561156c565b92509250925060006001811115610f8157610f8061289f565b5b816001811115610f9457610f9361289f565b5b14610fd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fcb9061291a565b60405180910390fd5b610fe385602001518484611885565b9350505050919050565b6060600060028351610fff919061293a565b67ffffffffffffffff81111561101857611017611dc6565b5b6040519080825280601f01601f19166020018201604052801561104a5781602001600182028036833780820191505090505b50905060005b835181101561118857600484828151811061106e5761106d6124ee565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c826002836110ab919061293a565b815181106110bc576110bb6124ee565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506010848281518110611100576110ff6124ee565b5b602001015160f81c60f81b60f81c611118919061273c565b60f81b82600160028461112b919061293a565b6111359190612566565b81518110611146576111456124ee565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806111809061251d565b915050611050565b5080915050919050565b60006020825110156111b057600060208301519050809150506111c7565b818060200190518101906111c49190612248565b90505b919050565b600060606020836000015110156111ed576111e68361198b565b90506111f9565b6111f683610f57565b90505b61120281611192565b915050919050565b606061123c611237836020015160008151811061122a576112296124ee565b5b6020026020010151610f57565b610fed565b9050919050565b6060825182106112645760405180602001604052806000815250905061127e565b61127b838384865161127691906124ba565b61199d565b90505b92915050565b600080600090505b80845111801561129c5750808351115b801561132557508281815181106112b6576112b56124ee565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112f6576112f56124ee565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b1561133d5780806113359061251d565b91505061128c565b8091505092915050565b61134f611b40565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606000806113838461156c565b925050915060018081111561139b5761139a61289f565b5b8160018111156113ae576113ad61289f565b5b146113ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e5906129e0565b60405180910390fd5b6000602067ffffffffffffffff81111561140b5761140a611dc6565b5b60405190808252806020026020018201604052801561144457816020015b611431611b40565b8152602001906001900390816114295790505b5090506000808490505b866000015181101561155c576020821061149d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149490612a72565b60405180910390fd5b6000806114db6040518060400160405280858c600001516114be91906124ba565b8152602001858c602001516114d39190612566565b81525061156c565b5091509150604051806040016040528083836114f79190612566565b8152602001848b6020015161150c9190612566565b815250858581518110611522576115216124ee565b5b602002602001018190525060018461153a9190612566565b935080826115489190612566565b836115539190612566565b9250505061144e565b8183528295505050505050919050565b6000806000808460000151116115b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ae90612ade565b60405180910390fd5b6000846020015190506000815160001a9050607f81116115e457600060016000945094509450505061187e565b60b781116116565760006080826115fb91906124ba565b905080876000015111611643576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163a90612b4a565b60405180910390fd5b600181600095509550955050505061187e565b60bf811161173757600060b78261166d91906124ba565b9050808760000151116116b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ac90612bb6565b60405180910390fd5b6000816020036101000a600185015104905080826116d39190612566565b886000015111611718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170f90612c22565b60405180910390fd5b8160016117259190612566565b8160009650965096505050505061187e565b60f781116117a957600060c08261174e91906124ba565b905080876000015111611796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178d90612c8e565b60405180910390fd5b600181600195509550955050505061187e565b600060f7826117b891906124ba565b905080876000015111611800576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f790612cfa565b60405180910390fd5b6000816020036101000a6001850151049050808261181e9190612566565b886000015111611863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185a90612d66565b60405180910390fd5b8160016118709190612566565b816001965096509650505050505b9193909250565b606060008267ffffffffffffffff8111156118a3576118a2611dc6565b5b6040519080825280601f01601f1916602001820160405280156118d55781602001600182028036833780820191505090505b5090506000815114156118eb5780915050611984565b600084866118f99190612566565b9050600060208301905060005b6020866119139190612d86565b81101561194f578251825260208361192b9190612566565b925060208261193a9190612566565b915080806119479061251d565b915050611906565b5060006001602087816119655761196461270d565b5b066020036101000a039050808251168119845116178252839450505050505b9392505050565b606061199682611b09565b9050919050565b606081601f836119ad9190612566565b10156119ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e590612e03565b60405180910390fd5b8282846119fb9190612566565b1015611a3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a3390612e03565b60405180910390fd5b8183611a489190612566565b84511015611a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8290612e6f565b60405180910390fd5b6060821560008114611aac5760405191506000825260208201604052611afd565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611aea5780518352602083019250602081019050611acd565b50868552601f19601f8301166040525050505b50809150509392505050565b6060611b1f826020015160008460000151611885565b9050919050565b604051806040016040528060608152602001606081525090565b604051806040016040528060008152602001600081525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611b9f611b9a611b9584611b5a565b611b7a565b611b5a565b9050919050565b6000611bb182611b84565b9050919050565b6000611bc382611ba6565b9050919050565b611bd381611bb8565b82525050565b6000602082019050611bee6000830184611bca565b92915050565b6000611bff82611b5a565b9050919050565b611c0f81611bf4565b82525050565b6000602082019050611c2a6000830184611c06565b92915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b611c5781611c44565b8114611c6257600080fd5b50565b600081359050611c7481611c4e565b92915050565b600060208284031215611c9057611c8f611c3a565b5b6000611c9e84828501611c65565b91505092915050565b60008115159050919050565b611cbc81611ca7565b82525050565b6000602082019050611cd76000830184611cb3565b92915050565b611ce681611bf4565b8114611cf157600080fd5b50565b600081359050611d0381611cdd565b92915050565b6000819050919050565b611d1c81611d09565b8114611d2757600080fd5b50565b600081359050611d3981611d13565b92915050565b600067ffffffffffffffff82169050919050565b611d5c81611d3f565b8114611d6757600080fd5b50565b600081359050611d7981611d53565b92915050565b611d8881611ca7565b8114611d9357600080fd5b50565b600081359050611da581611d7f565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611dfe82611db5565b810181811067ffffffffffffffff82111715611e1d57611e1c611dc6565b5b80604052505050565b6000611e30611c30565b9050611e3c8282611df5565b919050565b600067ffffffffffffffff821115611e5c57611e5b611dc6565b5b611e6582611db5565b9050602081019050919050565b82818337600083830152505050565b6000611e94611e8f84611e41565b611e26565b905082815260208101848484011115611eb057611eaf611db0565b5b611ebb848285611e72565b509392505050565b600082601f830112611ed857611ed7611dab565b5b8135611ee8848260208601611e81565b91505092915050565b600080600080600060a08688031215611f0d57611f0c611c3a565b5b6000611f1b88828901611cf4565b9550506020611f2c88828901611d2a565b9450506040611f3d88828901611d6a565b9350506060611f4e88828901611d96565b925050608086013567ffffffffffffffff811115611f6f57611f6e611c3f565b5b611f7b88828901611ec3565b9150509295509295909350565b600080fd5b600080fd5b60008083601f840112611fa857611fa7611dab565b5b8235905067ffffffffffffffff811115611fc557611fc4611f88565b5b602083019150836001820283011115611fe157611fe0611f8d565b5b9250929050565b600080fd5b60006080828403121561200357612002611fe8565b5b81905092915050565b60008060008060008060008060008060006101808c8e03121561203257612031611c3a565b5b60006120408e828f01611d2a565b9b505060206120518e828f01611cf4565b9a505060406120628e828f01611cf4565b99505060606120738e828f01611d2a565b98505060806120848e828f01611d2a565b97505060a08c013567ffffffffffffffff8111156120a5576120a4611c3f565b5b6120b18e828f01611f92565b965096505060c06120c48e828f01611d2a565b94505060e06120d58e828f01611fed565b9350506101608c013567ffffffffffffffff8111156120f7576120f6611c3f565b5b6121038e828f01611f92565b92509250509295989b509295989b9093969950565b61212181611d09565b82525050565b600060208201905061213c6000830184612118565b92915050565b61214b81611d3f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561218b578082015181840152602081019050612170565b8381111561219a576000848401525b50505050565b60006121ab82612151565b6121b5818561215c565b93506121c581856020860161216d565b6121ce81611db5565b840191505092915050565b600060a0820190506121ee6000830188612118565b6121fb6020830187612118565b6122086040830186612142565b6122156060830185611cb3565b818103608083015261222781846121a0565b90509695505050505050565b60008151905061224281611c4e565b92915050565b60006020828403121561225e5761225d611c3a565b5b600061226c84828501612233565b91505092915050565b600081905092915050565b600061228c8385612275565b9350612299838584611e72565b82840190509392505050565b60006122b2828486612280565b91508190509392505050565b6122c781611c44565b82525050565b60006080820190506122e260008301876122be565b6122ef60208301866122be565b6122fc60408301856122be565b61230960608301846122be565b95945050505050565b600061231e838561215c565b935061232b838584611e72565b61233483611db5565b840190509392505050565b600060c082019050612354600083018a612118565b6123616020830189611c06565b61236e6040830188611c06565b61237b6060830187612118565b6123886080830186612118565b81810360a083015261239b818486612312565b905098975050505050505050565b60006040820190506123be60008301856122be565b6123cb6020830184612118565b9392505050565b6000819050919050565b6123ed6123e882611c44565b6123d2565b82525050565b60006123ff82846123dc565b60208201915081905092915050565b600082825260208201905092915050565b7f50726f76696465642070726f6f6620697320696e76616c69642e000000000000600082015250565b6000612455601a8361240e565b91506124608261241f565b602082019050919050565b6000602082019050818103600083015261248481612448565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006124c582611d09565b91506124d083611d09565b9250828210156124e3576124e261248b565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061252882611d09565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561255b5761255a61248b565b5b600182019050919050565b600061257182611d09565b915061257c83611d09565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b1576125b061248b565b5b828201905092915050565b7f496e76616c696420726f6f742068617368000000000000000000000000000000600082015250565b60006125f260118361240e565b91506125fd826125bc565b602082019050919050565b60006020820190508181036000830152612621816125e5565b9050919050565b7f496e76616c6964206c6172676520696e7465726e616c20686173680000000000600082015250565b600061265e601b8361240e565b915061266982612628565b602082019050919050565b6000602082019050818103600083015261268d81612651565b9050919050565b7f496e76616c696420696e7465726e616c206e6f64652068617368000000000000600082015250565b60006126ca601a8361240e565b91506126d582612694565b602082019050919050565b600060208201905081810360008301526126f9816126bd565b9050919050565b600060ff82169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061274782612700565b915061275283612700565b9250826127625761276161270d565b5b828206905092915050565b600061277882612700565b915061278383612700565b9250828210156127965761279561248b565b5b828203905092915050565b7f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060008201527f7072656669780000000000000000000000000000000000000000000000000000602082015250565b60006127fd60268361240e565b9150612808826127a1565b604082019050919050565b6000602082019050818103600083015261282c816127f0565b9050919050565b7f526563656976656420616e20756e706172736561626c65206e6f64652e000000600082015250565b6000612869601d8361240e565b915061287482612833565b602082019050919050565b600060208201905081810360008301526128988161285c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f496e76616c696420524c502062797465732076616c75652e0000000000000000600082015250565b600061290460188361240e565b915061290f826128ce565b602082019050919050565b60006020820190508181036000830152612933816128f7565b9050919050565b600061294582611d09565b915061295083611d09565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156129895761298861248b565b5b828202905092915050565b7f496e76616c696420524c50206c6973742076616c75652e000000000000000000600082015250565b60006129ca60178361240e565b91506129d582612994565b602082019050919050565b600060208201905081810360008301526129f9816129bd565b9050919050565b7f50726f766964656420524c50206c6973742065786365656473206d6178206c6960008201527f7374206c656e6774682e00000000000000000000000000000000000000000000602082015250565b6000612a5c602a8361240e565b9150612a6782612a00565b604082019050919050565b60006020820190508181036000830152612a8b81612a4f565b9050919050565b7f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000600082015250565b6000612ac860188361240e565b9150612ad382612a92565b602082019050919050565b60006020820190508181036000830152612af781612abb565b9050919050565b7f496e76616c696420524c502073686f727420737472696e672e00000000000000600082015250565b6000612b3460198361240e565b9150612b3f82612afe565b602082019050919050565b60006020820190508181036000830152612b6381612b27565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00600082015250565b6000612ba0601f8361240e565b9150612bab82612b6a565b602082019050919050565b60006020820190508181036000830152612bcf81612b93565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000600082015250565b6000612c0c60188361240e565b9150612c1782612bd6565b602082019050919050565b60006020820190508181036000830152612c3b81612bff565b9050919050565b7f496e76616c696420524c502073686f7274206c6973742e000000000000000000600082015250565b6000612c7860178361240e565b9150612c8382612c42565b602082019050919050565b60006020820190508181036000830152612ca781612c6b565b9050919050565b7f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000600082015250565b6000612ce4601d8361240e565b9150612cef82612cae565b602082019050919050565b60006020820190508181036000830152612d1381612cd7565b9050919050565b7f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000600082015250565b6000612d5060168361240e565b9150612d5b82612d1a565b602082019050919050565b60006020820190508181036000830152612d7f81612d43565b9050919050565b6000612d9182611d09565b9150612d9c83611d09565b925082612dac57612dab61270d565b5b828204905092915050565b7f736c6963655f6f766572666c6f77000000000000000000000000000000000000600082015250565b6000612ded600e8361240e565b9150612df882612db7565b602082019050919050565b60006020820190508181036000830152612e1c81612de0565b9050919050565b7f736c6963655f6f75744f66426f756e6473000000000000000000000000000000600082015250565b6000612e5960118361240e565b9150612e6482612e23565b602082019050919050565b60006020820190508181036000830152612e8881612e4c565b905091905056fea264697066735822122074dee632ac29194e1f1bccf1f4b1d8201f31bbc289f63a71425c41734905a8de64736f6c634300080a0033", } // OptimismPortalABI is the input ABI used to generate the binding from. @@ -2673,24 +2847,24 @@ func (_OptimismPortal *OptimismPortalCallerSession) L2Sender() (common.Address, return _OptimismPortal.Contract.L2Sender(&_OptimismPortal.CallOpts) } -// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. // -// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_OptimismPortal *OptimismPortalTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { return _OptimismPortal.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) } -// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. // -// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_OptimismPortal *OptimismPortalSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) } -// DepositTransaction is a paid mutator transaction binding the contract method 0xfa92670c. +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. // -// Solidity: function depositTransaction(address _to, uint256 _value, uint256 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_OptimismPortal *OptimismPortalTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit *big.Int, _isCreation bool, _data []byte) (*types.Transaction, error) { +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) } @@ -2809,15 +2983,15 @@ type OptimismPortalTransactionDeposited struct { To common.Address Mint *big.Int Value *big.Int - GasLimit *big.Int + GasLimit uint64 IsCreation bool Data []byte Raw types.Log // Blockchain specific contextual infos } -// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. // -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) func (_OptimismPortal *OptimismPortalFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismPortalTransactionDepositedIterator, error) { var fromRule []interface{} @@ -2836,9 +3010,9 @@ func (_OptimismPortal *OptimismPortalFilterer) FilterTransactionDeposited(opts * return &OptimismPortalTransactionDepositedIterator{contract: _OptimismPortal.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil } -// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. // -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) func (_OptimismPortal *OptimismPortalFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *OptimismPortalTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} @@ -2882,9 +3056,9 @@ func (_OptimismPortal *OptimismPortalFilterer) WatchTransactionDeposited(opts *b }), nil } -// ParseTransactionDeposited is a log parse operation binding the contract event 0x26137a5e34446f63aa9ea28797a0e70c3987720913879898802dd60b944615ad. +// ParseTransactionDeposited is a log parse operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. // -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint256 gasLimit, bool isCreation, bytes data) +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) func (_OptimismPortal *OptimismPortalFilterer) ParseTransactionDeposited(log types.Log) (*OptimismPortalTransactionDeposited, error) { event := new(OptimismPortalTransactionDeposited) if err := _OptimismPortal.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { @@ -3418,7 +3592,7 @@ func (_Ownable *OwnableFilterer) ParseOwnershipTransferred(log types.Log) (*Owna // WithdrawalVerifierMetaData contains all meta data concerning the WithdrawalVerifier contract. var WithdrawalVerifierMetaData = &bind.MetaData{ ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212203fefb10a3ca14596cd54a35ac033725fc08679d4c580652ab8e765249653bb8c64736f6c634300080a0033", + Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202eecfa4ab6f0ebc682ef9a192b83bda8737bbea39514d69c0924b2d73c4b1a7564736f6c634300080a0033", } // WithdrawalVerifierABI is the input ABI used to generate the binding from. diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index fdd5df531af5..94cd96e5291a 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -17,7 +17,7 @@ import ( ) var ( - DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint256,bool,bytes)" + DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint64,bool,bytes)" DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) L1InfoFuncSignature = "setL1BlockValues(uint256,uint256,uint256,bytes32)" L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] @@ -70,7 +70,7 @@ func (dep *L1InfoDepositSource) SourceHash() common.Hash { // address indexed to, // uint256 mint, // uint256 value, -// uint256 gasLimit, +// uint64 gasLimit, // bool isCreation, // data data // ); @@ -201,24 +201,26 @@ func L1InfoDeposit(seqNumber uint64, block L1Info, depositContractAddr common.Ad } // UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block -func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]*types.DepositTx, error) { +func UserDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]*types.DepositTx, []error) { var out []*types.DepositTx + var errs []error - for _, rec := range receipts { + for i, rec := range receipts { if rec.Status != types.ReceiptStatusSuccessful { continue } - for _, log := range rec.Logs { + for j, log := range rec.Logs { if log.Address == depositContractAddr && len(log.Topics) > 0 && log.Topics[0] == DepositEventABIHash { dep, err := UnmarshalLogEvent(log) if err != nil { - return nil, fmt.Errorf("malformatted L1 deposit log: %v", err) + errs = append(errs, fmt.Errorf("malformatted L1 deposit log in receipt %d, log %d: %w", i, j, err)) + } else { + out = append(out, dep) } - out = append(out, dep) } } } - return out, nil + return out, errs } func BatchesFromEVMTransactions(config *rollup.Config, txLists []types.Transactions) ([]*BatchData, error) { @@ -341,18 +343,16 @@ func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info, depositContractAddress return opaqueL1Tx, nil } -func DeriveDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]hexutil.Bytes, error) { - userDeposits, err := UserDeposits(receipts, depositContractAddr) - if err != nil { - return nil, fmt.Errorf("failed to derive user deposits: %v", err) - } +func DeriveDeposits(receipts []*types.Receipt, depositContractAddr common.Address) ([]hexutil.Bytes, []error) { + userDeposits, errs := UserDeposits(receipts, depositContractAddr) encodedTxs := make([]hexutil.Bytes, 0, len(userDeposits)) for i, tx := range userDeposits { opaqueTx, err := types.NewTx(tx).MarshalBinary() if err != nil { - return nil, fmt.Errorf("failed to encode user tx %d", i) + errs = append(errs, fmt.Errorf("failed to encode user tx %d", i)) + } else { + encodedTxs = append(encodedTxs, opaqueTx) } - encodedTxs = append(encodedTxs, opaqueTx) } - return encodedTxs, nil + return encodedTxs, errs } diff --git a/opnode/rollup/derive/payload_attributes_test.go b/opnode/rollup/derive/payload_attributes_test.go index e8d632a7f118..7f975fe79125 100644 --- a/opnode/rollup/derive/payload_attributes_test.go +++ b/opnode/rollup/derive/payload_attributes_test.go @@ -204,8 +204,8 @@ func TestDeriveUserDeposits(t *testing.T) { TransactionIndex: uint(txIndex), }) } - got, err := UserDeposits(receipts, MockDepositContractAddr) - assert.NoError(t, err) + got, errs := UserDeposits(receipts, MockDepositContractAddr) + assert.Equal(t, len(errs), 0) assert.Equal(t, len(got), len(expectedDeposits)) for d, depTx := range got { expected := expectedDeposits[d] diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index f2c3e6b8c0bf..ea35fb83ad29 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -89,11 +89,12 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, // Next we append user deposits. If we're not the first block in an epoch, then receipts will // be empty and no deposits will be derived. - deposits, err := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress) + deposits, errs := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress) d.log.Info("Derived deposits", "deposits", deposits, "l2Parent", l2Head, "l1Origin", l1Origin) - if err != nil { - return l2Head, nil, fmt.Errorf("failed to derive deposits: %v", err) + for _, err := range errs { + d.log.Error("Failed to derive a deposit", "l1OriginHash", l1Origin.Hash, "err", err) } + // TODO: Should we halt if len(errs) > 0? Opens up a denial of service attack, but prevents lockup of funds. txns = append(txns, deposits...) // If our next L2 block timestamp is beyond the Sequencer drift threshold, then we must produce @@ -175,10 +176,11 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to get L1 timestamp of next L1 block: %v", err) } - deposits, err := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress) - if err != nil { - return l2Head, l2SafeHead, false, fmt.Errorf("failed to derive deposits: %w", err) + deposits, errs := derive.DeriveDeposits(receipts, d.Config.DepositContractAddress) + for _, err := range errs { + d.log.Error("Failed to derive a deposit", "l1OriginHash", l1Input[0].Hash, "err", err) } + // TODO: Should we halt if len(errs) > 0? Opens up a denial of service attack, but prevents lockup of funds. // TODO: with sharding the blobs may be identified in more detail than L1 block hashes transactions, err := d.dl.FetchAllTransactions(fetchCtx, l1Input) if err != nil { diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index c05988341199..022ead1783fc 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -229,7 +229,7 @@ func TestSystemE2E(t *testing.T) { // Finally send TX mintAmount := big.NewInt(1_000_000_000_000) opts.Value = mintAmount - tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, big.NewInt(1_000_000), false, nil) + tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, 1_000_000, false, nil) require.Nil(t, err, "with deposit tx") receipt, err := waitForTransaction(tx.Hash(), l1Client, 6*time.Second) @@ -317,7 +317,7 @@ func TestMintOnRevertedDeposit(t *testing.T) { mintAmount := big.NewInt(9_000_000) opts.Value = mintAmount value := new(big.Int).Mul(common.Big2, startBalance) // trigger a revert by transferring more than we have available - tx, err := depositContract.DepositTransaction(opts, toAddr, value, big.NewInt(1_000_000), false, nil) + tx, err := depositContract.DepositTransaction(opts, toAddr, value, 1_000_000, false, nil) require.Nil(t, err, "with deposit tx") receipt, err := waitForTransaction(tx.Hash(), l1Client, 6*time.Second) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 3e62a7dabab6..836fc891f77f 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,12 +1,12 @@ -DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11233) -DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 20962) -DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 21427) -DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 20980) -DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 21467) -DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 28003) -DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 25031) -DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 27671) -DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 28407) +DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11325) +DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 21066) +DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 21531) +DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 21084) +DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 21571) +DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 28107) +DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 25135) +DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 27775) +DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 28511) L1BLockTest:test_basefee() (gas: 7509) L1BLockTest:test_hash() (gas: 7508) L1BLockTest:test_number() (gas: 7509) @@ -26,7 +26,7 @@ L2OutputOracleTest:test_getL2Output() (gas: 15093) L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9654) L2OutputOracleTest:test_nextTimestamp() (gas: 12009) L2OutputOracleTest_Constructor:test_constructor() (gas: 29100) -OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24183) +OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24189) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43987) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200132) diff --git a/packages/contracts/contracts/L1/abstracts/DepositFeed.sol b/packages/contracts/contracts/L1/abstracts/DepositFeed.sol index edce3e067122..e88d91f2bf80 100644 --- a/packages/contracts/contracts/L1/abstracts/DepositFeed.sol +++ b/packages/contracts/contracts/L1/abstracts/DepositFeed.sol @@ -33,7 +33,7 @@ abstract contract DepositFeed { address indexed to, uint256 mint, uint256 value, - uint256 gasLimit, + uint64 gasLimit, bool isCreation, bytes data ); @@ -54,7 +54,7 @@ abstract contract DepositFeed { function depositTransaction( address _to, uint256 _value, - uint256 _gasLimit, + uint64 _gasLimit, bool _isCreation, bytes memory _data ) public payable { diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol index 5d1fcc467217..f11c2dbc333e 100644 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -21,7 +21,7 @@ contract DepositFeedTest is DSTest { address immutable NON_ZERO_ADDRESS = address(1); uint256 immutable NON_ZERO_VALUE = 100; uint256 immutable ZERO_VALUE = 0; - uint256 immutable NON_ZERO_GASLIMIT = 50000; + uint64 immutable NON_ZERO_GASLIMIT = 50000; bytes NON_ZERO_DATA = hex"1111"; Target df; @@ -31,7 +31,7 @@ contract DepositFeedTest is DSTest { address indexed to, uint256 mint, uint256 value, - uint256 gasLimit, + uint64 gasLimit, bool isCreation, bytes data ); diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index fbcbdedddd69..1ac4fbc5fdd9 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -17,7 +17,7 @@ contract OptimismPortal_Test is DSTest { address indexed to, uint256 mint, uint256 value, - uint256 gasLimit, + uint64 gasLimit, bool isCreation, bytes data ); diff --git a/packages/integration-tests/contracts/MultiDepositor.sol b/packages/integration-tests/contracts/MultiDepositor.sol index cad7ebcab43f..3643faeca6d6 100644 --- a/packages/integration-tests/contracts/MultiDepositor.sol +++ b/packages/integration-tests/contracts/MultiDepositor.sol @@ -4,7 +4,7 @@ interface DepositFeed { function depositTransaction( address _to, uint256 _value, - uint256 _gasLimit, + uint64 _gasLimit, bool _isCreation, bytes memory _data ) external payable; diff --git a/specs/deposits.md b/specs/deposits.md index b0fa19f26ac7..1b51e4f17e10 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -63,7 +63,7 @@ fields (rlp encoded in the order they appear here): - `uint256 mint`: The ETH value to mint on L2. - `uint256 value`: The ETH value to send to the recipient account. - `bytes data`: The input data. -- `uint256 gasLimit`: The gasLimit for the L2 transaction. +- `uint64 gasLimit`: The gasLimit for the L2 transaction. In contrast to [EIP-155] transactions, this transaction type does not include signature information, and makes the `from` address explicit. From b93465a25a8eebc84db156d1a40d8173d138e43a Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Wed, 27 Apr 2022 13:37:21 -0700 Subject: [PATCH 502/585] opnode/test: Provide flag to access geth logs (#389) This enables a more verbose output without having to modify the test itself. Provide the flag `gethlogs` to see logs from geth. --- opnode/test/system_test.go | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 022ead1783fc..ce426032069c 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -2,6 +2,7 @@ package test import ( "context" + "flag" "fmt" "math/big" "testing" @@ -27,6 +28,19 @@ import ( "github.com/stretchr/testify/require" ) +// Init testing to enable test flags +var _ = func() bool { + testing.Init() + return true +}() + +var verboseGethNodes bool + +func init() { + flag.BoolVar(&verboseGethNodes, "gethlogs", false, "Enable logs on geth nodes") + flag.Parse() +} + // Temporary until the contract is deployed properly instead of as a pre-deploy to a specific address var MockDepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") @@ -101,7 +115,9 @@ func defaultSystemConfig(t *testing.T) SystemConfig { } func TestL2OutputSubmitter(t *testing.T) { - log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } cfg := defaultSystemConfig(t) @@ -188,8 +204,9 @@ func TestL2OutputSubmitter(t *testing.T) { // TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. // All nodes are run in process (but are the full nodes, not mocked or stubbed). func TestSystemE2E(t *testing.T) { - log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs - + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } cfg := defaultSystemConfig(t) sys, err := cfg.start() @@ -281,8 +298,9 @@ func TestSystemE2E(t *testing.T) { } func TestMintOnRevertedDeposit(t *testing.T) { - log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs - + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } cfg := defaultSystemConfig(t) sys, err := cfg.start() @@ -353,8 +371,9 @@ func TestMintOnRevertedDeposit(t *testing.T) { } func TestMissingBatchE2E(t *testing.T) { - log.Root().SetHandler(log.DiscardHandler()) // Comment this out to see geth l1/l2 logs - + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } cfg := defaultSystemConfig(t) // Specifically set batch submitter balance to stop batches from being included cfg.Premine[bssHDPath] = 0 From cc7c5ce88d9f3232ca07e433c07ca702483b12ee Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 25 Apr 2022 11:55:11 -0700 Subject: [PATCH 503/585] opnode: Fix L1 Info Transactions There are three issues being fixed: 1. Set the `from` field to the correct magic value (found by ToB) 2. Update the L2 EE to provide gas to deposits. Otherwise the deposit transactions immediatley out of gas and fail. 3. Update the manual ABI encoding to match what solidity expects. The previous version was similar to packed encodeding, but as such could not be parsed by solidity. This also includes a regression test that the parsing of the L1 info tx and what is recorded in the state for each block matches. --- go.mod | 4 +- go.sum | 4 +- opnode/rollup/derive/invert.go | 56 +++++++-- opnode/rollup/derive/invert_test.go | 4 +- opnode/rollup/derive/payload_attributes.go | 29 ++--- opnode/rollup/driver/step.go | 4 +- opnode/test/system_test.go | 137 +++++++++++++++++++++ 7 files changed, 204 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index 14155f97dbec..16b5255d6120 100644 --- a/go.mod +++ b/go.mod @@ -165,7 +165,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8 +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead // For local debugging: -//replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum +// replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/go.sum b/go.sum index eab315cdc38e..fac6b1cd82c9 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8 h1:GrJtCdIozmrjTDrt/4PLwtVMkF3xYtgVVfnJb14gm+Y= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220411203319-ad60590374c8/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead h1:AiLggtwXHmAGxNusOEH7edb83TtJnavtR2uY1z6YzYc= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= 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= diff --git a/opnode/rollup/derive/invert.go b/opnode/rollup/derive/invert.go index fecae3e575ee..1b69bcfdc8d0 100644 --- a/opnode/rollup/derive/invert.go +++ b/opnode/rollup/derive/invert.go @@ -1,26 +1,58 @@ package derive import ( - "encoding/binary" + "errors" "fmt" "math/big" "github.com/ethereum/go-ethereum/common" ) +// setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) +type L1BlockInfo struct { + Number uint64 + Time uint64 + BaseFee *big.Int + BlockHash common.Hash +} + // L1InfoDepositTxData is the inverse of L1InfoDeposit, to see where the L2 chain is derived from func L1InfoDepositTxData(data []byte) (nr uint64, time uint64, baseFee *big.Int, blockHash common.Hash, err error) { - if len(data) != 4+8+8+32+32 { - err = fmt.Errorf("data is unexpected length: %d", len(data)) - return + info, err := L1InfoDepositTxDataToStruct(data) + return info.Number, info.Time, info.BaseFee, info.BlockHash, err +} + +// L1InfoDepositTxDataToStruct is the inverse of L1InfoDeposit, to see where the L2 chain is derived from +func L1InfoDepositTxDataToStruct(data []byte) (L1BlockInfo, error) { + out := L1BlockInfo{} + if len(data) != 4+32+32+32+32 { + return out, fmt.Errorf("data is unexpected length: %d", len(data)) + } + + // Number + offset := 4 // Selector hash. Should check + number := new(big.Int) + number.SetBytes(data[offset : offset+32]) + if !number.IsUint64() { + return L1BlockInfo{}, errors.New("number does not fit in uint64") } - offset := 4 - nr = binary.BigEndian.Uint64(data[offset : offset+8]) - offset += 8 - time = binary.BigEndian.Uint64(data[offset : offset+8]) - offset += 8 - baseFee = new(big.Int).SetBytes(data[offset : offset+32]) + out.Number = number.Uint64() + + // Timestamp + offset += 32 + timestamp := new(big.Int) + timestamp.SetBytes(data[offset : offset+32]) + if !timestamp.IsUint64() { + return L1BlockInfo{}, errors.New("timestamp does not fit in uint64") + } + out.Time = timestamp.Uint64() + + // BaseFee + offset += 32 + out.BaseFee = new(big.Int).SetBytes(data[offset : offset+32]) + + // Hash offset += 32 - blockHash.SetBytes(data[offset : offset+32]) - return + out.BlockHash.SetBytes(data[offset : offset+32]) + return out, nil } diff --git a/opnode/rollup/derive/invert_test.go b/opnode/rollup/derive/invert_test.go index 8da007d01507..9913da99c8d2 100644 --- a/opnode/rollup/derive/invert_test.go +++ b/opnode/rollup/derive/invert_test.go @@ -103,7 +103,7 @@ type infoTest struct { mkInfo func(rng *rand.Rand) *l1MockInfo } -var MockDepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") +var MockDepositContractAddr = common.HexToAddress("0xdeadbeefdeadbeefdeadbeefdeadbeef00000000") func TestParseL1InfoDepositTxData(t *testing.T) { // Go 1.18 will have native fuzzing for us to use, until then, we cover just the below cases @@ -125,7 +125,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { for i, testCase := range cases { t.Run(testCase.name, func(t *testing.T) { info := testCase.mkInfo(rand.New(rand.NewSource(int64(1234 + i)))) - depTx := L1InfoDeposit(123, info, MockDepositContractAddr) + depTx := L1InfoDeposit(123, info) nr, time, baseFee, h, err := L1InfoDepositTxData(depTx.Data) assert.NoError(t, err, "expected valid deposit info") assert.Equal(t, nr, info.num) diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 94cd96e5291a..391dced298f0 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -17,11 +17,12 @@ import ( ) var ( - DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint64,bool,bytes)" - DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) - L1InfoFuncSignature = "setL1BlockValues(uint256,uint256,uint256,bytes32)" - L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] - L1InfoPredeployAddr = common.HexToAddress("0x4200000000000000000000000000000000000015") + DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint64,bool,bytes)" + DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) + L1InfoFuncSignature = "setL1BlockValues(uint256,uint256,uint256,bytes32)" + L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] + L1InfoPredeployAddr = common.HexToAddress("0x4200000000000000000000000000000000000015") + L1InfoDepositerAddress = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") ) type UserDepositSource struct { @@ -171,15 +172,15 @@ type L1Info interface { // L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block, // and the L2 block-height difference with the start of the epoch. -func L1InfoDeposit(seqNumber uint64, block L1Info, depositContractAddr common.Address) *types.DepositTx { - data := make([]byte, 4+8+8+32+32) +func L1InfoDeposit(seqNumber uint64, block L1Info) *types.DepositTx { + data := make([]byte, 4+32+32+32+32) offset := 0 copy(data[offset:4], L1InfoFuncBytes4) offset += 4 - binary.BigEndian.PutUint64(data[offset:offset+8], block.NumberU64()) - offset += 8 - binary.BigEndian.PutUint64(data[offset:offset+8], block.Time()) - offset += 8 + binary.BigEndian.PutUint64(data[offset+24:offset+32], block.NumberU64()) + offset += 32 + binary.BigEndian.PutUint64(data[offset+24:offset+32], block.Time()) + offset += 32 block.BaseFee().FillBytes(data[offset : offset+32]) offset += 32 copy(data[offset:offset+32], block.Hash().Bytes()) @@ -191,7 +192,7 @@ func L1InfoDeposit(seqNumber uint64, block L1Info, depositContractAddr common.Ad return &types.DepositTx{ SourceHash: source.SourceHash(), - From: depositContractAddr, + From: L1InfoDepositerAddress, To: &L1InfoPredeployAddr, Mint: nil, Value: big.NewInt(0), @@ -334,8 +335,8 @@ func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, nextL } // L1InfoDepositBytes returns a serialized L1-info attributes transaction. -func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info, depositContractAddress common.Address) (hexutil.Bytes, error) { - l1Tx := types.NewTx(L1InfoDeposit(seqNumber, l1Info, depositContractAddress)) +func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info) (hexutil.Bytes, error) { + l1Tx := types.NewTx(L1InfoDeposit(seqNumber, l1Info)) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { return nil, fmt.Errorf("failed to encode L1 info tx") diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index ea35fb83ad29..85c153448a56 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -81,7 +81,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, // First transaction in every block is always the L1 info transaction. seqNumber := l2Head.Number + 1 - l2SafeHead.Number - l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info, d.Config.DepositContractAddress) + l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info) if err != nil { return l2Head, nil, err } @@ -212,7 +212,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S var reorg bool for i, batch := range batches { var txns []l2.Data - l1InfoTx, err := derive.L1InfoDepositBytes(uint64(i), l1Info, d.Config.DepositContractAddress) + l1InfoTx, err := derive.L1InfoDepositBytes(uint64(i), l1Info) if err != nil { return l2Head, l2SafeHead, false, fmt.Errorf("failed to create l1InfoTx: %w", err) } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index ce426032069c..d57ed3ee6c80 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -2,6 +2,7 @@ package test import ( "context" + "errors" "flag" "fmt" "math/big" @@ -12,6 +13,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" @@ -23,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" @@ -288,6 +291,7 @@ func TestSystemE2E(t *testing.T) { receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Second) require.Nil(t, err, "Waiting for L2 tx on verifier") + require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded") // Verify blocks match after batch submission on verifiers and sequencers verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber) @@ -432,3 +436,136 @@ func TestMissingBatchE2E(t *testing.T) { require.Nil(t, err, "Get block from sequencer") require.NotEqual(t, block.Hash(), receipt.BlockHash, "L2 Sequencer did not reorg out transaction on it's safe chain") } + +func L1InfoFromState(ctx context.Context, contract *l1block.L1Block, l2Number *big.Int) (derive.L1BlockInfo, error) { + var err error + var out derive.L1BlockInfo + opts := bind.CallOpts{ + BlockNumber: l2Number, + Context: ctx, + } + + number, err := contract.Number(&opts) + if err != nil { + return derive.L1BlockInfo{}, fmt.Errorf("failed to get number: %w", err) + } + if !number.IsUint64() { + return derive.L1BlockInfo{}, errors.New("number does not fit in a uint64") + + } + out.Number = number.Uint64() + + time, err := contract.Timestamp(&opts) + if err != nil { + return derive.L1BlockInfo{}, fmt.Errorf("failed to get timestamp: %w", err) + } + if !time.IsUint64() { + return derive.L1BlockInfo{}, errors.New("time does not fit in a uint64") + + } + out.Time = time.Uint64() + + out.BaseFee, err = contract.Basefee(&opts) + if err != nil { + return derive.L1BlockInfo{}, fmt.Errorf("failed to get timestamp: %w", err) + } + + blockHashBytes, err := contract.Hash(&opts) + if err != nil { + return derive.L1BlockInfo{}, fmt.Errorf("failed to get block hash: %w", err) + } + out.BlockHash = common.BytesToHash(blockHashBytes[:]) + + return out, nil +} + +func TestL1InfoContract(t *testing.T) { + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } + + cfg := defaultSystemConfig(t) + + sys, err := cfg.start() + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + l2Seq := sys.Clients["sequencer"] + l2Verif := sys.Clients["verifier"] + + endVerifBlockNumber := big.NewInt(4) + endSeqBlockNumber := big.NewInt(6) + endVerifBlock, err := waitForBlock(endVerifBlockNumber, l2Verif, time.Minute) + require.Nil(t, err) + endSeqBlock, err := waitForBlock(endSeqBlockNumber, l2Seq, time.Minute) + require.Nil(t, err) + + seqL1Info, err := l1block.NewL1Block(cfg.L1InfoPredeployAddress, l2Seq) + require.Nil(t, err) + + verifL1Info, err := l1block.NewL1Block(cfg.L1InfoPredeployAddress, l2Verif) + require.Nil(t, err) + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + + fillInfoLists := func(start *types.Block, contract *l1block.L1Block, client *ethclient.Client) ([]derive.L1BlockInfo, []derive.L1BlockInfo) { + var txList, stateList []derive.L1BlockInfo + for b := start; ; { + infoFromTx, err := derive.L1InfoDepositTxDataToStruct(b.Transactions()[0].Data()) + require.Nil(t, err) + txList = append(txList, infoFromTx) + + infoFromState, err := L1InfoFromState(ctx, contract, b.Number()) + require.Nil(t, err) + stateList = append(stateList, infoFromState) + + // Genesis L2 block contains no L1 Deposit TX + if b.NumberU64() == 1 { + return txList, stateList + } + b, err = client.BlockByHash(ctx, b.ParentHash()) + require.Nil(t, err) + } + } + + l1InfosFromSequencerTransactions, l1InfosFromSequencerState := fillInfoLists(endSeqBlock, seqL1Info, l2Seq) + l1InfosFromVerifierTransactions, l1InfosFromVerifierState := fillInfoLists(endVerifBlock, verifL1Info, l2Verif) + + l1blocks := make(map[common.Hash]derive.L1BlockInfo) + maxL1Hash := l1InfosFromSequencerTransactions[0].BlockHash + for h := maxL1Hash; ; { + b, err := l1Client.BlockByHash(ctx, h) + require.Nil(t, err) + + l1blocks[h] = derive.L1BlockInfo{ + Number: b.NumberU64(), + Time: b.Time(), + BaseFee: b.BaseFee(), + BlockHash: h, + } + + h = b.ParentHash() + if b.NumberU64() == 0 { + break + } + } + + checkInfoList := func(name string, list []derive.L1BlockInfo) { + for _, info := range list { + if expected, ok := l1blocks[info.BlockHash]; ok { + require.Equal(t, expected, info) + } else { + + t.Fatalf("Did not find block hash for L1 Info: %v in test %s", info, name) + } + } + } + + checkInfoList("On sequencer with tx", l1InfosFromSequencerTransactions) + checkInfoList("On sequencer with state", l1InfosFromSequencerState) + checkInfoList("On verifier with tx", l1InfosFromVerifierTransactions) + checkInfoList("On verifier with state", l1InfosFromVerifierState) + +} From 0c054885a6fd2011503784464da1e94997251fe3 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Fri, 29 Apr 2022 17:17:29 -0700 Subject: [PATCH 504/585] contracts: import messengers (#393) * chore: copy L1 and L2 Messengers from Monorepo * test: Add Messenger test files Monorepo test cases are copied in as comments from the monorepo ts tests. * chore: Add OZ upgradable contracts New remappings were also added in order to avoid excessively long import statements. * chore: Importe OZ and OP contracts as node_modules Necessary because hardhat does not support remappings!?! y u no? * refactor: Remove replayMessage() We no longer need this function as it was only necessary when the CTC a maximum gas limit per epoch concept. In order to remove the function I had to copy in the L1xDM interface rather than import from the node_modules. * chore: Remove unused files The ts test file is made redundant by an itest in the itest package. The sol test file was not being used for anything * refactor: Remove Address Manager and Resolver Instead the CTC and SCC are state variables * refactor: Replace CTC with OptimismPortal * refactor: Remove SCC We don't need to replace it with the L2OutputOracle in the L1xDM, because the verification is now done in the OptimismPortal itself. * forge install: forge-std * forge install: ds-test * refactor: Move boilerplate test code into CommonTest * test: Add sendMessage and pause tests for L1xDM * test: L1CrossDomainMessenger sendMessage and pause * refactor: replace L2ToL1MessagePasser with Withdrawer contract Also adds a lib with constant values for new bedrock predeploys. * chore: Make functions external, and reorder for CEI For whatever reason a bunch of functions on the messengers were public, when they could have been external. I fixed that, and removed the slither annotations. Where possible (in the sendMessage functions), I also reordered the events and calls to respect Checks-Effects-Interactions. There was no risk previously, but this removes any question, and quiets slither. * refactor: Reorganize ts helpers Move helpers/index into utils.ts, and add other files which are exported in the new index.ts. * test: Add mock proof generation script and helpers * test: Add L1xDM relayMessageSucceeds tests * test: Add proof generation scripts and helpers * refactor: Add l2Sender check in L2xDM * refactor: Copy in the L1 and L2 standard bridge At this point they are simply verbatim. * refactor: Bridges - fix import paths * refactor: Token Bridge - replace messengers with Portal Also remove the CrossDomainEnabled lib. refactor: Token Bridge - replace messengers with Portal Also remove the CrossDomainEnabled lib. * style: Address/remove some slither disable comments style: Address/remove some slither disable comments * refactor: extract l2Sender check into a modifier * refactor: Support deposits of ETH in L2 Bridge This copies in the IL2ERC20Bridge interface so that payable can be added. In the case that the L2 token address matches OVM_ETH, the value of the call will be forwarded. * interface: add IWithdrawer.sol * contracts: add comments to L1 contracts * contracts: use unchecked * contracts: fix imports in common test * test: L1CrossDomainMessenger * test: L2CrossDomainMessenger * contracts: fix typo * tests: bridge tests * contracts: remove extra message assignment * contracts: update gas snapshot * forge install: solmate * contracts: remove usage of OVM_ETH All `OVM_ETH` will be migrated to `ETH` with the upgrade to bedrock. We do not want to allow for the creation of new `OVM_ETH` by depositing `ETH` into the bridge and have it create `OVM_ETH` on L2. * contracts: add in L2StandardERC20 * contracts: add in token factory The token factory will deploy tokens on L2 that correspond to tokens on L1. This allows for easy deposits through the bridge. * contracts: test rlp lib for computing contract addrs This library lets you compute the contract address based on the deployment account and nonce. h/t @t11s * contracts: test infra for bridge * contracts: add note to self * contracts: fix compiler warnings * contracts: update snapshot * contracts: add IDepositFeed * contracts: type cast uint256 to uint64 in messenger * test: fix merge * contracts: modify paths to compile with hardhat * hardhat: update config * contracts: fix build * forge tests: first yarn install * contracts: lint * contracts: update snapshot Co-authored-by: Maurelian --- .github/workflows/solidity-ci.yml | 3 + .gitmodules | 14 +- packages/contracts/.gas-snapshot | 75 ++- .../contracts/contracts/L1/L2OutputOracle.sol | 2 +- .../contracts/L1/abstracts/DepositFeed.sol | 8 +- .../contracts/L1/abstracts/IDepositFeed.sol | 11 + .../L1/abstracts/WithdrawalsRelay.sol | 2 + .../L1/messaging/IL1CrossDomainMessenger.sol | 45 ++ .../L1/messaging/L1CrossDomainMessenger.sol | 262 ++++++++ .../L1/messaging/L1StandardBridge.sol | 272 ++++++++ .../contracts/contracts/L2/IWithdrawer.sol | 25 + .../contracts/contracts/L2/Withdrawer.sol | 7 +- .../contracts/L2/messaging/IL2ERC20Bridge.sol | 108 ++++ .../L2/messaging/IL2StandardTokenFactory.sol | 11 + .../L2/messaging/L2CrossDomainMessenger.sol | 175 +++++ .../L2/messaging/L2StandardBridge.sol | 191 ++++++ .../L2/messaging/L2StandardTokenFactory.sol | 40 ++ .../contracts/L2/tokens/IL2StandardERC20.sol | 18 + .../contracts/L2/tokens/L2StandardERC20.sol | 56 ++ .../Lib_BedrockPredeployAddresses.sol | 10 + .../libraries/Lib_WithdrawalVerifier.sol | 2 +- .../contracts/contracts/test/CommonTest.t.sol | 17 + .../contracts/test/DepositFeed.t.sol | 14 +- .../contracts/contracts/test/L1Block.t.sol | 4 +- .../test/L1CrossDomainMessenger.t.sol | 318 +++++++++ .../contracts/test/L1StandardBridge.t.sol | 102 +++ .../test/L2CrossDomainMessenger.t.sol | 205 ++++++ .../contracts/test/L2OutputOracle.t.sol | 9 +- .../contracts/test/L2StandardBridge.t.sol | 83 +++ .../contracts/contracts/test/Lib_RLP.t.sol | 28 + .../contracts/test/OptimismPortal.t.sol | 9 +- .../test/TestLib_SecureMerkleTrie.sol | 46 -- .../contracts/test/WithdrawalsRelay.t.sol | 56 +- .../contracts/contracts/test/Withdrawer.t.sol | 10 +- packages/contracts/foundry.toml | 5 + packages/contracts/hardhat.config.ts | 13 +- packages/contracts/helpers/constants.ts | 8 + packages/contracts/helpers/generateProofs.ts | 101 +++ packages/contracts/helpers/index.ts | 219 +------ .../contracts/helpers/trie-test-generator.ts | 261 ++++++++ packages/contracts/helpers/utils.ts | 216 +++++++ packages/contracts/lib/ds-test | 1 - packages/contracts/lib/forge-std | 2 +- packages/contracts/lib/openzeppelin-contracts | 1 - packages/contracts/lib/optimism | 1 - packages/contracts/lib/solmate | 1 + packages/contracts/package.json | 4 + packages/contracts/scripts/ffiMakeProof.ts | 18 + packages/contracts/scripts/makeProof.ts | 21 + packages/contracts/test/withdrawer.spec.ts | 213 ------ packages/contracts/yarn.lock | 612 ++++++++++++++++-- 51 files changed, 3300 insertions(+), 635 deletions(-) create mode 100644 packages/contracts/contracts/L1/abstracts/IDepositFeed.sol create mode 100644 packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol create mode 100644 packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol create mode 100644 packages/contracts/contracts/L1/messaging/L1StandardBridge.sol create mode 100644 packages/contracts/contracts/L2/IWithdrawer.sol create mode 100644 packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol create mode 100644 packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol create mode 100644 packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol create mode 100644 packages/contracts/contracts/L2/messaging/L2StandardBridge.sol create mode 100644 packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol create mode 100644 packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol create mode 100644 packages/contracts/contracts/L2/tokens/L2StandardERC20.sol create mode 100644 packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol create mode 100644 packages/contracts/contracts/test/CommonTest.t.sol create mode 100644 packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol create mode 100644 packages/contracts/contracts/test/L1StandardBridge.t.sol create mode 100644 packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol create mode 100644 packages/contracts/contracts/test/L2StandardBridge.t.sol create mode 100644 packages/contracts/contracts/test/Lib_RLP.t.sol delete mode 100644 packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol create mode 100644 packages/contracts/helpers/constants.ts create mode 100644 packages/contracts/helpers/generateProofs.ts create mode 100644 packages/contracts/helpers/trie-test-generator.ts create mode 100644 packages/contracts/helpers/utils.ts delete mode 160000 packages/contracts/lib/ds-test delete mode 160000 packages/contracts/lib/openzeppelin-contracts delete mode 160000 packages/contracts/lib/optimism create mode 160000 packages/contracts/lib/solmate create mode 100644 packages/contracts/scripts/ffiMakeProof.ts create mode 100644 packages/contracts/scripts/makeProof.ts delete mode 100644 packages/contracts/test/withdrawer.spec.ts diff --git a/.github/workflows/solidity-ci.yml b/.github/workflows/solidity-ci.yml index b771e73b5faf..4feac712241b 100644 --- a/.github/workflows/solidity-ci.yml +++ b/.github/workflows/solidity-ci.yml @@ -48,6 +48,9 @@ jobs: with: version: nightly + - name: Install deps + run: yarn install + - name: Build with Forge run: yarn build:forge diff --git a/.gitmodules b/.gitmodules index f38688f818ba..ade85d7b22f1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,6 @@ -[submodule "packages/contracts/lib/ds-test"] - path = packages/contracts/lib/ds-test - url = https://github.com/dapphub/ds-test -[submodule "packages/contracts/lib/openzeppelin-contracts"] - path = packages/contracts/lib/openzeppelin-contracts - url = https://github.com/openzeppelin/openzeppelin-contracts [submodule "packages/contracts/lib/forge-std"] path = packages/contracts/lib/forge-std - url = https://github.com/brockelmore/forge-std -[submodule "packages/contracts/lib/optimism"] - path = packages/contracts/lib/optimism - url = https://github.com/ethereum-optimism/optimism + url = https://github.com/foundry-rs/forge-std +[submodule "packages/contracts/lib/solmate"] + path = packages/contracts/lib/solmate + url = https://github.com/rari-capital/solmate diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 836fc891f77f..28cf87783984 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,35 +1,60 @@ -DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11325) -DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 21066) -DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 21531) -DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 21084) -DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 21571) -DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 28107) +DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11345) +DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 26479) +DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 26944) +DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 26497) +DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 26984) +DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 33520) DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 25135) -DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 27775) -DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 28511) +DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 33188) +DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 33924) L1BLockTest:test_basefee() (gas: 7509) L1BLockTest:test_hash() (gas: 7508) L1BLockTest:test_number() (gas: 7509) L1BLockTest:test_timestamp() (gas: 7463) -L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20880) -L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19077) -L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 21023) -L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18306) -L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21226) -L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13134) -L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18381) -L2OutputOracleTest:testCannot_deleteL2Output_ifWrongOutput() (gas: 25541) -L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49539) -L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14981) -L2OutputOracleTest:test_deleteL2Output() (gas: 32908) +L1CrossDomainMessenger_Test:testCannot_pause() (gas: 13061) +L1CrossDomainMessenger_Test:test_blockAndUnblockSuccessfulMessage() (gas: 108194) +L1CrossDomainMessenger_Test:test_pause() (gas: 31719) +L1CrossDomainMessenger_Test:test_relayMessageBlockingAuth() (gas: 20956) +L1CrossDomainMessenger_Test:test_relayMessageInsideFraudProofWindow() (gas: 14531) +L1CrossDomainMessenger_Test:test_relayMessageSucceeds() (gas: 84960) +L1CrossDomainMessenger_Test:test_relayMessageToSystemContract() (gas: 32472) +L1CrossDomainMessenger_Test:test_relayRevertOnBlockedMessage() (gas: 58192) +L1CrossDomainMessenger_Test:test_relayShouldRevertIfPaused() (gas: 43739) +L1CrossDomainMessenger_Test:test_relayShouldRevertSendingSameMessageTwice() (gas: 210) +L1CrossDomainMessenger_Test:test_revertOnInvalidOutputRootProof() (gas: 18192) +L1CrossDomainMessenger_Test:test_sendMessage() (gas: 46192) +L1CrossDomainMessenger_Test:test_sendMessageTwice() (gas: 49016) +L1CrossDomainMessenger_Test:test_xDomainMessageSenderResets() (gas: 83962) +L1StandardBridge_Test:test_L1BridgeSetsPortalAndL2Bridge() (gas: 14780) +L2CrossDomainMessenger_Test:test_L2MessengerCallsTarget() (gas: 66275) +L2CrossDomainMessenger_Test:test_L2MessengerCannotCallL2MessagePasser() (gas: 44127) +L2CrossDomainMessenger_Test:test_L2MessengerCannotRelaySameMessageTwice() (gas: 69883) +L2CrossDomainMessenger_Test:test_L2MessengerCorrectL1Messenger() (gas: 9688) +L2CrossDomainMessenger_Test:test_L2MessengerRevertInvalidL1XDomainMessenger() (gas: 13781) +L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 124835) +L2CrossDomainMessenger_Test:test_L2MessengerSendSameMessageTwice() (gas: 162907) +L2CrossDomainMessenger_Test:test_L2MessengerXDomainMessageSenderReset() (gas: 71843) +L2CrossDomainMessenger_Test:test_L2MessengerxDomainMsgSender() (gas: 13320) +L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20865) +L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19041) +L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 21020) +L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18309) +L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21223) +L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13139) +L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18390) +L2OutputOracleTest:testCannot_deleteL2Output_ifWrongOutput() (gas: 25529) +L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49533) +L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14972) +L2OutputOracleTest:test_deleteL2Output() (gas: 32896) L2OutputOracleTest:test_getL2Output() (gas: 15093) -L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9654) -L2OutputOracleTest:test_nextTimestamp() (gas: 12009) -L2OutputOracleTest_Constructor:test_constructor() (gas: 29100) +L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9669) +L2OutputOracleTest:test_nextTimestamp() (gas: 12024) +L2OutputOracleTest_Constructor:test_constructor() (gas: 29190) +L2StandardBridge_Test:test_L2BridgeCorrectL1Bridge() (gas: 9629) OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24189) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 43987) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 39686) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 200132) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 39599) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 35297) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 192101) WithdawerBurnTest:test_burn() (gas: 50276) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 72023) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72488) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index 8121d0e51284..d1bb474a9f26 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.10; /* Library Imports */ -import { Ownable } from "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title L2OutputOracle diff --git a/packages/contracts/contracts/L1/abstracts/DepositFeed.sol b/packages/contracts/contracts/L1/abstracts/DepositFeed.sol index e88d91f2bf80..46b040d09f49 100644 --- a/packages/contracts/contracts/L1/abstracts/DepositFeed.sol +++ b/packages/contracts/contracts/L1/abstracts/DepositFeed.sol @@ -1,16 +1,16 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +import { IDepositFeed } from "./IDepositFeed.sol"; + /* Library Imports */ -import { - AddressAliasHelper -} from "../../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; /** * @title DepositFeed * @notice Implements the logic for depositing from L1 to L2. */ -abstract contract DepositFeed { +abstract contract DepositFeed is IDepositFeed { /********** * Errors * **********/ diff --git a/packages/contracts/contracts/L1/abstracts/IDepositFeed.sol b/packages/contracts/contracts/L1/abstracts/IDepositFeed.sol new file mode 100644 index 000000000000..e61662a3a336 --- /dev/null +++ b/packages/contracts/contracts/L1/abstracts/IDepositFeed.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.8.10; + +interface IDepositFeed { + function depositTransaction( + address _to, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) external payable; +} diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol index 179a52e2c031..22309967b75d 100644 --- a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol +++ b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol @@ -99,6 +99,8 @@ abstract contract WithdrawalsRelay { bytes calldata _withdrawalProof ) external { // Check that the timestamp is sufficiently finalized. + // The timestamp corresponds to a particular L2 output, + // so it is safe to be passed in by a user. unchecked { if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { revert NotYetFinal(); diff --git a/packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol b/packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol new file mode 100644 index 000000000000..b3ef8e0c578d --- /dev/null +++ b/packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Library Imports */ +import { Lib_OVMCodec } from "@eth-optimism/contracts/libraries/codec/Lib_OVMCodec.sol"; + +/* Interface Imports */ +import { + ICrossDomainMessenger +} from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol"; + +/** + * @title IL1CrossDomainMessenger + */ +interface IL1CrossDomainMessenger is ICrossDomainMessenger { + /******************* + * Data Structures * + *******************/ + + struct L2MessageInclusionProof { + bytes32 stateRoot; + Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader; + Lib_OVMCodec.ChainInclusionProof stateRootProof; + bytes stateTrieWitness; + bytes storageTrieWitness; + } + + /******************** + * Public Functions * + ********************/ + + /** + * Relays a cross domain message to a contract. + * @param _target Target contract address. + * @param _sender Message sender address. + * @param _message Message to send to the target. + * @param _messageNonce Nonce for the provided message. + */ + function relayMessage( + address _target, + address _sender, + bytes memory _message, + uint256 _messageNonce + ) external; +} diff --git a/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol b/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol new file mode 100644 index 000000000000..910880a57a5e --- /dev/null +++ b/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// solhint-disable max-line-length +/* Library Imports */ +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; +import { Lib_OVMCodec } from "@eth-optimism/contracts/libraries/codec/Lib_OVMCodec.sol"; +import { + Lib_SecureMerkleTrie +} from "@eth-optimism/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; +import { + Lib_DefaultValues +} from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { + Lib_CrossDomainUtils +} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; + +/* Interface Imports */ +import { IL1CrossDomainMessenger } from "./IL1CrossDomainMessenger.sol"; +import { OptimismPortal } from "../OptimismPortal.sol"; + +/* External Imports */ +import { + OwnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { + PausableUpgradeable +} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; +import { + ReentrancyGuardUpgradeable +} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; + +// solhint-enable max-line-length + +/** + * @title L1CrossDomainMessenger + * @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages + * from L2 onto L1. In the event that a message sent from L1 to L2 is rejected for exceeding the L2 + * epoch gas limit, it can be resubmitted via this contract's replay function. + * + */ +contract L1CrossDomainMessenger is + IL1CrossDomainMessenger, + OwnableUpgradeable, + PausableUpgradeable, + ReentrancyGuardUpgradeable +{ + /********** + * Events * + **********/ + + event MessageBlocked(bytes32 indexed _xDomainCalldataHash); + + event MessageAllowed(bytes32 indexed _xDomainCalldataHash); + + /********************** + * Contract Variables * + **********************/ + OptimismPortal public optimismPortal; + address public l2CrossDomainMessenger; + + // Bedrock upgrade note: the nonce must be initialized to greater than the last value of + // CanonicalTransactionChain.queueElements.length. Otherwise it will be possible to have + // messages which cannot be relayed on L2. + uint256 public messageNonce; + + mapping(bytes32 => bool) public blockedMessages; + mapping(bytes32 => bool) public relayedMessages; + mapping(bytes32 => bool) public successfulMessages; + + address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; + + /*************** + * Constructor * + ***************/ + + /** + * This contract is intended to be behind a delegate proxy. + * We still need to set this value in initialize(). + */ + constructor() {} + + /******************** + * Public Functions * + ********************/ + + /** + * @param _optimismPortal Address of the OptimismPortal. + */ + function initialize(OptimismPortal _optimismPortal, address _l2CrossDomainMessenger) + external + initializer + { + require( + address(optimismPortal) == address(0), + "L1CrossDomainMessenger already intialized." + ); + optimismPortal = _optimismPortal; + l2CrossDomainMessenger = _l2CrossDomainMessenger; + xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; + + // Initialize upgradable OZ contracts + __Context_init_unchained(); // Context is a dependency for both Ownable and Pausable + __Ownable_init_unchained(); + __Pausable_init_unchained(); + __ReentrancyGuard_init_unchained(); + } + + /** + * Pause relaying. + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * Block a message. + * @param _xDomainCalldataHash Hash of the message to block. + */ + function blockMessage(bytes32 _xDomainCalldataHash) external onlyOwner { + blockedMessages[_xDomainCalldataHash] = true; + emit MessageBlocked(_xDomainCalldataHash); + } + + /** + * Allow a message. + * @param _xDomainCalldataHash Hash of the message to block. + */ + function allowMessage(bytes32 _xDomainCalldataHash) external onlyOwner { + blockedMessages[_xDomainCalldataHash] = false; + emit MessageAllowed(_xDomainCalldataHash); + } + + /** + * Get the xDomainMessageSender + */ + function xDomainMessageSender() external view returns (address) { + require( + xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, + "xDomainMessageSender is not set" + ); + return xDomainMsgSender; + } + + /** + * Sends a cross domain message to the target messenger. + * This function faciliates L1 to L2 communication. + * @param _target Target contract address. + * @param _message Message to send to the target. + * @param _gasLimit Gas limit for the provided message. + */ + function sendMessage( + address _target, + bytes memory _message, + uint32 _gasLimit + ) external { + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + _target, + msg.sender, + _message, + messageNonce + ); + + emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit); + + _sendXDomainMessage(xDomainCalldata, _gasLimit); + } + + /** + * Relays a cross domain message to a contract. + * This function faciliates L2 to L1 communication. + * Calls WithdrawalsRelay.finalizeWithdrawalTransaction + * @inheritdoc IL1CrossDomainMessenger + */ + function relayMessage( + address _target, + address _sender, + bytes memory _message, + uint256 _messageNonce + ) external nonReentrant whenNotPaused { + require( + msg.sender == address(optimismPortal), + "Messages must be relayed by first calling the Optimism Portal" + ); + require( + optimismPortal.l2Sender() == l2CrossDomainMessenger, + "Message must be sent from the L2 Cross Domain Messenger" + ); + + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + _target, + _sender, + _message, + _messageNonce + ); + + bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); + + require( + successfulMessages[xDomainCalldataHash] == false, + "Provided message has already been received." + ); + + require( + blockedMessages[xDomainCalldataHash] == false, + "Provided message has been blocked." + ); + + require( + _target != address(optimismPortal), + "Cannot send L2->L1 messages to L1 system contracts." + ); + + xDomainMsgSender = _sender; + // slither-disable-next-line reentrancy-no-eth, reentrancy-events, reentrancy-benign + (bool success, ) = _target.call(_message); + // slither-disable-next-line reentrancy-benign + xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; + + // Mark the message as received if the call was successful. Ensures that a message can be + // relayed multiple times in the case that the call reverted. + if (success == true) { + // slither-disable-next-line reentrancy-no-eth + successfulMessages[xDomainCalldataHash] = true; + // slither-disable-next-line reentrancy-events + emit RelayedMessage(xDomainCalldataHash); + } else { + // slither-disable-next-line reentrancy-events + emit FailedRelayedMessage(xDomainCalldataHash); + } + + // Store an identifier that can be used to prove that the given message was relayed by some + // user. Gives us an easy way to pay relayers for their work. + bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number)); + // slither-disable-next-line reentrancy-benign + relayedMessages[relayId] = true; + } + + /********************** + * Internal Functions * + **********************/ + + /** + * Sends a cross domain message. To preserve backwards compatibility, + * the gasLimit is a uint256 so that the function selector stays the same. + * TODO: revert on overflow when converting to uint64? + * @param _message Message to send. + * @param _gasLimit L2 gas limit for the message. + */ + function _sendXDomainMessage(bytes memory _message, uint256 _gasLimit) internal { + optimismPortal.depositTransaction( + Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, + 0, + uint64(_gasLimit), + false, + _message + ); + } +} diff --git a/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol b/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol new file mode 100644 index 000000000000..2cb22988ee8d --- /dev/null +++ b/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Interface Imports */ +import { IL1StandardBridge } from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; +import { IL1ERC20Bridge } from "@eth-optimism/contracts/L1/messaging/IL1ERC20Bridge.sol"; +import { IL2ERC20Bridge } from "@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { OptimismPortal } from "../OptimismPortal.sol"; + +/* Library Imports */ +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title L1StandardBridge + * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard + * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits + * and listening to it for newly finalized withdrawals. + * + */ +contract L1StandardBridge is IL1StandardBridge { + using SafeERC20 for IERC20; + + /******************************** + * External Contract References * + ********************************/ + + OptimismPortal public optimismPortal; + address public l2TokenBridge; + + // Maps L1 token to L2 token to balance of the L1 token deposited + mapping(address => mapping(address => uint256)) public deposits; + + /*************** + * Constructor * + ***************/ + + // This contract lives behind a proxy, so the constructor parameters will go unused. + constructor() {} + + /****************** + * Initialization * + ******************/ + + /** + * @param _optimismPortal OptimismPortal address. + * @param _l2TokenBridge L2 standard bridge address. + */ + // slither-disable-next-line external-function + function initialize(OptimismPortal _optimismPortal, address _l2TokenBridge) public { + require(address(optimismPortal) == address(0), "Contract has already been initialized."); + optimismPortal = _optimismPortal; + l2TokenBridge = _l2TokenBridge; + } + + /************** + * Depositing * + **************/ + + /** @dev Modifier requiring sender to be EOA. This check could be bypassed by a malicious + * contract via initcode, but it takes care of the user error we want to avoid. + */ + modifier onlyEOA() { + // Used to stop deposits from contracts (avoid accidentally lost tokens) + require(!Address.isContract(msg.sender), "Account not EOA"); + _; + } + + /** + * @dev This function can be called with no data + * to deposit an amount of ETH to the caller's balance on L2. + * Since the receive function doesn't take data, a conservative + * default amount is forwarded to L2. + */ + receive() external payable onlyEOA { + _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes("")); + } + + /** + * @inheritdoc IL1StandardBridge + */ + function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA { + _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data); + } + + /** + * @inheritdoc IL1StandardBridge + */ + function depositETHTo( + address _to, + uint32 _l2Gas, + bytes calldata _data + ) external payable { + _initiateETHDeposit(msg.sender, _to, _l2Gas, _data); + } + + /** + * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of + * the deposit. + * @param _from Account to pull the deposit from on L1. + * @param _to Account to give the deposit to on L2. + * @param _l2Gas Gas limit required to complete the deposit on L2. + * @param _data Optional data to forward to L2. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function _initiateETHDeposit( + address _from, + address _to, + uint32 _l2Gas, + bytes memory _data + ) internal { + emit ETHDepositInitiated(_from, _to, msg.value, _data); + + // Send calldata into L2 + optimismPortal.depositTransaction{ value: msg.value }(_to, msg.value, _l2Gas, false, _data); + } + + /** + * @inheritdoc IL1ERC20Bridge + */ + function depositERC20( + address _l1Token, + address _l2Token, + uint256 _amount, + uint32 _l2Gas, + bytes calldata _data + ) external virtual onlyEOA { + _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data); + } + + /** + * @inheritdoc IL1ERC20Bridge + */ + function depositERC20To( + address _l1Token, + address _l2Token, + address _to, + uint256 _amount, + uint32 _l2Gas, + bytes calldata _data + ) external virtual { + _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data); + } + + /** + * @dev Performs the logic for deposits by informing the L2 Deposited Token + * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom) + * + * @param _l1Token Address of the L1 ERC20 we are depositing + * @param _l2Token Address of the L1 respective L2 ERC20 + * @param _from Account to pull the deposit from on L1 + * @param _to Account to give the deposit to on L2 + * @param _amount Amount of the ERC20 to deposit. + * @param _l2Gas Gas limit required to complete the deposit on L2. + * @param _data Optional data to forward to L2. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function _initiateERC20Deposit( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + uint32 _l2Gas, + bytes calldata _data + ) internal { + // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future + // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if + // from is an EOA or address(0). + // slither-disable-next-line reentrancy-events, reentrancy-benign + IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount); + + // Construct calldata for _l2Token.finalizeDeposit(_to, _amount) + bytes memory message = abi.encodeWithSelector( + IL2ERC20Bridge.finalizeDeposit.selector, + _l1Token, + _l2Token, + _from, + _to, + _amount, + _data + ); + + // slither-disable-next-line reentrancy-benign + deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount; + + // slither-disable-next-line reentrancy-events + emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data); + + // Send calldata into L2 + optimismPortal.depositTransaction( + Lib_PredeployAddresses.L2_STANDARD_BRIDGE, + 0, + _l2Gas, + false, + message + ); + } + + /************************* + * Cross-chain Functions * + *************************/ + + /** + * @notice Ensures that the caller is the portal, and that it has the l2Sender value + * set to the address of the L2 Token Bridge. + */ + modifier onlyL2Bridge() { + require( + msg.sender == address(optimismPortal), + "Messages must be relayed by first calling the Optimism Portal" + ); + require( + optimismPortal.l2Sender() == l2TokenBridge, + "Message must be sent from the L2 Token Bridge" + ); + _; + } + + /** + * @inheritdoc IL1StandardBridge + */ + function finalizeETHWithdrawal( + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external onlyL2Bridge { + emit ETHWithdrawalFinalized(_from, _to, _amount, _data); + + (bool success, ) = _to.call{ value: _amount }(new bytes(0)); + require(success, "TransferHelper::safeTransferETH: ETH transfer failed"); + } + + /** + * @inheritdoc IL1ERC20Bridge + */ + function finalizeERC20Withdrawal( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external onlyL2Bridge { + deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] - _amount; + emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); + + // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer + IERC20(_l1Token).safeTransfer(_to, _amount); + } + + /***************************** + * Temporary - Migrating ETH * + *****************************/ + + /** + * @dev Adds ETH balance to the account. This is meant to allow for ETH + * to be migrated from an old gateway to a new gateway. + * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the + * old contract + */ + // Bedrock upgrade note: we may use this if this contract gets merged into the portal, + // or even if we just start using a new proxy. + function donateETH() external payable {} +} diff --git a/packages/contracts/contracts/L2/IWithdrawer.sol b/packages/contracts/contracts/L2/IWithdrawer.sol new file mode 100644 index 000000000000..d2f3f9b9a268 --- /dev/null +++ b/packages/contracts/contracts/L2/IWithdrawer.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.8.0; + +interface IWithdrawer { + event WithdrawalInitiated( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data + ); + event WithdrawerBalanceBurnt(uint256 indexed amount); + + function burn() external; + + function initiateWithdrawal( + address _target, + uint256 _gasLimit, + bytes memory _data + ) external payable; + + function nonce() external view returns (uint256); + + function withdrawals(bytes32) external view returns (bool); +} diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 803088320ae0..0175970e26cb 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -2,9 +2,7 @@ pragma solidity 0.8.10; /* Library Imports */ -import { - AddressAliasHelper -} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; /* Interaction imports */ @@ -71,6 +69,7 @@ contract Withdrawer { if (msg.sender != tx.origin) { from = AddressAliasHelper.undoL1ToL2Alias(msg.sender); } + bytes32 withdrawalHash = WithdrawalVerifier._deriveWithdrawalHash( nonce, msg.sender, @@ -83,7 +82,7 @@ contract Withdrawer { emit WithdrawalInitiated(nonce, from, _target, msg.value, _gasLimit, _data); unchecked { - nonce++; + ++nonce; } } diff --git a/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol b/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol new file mode 100644 index 000000000000..3fa345d61f3f --- /dev/null +++ b/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/** + * @title IL2ERC20Bridge + */ +interface IL2ERC20Bridge { + /********** + * Events * + **********/ + + event WithdrawalInitiated( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event DepositFinalized( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event DepositFailed( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + /******************** + * Public Functions * + ********************/ + + /** + * @dev get the address of the corresponding L1 bridge contract. + * @return Address of the corresponding L1 bridge contract. + */ + function l1TokenBridge() external returns (address); + + /** + * @dev initiate a withdraw of some tokens to the caller's account on L1 + * @param _l2Token Address of L2 token where withdrawal was initiated. + * @param _amount Amount of the token to withdraw. + * param _l1Gas Unused, but included for potential forward compatibility considerations. + * @param _data Optional data to forward to L1. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function withdraw( + address _l2Token, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) external; + + /** + * @dev initiate a withdraw of some token to a recipient's account on L1. + * @param _l2Token Address of L2 token where withdrawal is initiated. + * @param _to L1 adress to credit the withdrawal to. + * @param _amount Amount of the token to withdraw. + * param _l1Gas Unused, but included for potential forward compatibility considerations. + * @param _data Optional data to forward to L1. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) external; + + /************************* + * Cross-chain Functions * + *************************/ + + /** + * @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this + * L2 token. This call will fail if it did not originate from a corresponding deposit in + * L1StandardTokenBridge. + * @param _l1Token Address for the l1 token this is called with + * @param _l2Token Address for the l2 token this is called with + * @param _from Account to pull the deposit from on L2. + * @param _to Address to receive the withdrawal at + * @param _amount Amount of the token to withdraw + * @param _data Data provider by the sender on L1. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function finalizeDeposit( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external; +} diff --git a/packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol b/packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol new file mode 100644 index 000000000000..d3a5e7d4e4ad --- /dev/null +++ b/packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.8.10; + +interface IL2StandardTokenFactory { + event StandardL2TokenCreated(address indexed _l1Token, address indexed _l2Token); + + function createStandardL2Token( + address _l1Token, + string memory _name, + string memory _symbol + ) external; +} diff --git a/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol b/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol new file mode 100644 index 000000000000..a7517600599f --- /dev/null +++ b/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// solhint-disable max-line-length +/* Library Imports */ +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; +import { + Lib_CrossDomainUtils +} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; +import { + Lib_DefaultValues +} from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; +import { Lib_BedrockPredeployAddresses } from "../../libraries/Lib_BedrockPredeployAddresses.sol"; + +/* Interface Imports */ +import { + IL2CrossDomainMessenger +} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; +import { Withdrawer } from "../Withdrawer.sol"; + +// solhint-enable max-line-length + +/** + * @title L2CrossDomainMessenger + * @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point + * for L2 messages sent via the L1 Cross Domain Messenger. + * + */ +contract L2CrossDomainMessenger is IL2CrossDomainMessenger { + /************* + * Variables * + *************/ + + mapping(bytes32 => bool) public relayedMessages; + mapping(bytes32 => bool) public successfulMessages; + mapping(bytes32 => bool) public sentMessages; + uint256 public messageNonce; + address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; + address public l1CrossDomainMessenger; + + /*************** + * Constructor * + ***************/ + + constructor(address _l1CrossDomainMessenger) { + l1CrossDomainMessenger = _l1CrossDomainMessenger; + } + + /******************** + * Public Functions * + ********************/ + + function xDomainMessageSender() external view returns (address) { + require( + xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, + "xDomainMessageSender is not set" + ); + return xDomainMsgSender; + } + + /** + * Sends a cross domain message to the target messenger. + * @param _target Target contract address. + * @param _message Message to send to the target. + * @param _gasLimit Gas limit for the provided message. + */ + function sendMessage( + address _target, + bytes memory _message, + uint32 _gasLimit + ) external { + // Temp note: I think we might be able to remove xDomainCallData from this contract + // entirely. + // Possibly also from the L1xDM as well, but needs considerations. + // Rationale: the proof no longer occurs in the L1 messenger, but rather in the + // WithdrawalRelayer logic (which is inherited into the Portal). This proof relies on + // the value returned by WithdrawalVerifier._deriveWithdrawalHash(), which takes in + // more arguments. + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + _target, + msg.sender, + _message, + messageNonce + ); + + // Temp note: Further to my notes above, afaict this mapping is not used for anything. + // It'd be great if we can save an SSTORE by removing it. + sentMessages[keccak256(xDomainCalldata)] = true; + + // Emit an event before we bump the nonce or the nonce will be off by one. + emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit); + unchecked { + ++messageNonce; + } + + // Actually send the message. + Withdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER).initiateWithdrawal( + l1CrossDomainMessenger, + _gasLimit, + _message + ); + } + + /** + * Relays a cross domain message to a contract. + * @inheritdoc IL2CrossDomainMessenger + */ + function relayMessage( + address _target, + address _sender, + bytes memory _message, + uint256 _messageNonce + ) external { + // Since it is impossible to deploy a contract to an address on L2 which matches + // the alias of the L1CrossDomainMessenger, this check can only pass when it is called in + // the first call frame of a deposit transaction. Thus reentrancy is prevented here. + require( + AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1CrossDomainMessenger, + "Provided message could not be verified." + ); + + // Temp note: Here we would need to keep the xDomainCalldata hashing and + // storage, because it allows replays when the call fails, and prevents + // them when it succeeds. + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + _target, + _sender, + _message, + _messageNonce + ); + + bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); + + require( + successfulMessages[xDomainCalldataHash] == false, + "Provided message has already been received." + ); + + // Prevent calls to WITHDRAWER, which would enable + // an attacker to maliciously craft the _message to spoof + // a call from any L2 account. + // Todo: evaluate if this attack is still relevant + if (_target == Lib_BedrockPredeployAddresses.WITHDRAWER) { + // Write to the successfulMessages mapping and return immediately. + successfulMessages[xDomainCalldataHash] = true; + return; + } + + xDomainMsgSender = _sender; + // slither-disable-next-line reentrancy-no-eth, reentrancy-events, reentrancy-benign + (bool success, ) = _target.call(_message); + // slither-disable-next-line reentrancy-benign + xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; + + // Mark the message as received if the call was successful. Ensures that a message can be + // relayed multiple times in the case that the call reverted. + if (success == true) { + // slither-disable-next-line reentrancy-no-eth + successfulMessages[xDomainCalldataHash] = true; + // slither-disable-next-line reentrancy-events + emit RelayedMessage(xDomainCalldataHash); + } else { + // slither-disable-next-line reentrancy-events + emit FailedRelayedMessage(xDomainCalldataHash); + } + + // Store an identifier that can be used to prove that the given message was relayed by some + // user. Gives us an easy way to pay relayers for their work. + // TODO: consider unaliasing `msg.sender` here + bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number)); + + // slither-disable-next-line reentrancy-benign + relayedMessages[relayId] = true; + } +} diff --git a/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol b/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol new file mode 100644 index 000000000000..b3671f302690 --- /dev/null +++ b/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Interface Imports */ +import { IL1StandardBridge } from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; +import { IL1ERC20Bridge } from "@eth-optimism/contracts/L1/messaging/IL1ERC20Bridge.sol"; +import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol"; + +/* Library Imports */ +import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { Lib_BedrockPredeployAddresses } from "../../libraries/Lib_BedrockPredeployAddresses.sol"; +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; + +/* Contract Imports */ +import { IL2StandardERC20 } from "@eth-optimism/contracts/standards/IL2StandardERC20.sol"; +import { Withdrawer } from "../Withdrawer.sol"; + +/** + * @title L2StandardBridge + * @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to + * enable ETH and ERC20 transitions between L1 and L2. + * This contract acts as a minter for new tokens when it hears about deposits into the L1 Standard + * bridge. + * This contract also acts as a burner of the tokens intended for withdrawal, informing the L1 + * bridge to release L1 funds. + */ +contract L2StandardBridge is IL2ERC20Bridge { + /******************************** + * External Contract References * + ********************************/ + + address public l1TokenBridge; + + /*************** + * Constructor * + ***************/ + + /** + * @param _l1TokenBridge Address of the L1 bridge deployed to the main chain. + */ + constructor(address _l1TokenBridge) { + l1TokenBridge = _l1TokenBridge; + } + + /*************** + * Withdrawing * + ***************/ + + /** + * @inheritdoc IL2ERC20Bridge + */ + function withdraw( + address _l2Token, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) external virtual { + _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data); + } + + /** + * @inheritdoc IL2ERC20Bridge + */ + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) external virtual { + _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data); + } + + /** + * @dev Performs the logic for withdrawals by burning the token and informing + * the L1 token Gateway of the withdrawal. + * @param _l2Token Address of L2 token where withdrawal is initiated. + * @param _from Account to pull the withdrawal from on L2. + * @param _to Account to give the withdrawal to on L1. + * @param _amount Amount of the token to withdraw. + * @param _l1Gas Unused, but included for potential forward compatibility considerations. + * @param _data Optional data to forward to L1. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function _initiateWithdrawal( + address _l2Token, + address _from, + address _to, + uint256 _amount, + uint32 _l1Gas, + bytes calldata _data + ) internal { + // When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2 + // usage + // slither-disable-next-line reentrancy-events + IL2StandardERC20(_l2Token).burn(msg.sender, _amount); + + // Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount) + // slither-disable-next-line reentrancy-events + address l1Token = IL2StandardERC20(_l2Token).l1Token(); + bytes memory message = abi.encodeWithSelector( + IL1ERC20Bridge.finalizeERC20Withdrawal.selector, + l1Token, + _l2Token, + _from, + _to, + _amount, + _data + ); + + // slither-disable-next-line reentrancy-events + emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data); + + // Send message up to L1 bridge + Withdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER).initiateWithdrawal( + l1TokenBridge, + _l1Gas, + message + ); + } + + /************************************ + * Cross-chain Function: Depositing * + ************************************/ + + /** + * @inheritdoc IL2ERC20Bridge + */ + function finalizeDeposit( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external virtual { + // Since it is impossible to deploy a contract to an address on L2 which matches + // the alias of the l1TokenBridge, this check can only pass when it is called in + // the first call frame of a deposit transaction. Thus reentrancy is prevented here. + require( + AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1TokenBridge, + "Can only be called by a the l1TokenBridge" + ); + + if ( + // Check the target token is compliant and + // verify the deposited token on L1 matches the L2 deposited token representation here + // slither-disable-next-line reentrancy-events + ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) && + _l1Token == IL2StandardERC20(_l2Token).l1Token() + ) { + // When a deposit is finalized, we credit the account on L2 with the same amount of + // tokens. + // slither-disable-next-line reentrancy-events + IL2StandardERC20(_l2Token).mint(_to, _amount); + // slither-disable-next-line reentrancy-events + emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); + } else { + // Either the L2 token which is being deposited-into disagrees about the correct address + // of its L1 token, or does not support the correct interface. + // This should only happen if there is a malicious L2 token, or if a user somehow + // specified the wrong L2 token address to deposit into. + // In either case, we stop the process here and construct a withdrawal + // message so that users can get their funds out in some cases. + // There is no way to prevent malicious token contracts altogether, but this does limit + // user error and mitigate some forms of malicious contract behavior. + bytes memory message = abi.encodeWithSelector( + IL1ERC20Bridge.finalizeERC20Withdrawal.selector, + _l1Token, + _l2Token, + _to, // switched the _to and _from here to bounce back the deposit to the sender + _from, + _amount, + _data + ); + + emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data); + + // Send message up to L1 bridge + Withdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER).initiateWithdrawal( + l1TokenBridge, + 0, + message + ); + } + } +} diff --git a/packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol b/packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol new file mode 100644 index 000000000000..c9380746274c --- /dev/null +++ b/packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Contract Imports */ +import { L2StandardERC20 } from "../tokens/L2StandardERC20.sol"; +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; + +/** + * @title L2StandardTokenFactory + * @dev Factory contract for creating standard L2 token representations of L1 ERC20s + * compatible with and working on the standard bridge. + */ +contract L2StandardTokenFactory { + event StandardL2TokenCreated(address indexed _l1Token, address indexed _l2Token); + + /** + * @dev Creates an instance of the standard ERC20 token on L2. + * @param _l1Token Address of the corresponding L1 token. + * @param _name ERC20 name. + * @param _symbol ERC20 symbol. + */ + function createStandardL2Token( + address _l1Token, + string memory _name, + string memory _symbol + ) external { + require(_l1Token != address(0), "Must provide L1 token address"); + + L2StandardERC20 l2Token = new L2StandardERC20( + Lib_PredeployAddresses.L2_STANDARD_BRIDGE, + _l1Token, + _name, + _symbol + ); + + emit StandardL2TokenCreated(_l1Token, address(l2Token)); + } +} diff --git a/packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol b/packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol new file mode 100644 index 000000000000..f9e981842520 --- /dev/null +++ b/packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +interface IL2StandardERC20 is IERC20, IERC165 { + function l1Token() external returns (address); + + function l2Bridge() external returns (address); + + function mint(address _to, uint256 _amount) external; + + function burn(address _from, uint256 _amount) external; + + event Mint(address indexed _account, uint256 _amount); + event Burn(address indexed _account, uint256 _amount); +} diff --git a/packages/contracts/contracts/L2/tokens/L2StandardERC20.sol b/packages/contracts/contracts/L2/tokens/L2StandardERC20.sol new file mode 100644 index 000000000000..06144d7cb343 --- /dev/null +++ b/packages/contracts/contracts/L2/tokens/L2StandardERC20.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// import { ERC20 } from "solmate/tokens/ERC20.sol"; +// import { ERC20 } from "solmate/tokens/ERC20.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "./IL2StandardERC20.sol"; + +contract L2StandardERC20 is IL2StandardERC20, ERC20 { + address public l1Token; + address public l2Bridge; + + /** + * @param _l2Bridge Address of the L2 standard bridge. + * @param _l1Token Address of the corresponding L1 token. + * @param _name ERC20 name. + * @param _symbol ERC20 symbol. + */ + constructor( + address _l2Bridge, + address _l1Token, + string memory _name, + string memory _symbol + ) ERC20(_name, _symbol) { + l1Token = _l1Token; + l2Bridge = _l2Bridge; + } + + modifier onlyL2Bridge() { + require(msg.sender == l2Bridge, "Only L2 Bridge can mint and burn"); + _; + } + + // slither-disable-next-line external-function + function supportsInterface(bytes4 _interfaceId) public pure returns (bool) { + bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165 + bytes4 secondSupportedInterface = IL2StandardERC20.l1Token.selector ^ + IL2StandardERC20.mint.selector ^ + IL2StandardERC20.burn.selector; + return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface; + } + + // slither-disable-next-line external-function + function mint(address _to, uint256 _amount) public virtual onlyL2Bridge { + _mint(_to, _amount); + + emit Mint(_to, _amount); + } + + // slither-disable-next-line external-function + function burn(address _from, uint256 _amount) public virtual onlyL2Bridge { + _burn(_from, _amount); + + emit Burn(_from, _amount); + } +} diff --git a/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol b/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol new file mode 100644 index 000000000000..07513b05dfcc --- /dev/null +++ b/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/** + * @title Lib_BedrockPredeployAddresses + */ +library Lib_BedrockPredeployAddresses { + address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015; + address internal constant WITHDRAWER = 0x4200000000000000000000000000000000000016; +} diff --git a/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol index 0346d29c87c1..a5fea789cf69 100644 --- a/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.10; /* Library Imports */ import { Lib_SecureMerkleTrie -} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; +} from "@eth-optimism/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; /** * @title WithdrawalVerifier diff --git a/packages/contracts/contracts/test/CommonTest.t.sol b/packages/contracts/contracts/test/CommonTest.t.sol new file mode 100644 index 000000000000..8f44709c5189 --- /dev/null +++ b/packages/contracts/contracts/test/CommonTest.t.sol @@ -0,0 +1,17 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/* Testing utilities */ +import { DSTest } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; + +contract CommonTest is DSTest { + Vm vm = Vm(HEVM_ADDRESS); + address immutable ZERO_ADDRESS = address(0); + address immutable NON_ZERO_ADDRESS = address(1); + uint256 immutable NON_ZERO_VALUE = 100; + uint256 immutable ZERO_VALUE = 0; + uint64 immutable NON_ZERO_GASLIMIT = 50000; + bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); + bytes NON_ZERO_DATA = hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"; +} diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol index f11c2dbc333e..4cc4ec87ba18 100644 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ b/packages/contracts/contracts/test/DepositFeed.t.sol @@ -2,27 +2,19 @@ pragma solidity 0.8.10; /* Testing utilities */ -import { DSTest } from "../../lib/ds-test/src/test.sol"; -import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { CommonTest } from "./CommonTest.t.sol"; /* Library Imports */ import { AddressAliasHelper -} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +} from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; /* Target contract */ import { DepositFeed } from "../L1/abstracts/DepositFeed.sol"; contract Target is DepositFeed {} -contract DepositFeedTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - address immutable ZERO_ADDRESS = address(0); - address immutable NON_ZERO_ADDRESS = address(1); - uint256 immutable NON_ZERO_VALUE = 100; - uint256 immutable ZERO_VALUE = 0; - uint64 immutable NON_ZERO_GASLIMIT = 50000; - bytes NON_ZERO_DATA = hex"1111"; +contract DepositFeedTest is CommonTest { Target df; diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts/contracts/test/L1Block.t.sol index 3f5da9d1d9a8..c051cbeef99b 100644 --- a/packages/contracts/contracts/test/L1Block.t.sol +++ b/packages/contracts/contracts/test/L1Block.t.sol @@ -1,8 +1,8 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -import { DSTest } from "../../lib/ds-test/src/test.sol"; -import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { DSTest } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; import { L1Block } from "../L2/L1Block.sol"; contract L1BLockTest is DSTest { diff --git a/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol b/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol new file mode 100644 index 000000000000..bd86d37c30dc --- /dev/null +++ b/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol @@ -0,0 +1,318 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +/* Testing utilities */ +import { CommonTest } from "./CommonTest.t.sol"; +import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; + +/* Libraries */ +import { + Lib_DefaultValues +} from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { + Lib_CrossDomainUtils +} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; +import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; + +/* Target contract dependencies */ +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { OptimismPortal } from "../L1/OptimismPortal.sol"; + +/* Target contract */ +import { L1CrossDomainMessenger } from "../L1/messaging/L1CrossDomainMessenger.sol"; +import { IDepositFeed } from "../L1/abstracts/IDepositFeed.sol"; + +import { + ICrossDomainMessenger +} from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol"; + +contract L1CrossDomainMessenger_Test is CommonTest, L2OutputOracle_Initializer { + // Dependencies + OptimismPortal op; + // 'L2OutputOracle oracle' is declared in L2OutputOracle_Initializer + + event SentMessage( + address indexed target, + address sender, + bytes message, + uint256 messageNonce, + uint256 gasLimit + ); + event RelayedMessage(bytes32 indexed msgHash); + + // Contract under test + L1CrossDomainMessenger messenger; + + // Receiver address for testing + address recipient = address(0xabbaacdc); + + function setUp() external { + // new portal with small finalization window + op = new OptimismPortal(oracle, 100); + messenger = new L1CrossDomainMessenger(); + messenger.initialize(op, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER); + } + + // pause: should pause the contract when called by the current owner + function test_pause() external { + messenger.pause(); + assert(messenger.paused()); + } + + // pause: should not pause the contract when called by account other than the owner + function testCannot_pause() external { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(address(0xABBA)); + messenger.pause(); + } + + // sendMessage: should be able to send a single message + function test_sendMessage() external { + uint256 messageNonce = messenger.messageNonce(); + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + recipient, + address(this), + NON_ZERO_DATA, + messageNonce + ); + vm.expectCall( + address(op), + abi.encodeWithSelector( + IDepositFeed.depositTransaction.selector, + Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, + 0, + NON_ZERO_GASLIMIT, + false, + xDomainCalldata + ) + ); + messenger.sendMessage(recipient, NON_ZERO_DATA, uint32(NON_ZERO_GASLIMIT)); + } + + // sendMessage: should be able to send the same message twice + function test_sendMessageTwice() external { + messenger.sendMessage(recipient, NON_ZERO_DATA, uint32(NON_ZERO_GASLIMIT)); + messenger.sendMessage(recipient, NON_ZERO_DATA, uint32(NON_ZERO_GASLIMIT)); + } + + // xDomainMessageSender: should return the xDomainMsgSender address + // TODO: might need a test contract + // function test_xDomainSenderSetCorrectly() external {} + + // relayMessage: should send a successful call to the target contract + function test_relayMessageSucceeds() external { + address target = address(0xabcd); + address sender = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; + bytes memory message = hex"1111"; + uint256 messageNonce = 42; + // The encoding we'll use to verify that the message was successful relayed + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + target, + sender, + message, + messageNonce + ); + + // ensure that both the messenger and target receive a call + vm.expectCall( + address(messenger), + abi.encodeWithSelector( + L1CrossDomainMessenger.relayMessage.selector, + target, + sender, + message, + messageNonce + ) + ); + vm.expectCall(address(0xabcd), hex"1111"); + // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. + vm.store(address(op), 0, bytes32(abi.encode(sender))); + vm.prank(address(op)); + vm.expectEmit(true, true, true, true); + emit RelayedMessage(keccak256(xDomainCalldata)); + messenger.relayMessage(target, sender, message, messageNonce); + + // Ensure the hash of the xDomainCalldata was stored in the successfulMessages mapping. + bytes32 messageHash = keccak256(xDomainCalldata); + assert(messenger.successfulMessages(messageHash)); + } + + + // relayMessage: should revert if still inside the fraud proof window + function test_relayMessageInsideFraudProofWindow() external { + bytes memory cd = abi.encodeWithSelector( + L1CrossDomainMessenger.relayMessage.selector, + address(42), + address(this), + hex"1111", + 0 + ); + + WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({ + version: bytes32(0), + stateRoot: bytes32(0), + withdrawerStorageRoot: bytes32(0), + latestBlockhash:bytes32(0) + }); + + bytes memory withdrawProof = bytes(hex""); + + // get the finalization window + uint256 window = op.FINALIZATION_PERIOD(); + assert(window != 0); + // set block.timestamp to be one less than the finalization window. + // the timestamp 0 is passed into `finalizeWithdrawalTransaction` + vm.warp(window - 1); + + // The OptimismPortal is responsible for keeping track + // of the finalization window + vm.expectRevert(abi.encodeWithSignature("NotYetFinal()")); + op.finalizeWithdrawalTransaction( + 0, // nonce + address(this), // sender + address(42), // target + 0, // value + 100000, // gasLimit + cd, // calldata + 0, // timestamp + outputRootProof, // outputRootProof + withdrawProof // withdrawProof + ); + } + + // relayMessage: should revert if attempting to relay a message sent to an L1 system contract + function test_relayMessageToSystemContract() external { + // set the target to be the OptimismPortal + address target = address(op); + address sender = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; + bytes memory message = hex"1111"; + uint256 messageNonce = 42; + + // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. + vm.store(address(op), 0, bytes32(abi.encode(sender))); + vm.prank(address(op)); + vm.expectRevert("Cannot send L2->L1 messages to L1 system contracts."); + messenger.relayMessage(target, sender, message, messageNonce); + } + + // relayMessage: should revert if provided an invalid output root proof + function test_revertOnInvalidOutputRootProof() external { + // create an invalid output root proof + WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({ + version: bytes32(0), + stateRoot: bytes32(0), + withdrawerStorageRoot: bytes32(0), + latestBlockhash:bytes32(0) + }); + bytes memory withdrawProof = bytes(hex""); + + vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); + op.finalizeWithdrawalTransaction( + 0, // nonce + address(this), // sender + address(42), // target + 0, // value + 100000, // gasLimit + bytes(""), // calldata + 0, // timestamp + outputRootProof, // outputRootProof + withdrawProof // withdrawProof + ); + } + + // relayMessage: the xDomainMessageSender is reset to the original value + function test_xDomainMessageSenderResets() external { + vm.expectRevert("xDomainMessageSender is not set"); + messenger.xDomainMessageSender(); + + address sender = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; + bytes memory message = hex"1111"; + uint256 messageNonce = 42; + + vm.store(address(op), 0, bytes32(abi.encode(sender))); + vm.prank(address(op)); + messenger.relayMessage(address(0), sender, message, messageNonce); + + vm.expectRevert("xDomainMessageSender is not set"); + messenger.xDomainMessageSender(); + } + + // relayMessage: should revert if trying to send the same message twice + function test_relayShouldRevertSendingSameMessageTwice() external { + // TODO: this is a test on the L2CrossDomainMessenger + } + + // relayMessage: should revert if paused + function test_relayShouldRevertIfPaused() external { + vm.prank(messenger.owner()); + messenger.pause(); + + vm.expectRevert("Pausable: paused"); + messenger.relayMessage(address(0), address(0), hex"", 0); + } + + // blockMessage and allowMessage: should revert if called by an account other than the owner + function test_relayMessageBlockingAuth() external { + bytes32 msgHash = bytes32(hex"ff"); + + vm.prank(address(0)); + vm.expectRevert("Ownable: caller is not the owner"); + messenger.blockMessage(msgHash); + assert(messenger.blockedMessages(msgHash) == false); + + vm.prank(address(0)); + vm.expectRevert("Ownable: caller is not the owner"); + messenger.allowMessage(msgHash); + assert(messenger.blockedMessages(msgHash) == false); + } + + // blockMessage and allowMessage: should revert if the message is blocked + function test_relayRevertOnBlockedMessage() external { + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + address(0), + address(0), + hex"ff", + 0 + ); + bytes32 msgHash = keccak256(xDomainCalldata); + + vm.prank(messenger.owner()); + messenger.blockMessage(msgHash); + + vm.store(address(op), 0, bytes32(abi.encode(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER))); + vm.prank(address(op)); + vm.expectRevert("Provided message has been blocked."); + messenger.relayMessage(address(0), address(0), hex"ff", 0); + } + + // blockMessage and allowMessage: should succeed if the message is blocked, then unblocked + function test_blockAndUnblockSuccessfulMessage() external { + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + address(0), + address(0), + hex"ff", + 0 + ); + bytes32 msgHash = keccak256(xDomainCalldata); + + vm.prank(messenger.owner()); + messenger.blockMessage(msgHash); + + vm.store(address(op), 0, bytes32(abi.encode(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER))); + vm.prank(address(op)); + vm.expectRevert("Provided message has been blocked."); + messenger.relayMessage(address(0), address(0), hex"ff", 0); + + vm.prank(messenger.owner()); + messenger.allowMessage(msgHash); + + vm.prank(address(op)); + + vm.expectEmit(true, true, true, true); + emit RelayedMessage(msgHash); + messenger.relayMessage(address(0), address(0), hex"ff", 0); + } +} diff --git a/packages/contracts/contracts/test/L1StandardBridge.t.sol b/packages/contracts/contracts/test/L1StandardBridge.t.sol new file mode 100644 index 000000000000..89e709c5e299 --- /dev/null +++ b/packages/contracts/contracts/test/L1StandardBridge.t.sol @@ -0,0 +1,102 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; + +import { IWithdrawer } from "../L2/IWithdrawer.sol"; +import { Withdrawer } from "../L2/Withdrawer.sol"; +import { L2StandardBridge } from "../L2/messaging/L2StandardBridge.sol"; +import { L1StandardBridge } from "../L1/messaging/L1StandardBridge.sol"; +import { OptimismPortal } from "../L1/OptimismPortal.sol"; +import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; +import { L2StandardTokenFactory } from "../L2/messaging/L2StandardTokenFactory.sol"; +import { IL2StandardTokenFactory } from "../L2/messaging/IL2StandardTokenFactory.sol"; +import { L2StandardERC20 } from "../L2/tokens/L2StandardERC20.sol"; +import { IL2StandardERC20 } from "../L2/tokens/IL2StandardERC20.sol"; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { CommonTest } from "./CommonTest.t.sol"; +import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; +import { LibRLP } from "./Lib_RLP.t.sol"; + +contract L1StandardBridge_Test is CommonTest, L2OutputOracle_Initializer { + OptimismPortal op; + + IWithdrawer W; + L1StandardBridge L1Bridge; + L2StandardBridge L2Bridge; + IL2StandardTokenFactory L2TokenFactory; + IL2StandardERC20 L2Token; + + function setUp() external { + L1Bridge = new L1StandardBridge(); + L2Bridge = new L2StandardBridge(address(L1Bridge)); + op = new OptimismPortal(oracle, 100); + + L1Bridge.initialize(op, address(L2Bridge)); + + Withdrawer w = new Withdrawer(); + vm.etch(Lib_BedrockPredeployAddresses.WITHDRAWER, address(w).code); + W = IWithdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER); + + L2StandardTokenFactory factory = new L2StandardTokenFactory(); + vm.etch(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY, address(factory).code); + L2TokenFactory = IL2StandardTokenFactory(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY); + + ERC20 token = new ERC20("Test Token", "TT"); + + // Deploy the L2 ERC20 now + L2TokenFactory.createStandardL2Token( + address(token), + string(abi.encodePacked("L2-", token.name())), + string(abi.encodePacked("L2-", token.symbol())) + ); + + L2Token = IL2StandardERC20( + LibRLP.computeAddress(address(L2TokenFactory), 0) + ); + } + + function test_L1BridgeSetsPortalAndL2Bridge() external { + OptimismPortal portal = L1Bridge.optimismPortal(); + address bridge = L1Bridge.l2TokenBridge(); + + assertEq(address(portal), address(op)); + assertEq(bridge, address(L2Bridge)); + } + + // receive + // - can accept ETH + // depositETH + // - emits ETHDepositInitiated + // - calls optimismPortal.depositTransaction + // - only EOA + // - ETH ends up in the optimismPortal + // depositETHTo + // - emits ETHDepositInitiated + // - calls optimismPortal.depositTransaction + // - EOA or contract can call + // - ETH ends up in the optimismPortal + // depositERC20 + // - updates bridge.deposits + // - emits ERC20DepositInitiated + // - calls optimismPortal.depositTransaction + // - only callable by EOA + // depositERC20To + // - updates bridge.deposits + // - emits ERC20DepositInitiated + // - calls optimismPortal.depositTransaction + // - reverts if called by EOA + // - callable by a contract + // finalizeETHWithdrawal + // - emits ETHWithdrawalFinalized + // - only callable by L2 bridge + // finalizeERC20Withdrawal + // - updates bridge.deposits + // - emits ERC20WithdrawalFinalized + // - only callable by L2 bridge + // donateETH + // - can send ETH to the contract +} diff --git a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol new file mode 100644 index 000000000000..b902f9b37b2b --- /dev/null +++ b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol @@ -0,0 +1,205 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { CommonTest } from "./CommonTest.t.sol"; +import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; + +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { + Lib_CrossDomainUtils +} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; + +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { OptimismPortal } from "../L1/OptimismPortal.sol"; +import { L2CrossDomainMessenger } from "../L2/messaging/L2CrossDomainMessenger.sol"; +import { L1CrossDomainMessenger } from "../L1/messaging/L1CrossDomainMessenger.sol"; +import { Withdrawer } from "../L2/Withdrawer.sol"; +import { IWithdrawer } from "../L2/IWithdrawer.sol"; +import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; + +import { + Lib_DefaultValues +} from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; + +import { console } from "forge-std/console.sol"; + +contract L2CrossDomainMessenger_Test is CommonTest, L2OutputOracle_Initializer { + + // Dependencies + OptimismPortal op; + + IWithdrawer W; + L1CrossDomainMessenger L1Messenger; + L2CrossDomainMessenger L2Messenger; + + event SentMessage( + address indexed target, + address sender, + bytes message, + uint256 messageNonce, + uint256 gasLimit + ); + + event WithdrawalInitiated( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data + ); + + function setUp() external { + op = new OptimismPortal(oracle, 100); + L1Messenger = new L1CrossDomainMessenger(); + L1Messenger.initialize(op, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER); + + L2Messenger = new L2CrossDomainMessenger(address(L1Messenger)); + + // Deploy the Withdrawer and then get its code to set at the + // correct address + Withdrawer w = new Withdrawer(); + bytes memory code = address(w).code; + vm.etch(Lib_BedrockPredeployAddresses.WITHDRAWER, code); + W = IWithdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER); + } + + // xDomainMessageSender: should return correct L1Messenger address + function test_L2MessengerCorrectL1Messenger() external { + address l1 = L2Messenger.l1CrossDomainMessenger(); + assertEq(l1, address(L1Messenger)); + } + + // xDomainMessageSender: should return the xDomainMsgSender address + function test_L2MessengerxDomainMsgSender() external { + vm.expectRevert("xDomainMessageSender is not set"); + L2Messenger.xDomainMessageSender(); + + bytes32 slot = vm.load(address(L2Messenger), bytes32(uint256(4))); + assertEq(address(uint160(uint256(slot))), Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER); + } + + // sendMessage: should be able to send a single message + function test_L2MessengerSendMessage() external { + address target = address(0); + bytes memory message = hex""; + uint32 gasLimit = 1000; + + uint256 nonce = W.nonce(); + address sender = AddressAliasHelper.undoL1ToL2Alias(address(L2Messenger)); + + vm.expectEmit(true, true, true, true); + emit SentMessage(target, address(this), message, nonce, gasLimit); + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(nonce, sender, address(L1Messenger), 0, gasLimit, message); + + L2Messenger.sendMessage(target, message, gasLimit); + } + + // sendMessage: should be able to send the same message twice + function test_L2MessengerSendSameMessageTwice() external { + L2Messenger.sendMessage(address(0), hex"", 1000); + L2Messenger.sendMessage(address(0), hex"", 1000); + // TODO: assertion on events, nonce increments + } + + // relayMessage: should revert if the L1 message sender is not the L1CrossDomainMessenger + function test_L2MessengerRevertInvalidL1XDomainMessenger() external { + vm.expectRevert("Provided message could not be verified."); + vm.prank(address(0)); + L2Messenger.relayMessage( + address(0), + address(0), + hex"", + 0 + ); + } + + // relayMessage: should send a call to the target contract + function test_L2MessengerCallsTarget() external { + address target = address(4); + + vm.expectCall(target, hex"ff"); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); + L2Messenger.relayMessage( + target, + address(this), + hex"ff", + 1000 + ); + } + + // relayMessage: the xDomainMessageSender is reset to the original value + function test_L2MessengerXDomainMessageSenderReset() external { + vm.expectRevert("xDomainMessageSender is not set"); + L2Messenger.xDomainMessageSender(); + + vm.expectCall(address(4), hex"ff"); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); + L2Messenger.relayMessage( + address(4), + address(this), + hex"ff", + 1000 + ); + + vm.expectRevert("xDomainMessageSender is not set"); + L2Messenger.xDomainMessageSender(); + bytes32 slot = vm.load(address(L2Messenger), bytes32(uint256(4))); + assertEq(address(uint160(uint256(slot))), Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER); + } + + // relayMessage: should revert if trying to send the same message twice + function test_L2MessengerCannotRelaySameMessageTwice() external { + vm.expectCall(address(4), hex"ff"); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); + L2Messenger.relayMessage( + address(4), + address(this), + hex"ff", + 1000 + ); + + vm.expectRevert("Provided message has already been received."); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); + L2Messenger.relayMessage( + address(4), + address(this), + hex"ff", + 1000 + ); + } + + // relayMessage: should not make a call if the target is the L2 MessagePasser + function test_L2MessengerCannotCallL2MessagePasser() external { + address target = Lib_BedrockPredeployAddresses.WITHDRAWER; + + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); + L2Messenger.relayMessage( + target, + address(this), + hex"ff", + 1000 + ); + + bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( + target, + address(this), + hex"ff", + 1000 + ); + bytes32 hash = keccak256(xDomainCalldata); + assert(L2Messenger.successfulMessages(hash) == true); + + bytes32 relayId = keccak256(abi.encodePacked( + xDomainCalldata, + AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), + block.number + )); + + assert(L2Messenger.relayedMessages(relayId) == false); + } +} diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 435385ec758e..3a45339e7a33 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -1,14 +1,13 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -import { DSTest } from "../../lib/ds-test/src/test.sol"; -import { Vm } from "../../lib/forge-std/src/Vm.sol"; +/* Testing utilities */ +import { CommonTest } from "./CommonTest.t.sol"; + import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -contract L2OutputOracle_Initializer is DSTest { +contract L2OutputOracle_Initializer is CommonTest { // Utility variables - Vm vm = Vm(HEVM_ADDRESS); - bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); uint256 appendedTimestamp; // Test target diff --git a/packages/contracts/contracts/test/L2StandardBridge.t.sol b/packages/contracts/contracts/test/L2StandardBridge.t.sol new file mode 100644 index 000000000000..777c10d08289 --- /dev/null +++ b/packages/contracts/contracts/test/L2StandardBridge.t.sol @@ -0,0 +1,83 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; + +import { IWithdrawer } from "../L2/IWithdrawer.sol"; +import { Withdrawer } from "../L2/Withdrawer.sol"; +import { L2StandardBridge } from "../L2/messaging/L2StandardBridge.sol"; +import { L1StandardBridge } from "../L1/messaging/L1StandardBridge.sol"; +import { OptimismPortal } from "../L1/OptimismPortal.sol"; +import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; +import { L2StandardTokenFactory } from "../L2/messaging/L2StandardTokenFactory.sol"; +import { IL2StandardTokenFactory } from "../L2/messaging/IL2StandardTokenFactory.sol"; +import { L2StandardERC20 } from "../L2/tokens/L2StandardERC20.sol"; +import { IL2StandardERC20 } from "../L2/tokens/IL2StandardERC20.sol"; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { CommonTest } from "./CommonTest.t.sol"; +import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; +import { LibRLP } from "./Lib_RLP.t.sol"; + +import { console } from "forge-std/console.sol"; + +contract L2StandardBridge_Test is CommonTest, L2OutputOracle_Initializer { + OptimismPortal op; + + IWithdrawer W; + L1StandardBridge L1Bridge; + L2StandardBridge L2Bridge; + IL2StandardTokenFactory L2TokenFactory; + IL2StandardERC20 L2Token; + + function setUp() external { + L1Bridge = new L1StandardBridge(); + L2Bridge = new L2StandardBridge(address(L1Bridge)); + op = new OptimismPortal(oracle, 100); + + L1Bridge.initialize(op, address(L2Bridge)); + + Withdrawer w = new Withdrawer(); + vm.etch(Lib_BedrockPredeployAddresses.WITHDRAWER, address(w).code); + W = IWithdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER); + + L2StandardTokenFactory factory = new L2StandardTokenFactory(); + vm.etch(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY, address(factory).code); + L2TokenFactory = IL2StandardTokenFactory(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY); + + ERC20 token = new ERC20("Test Token", "TT"); + + // Deploy the L2 ERC20 now + L2TokenFactory.createStandardL2Token( + address(token), + string(abi.encodePacked("L2-", token.name())), + string(abi.encodePacked("L2-", token.symbol())) + ); + + L2Token = IL2StandardERC20( + LibRLP.computeAddress(address(L2TokenFactory), 0) + ); + } + + function test_L2BridgeCorrectL1Bridge() external { + address l1Bridge = L2Bridge.l1TokenBridge(); + assertEq(address(L1Bridge), l1Bridge); + } + + // withdraw + // - token is burned + // - emits WithdrawalInitiated + // - calls Withdrawer.initiateWithdrawal + // withdrawTo + // - token is burned + // - emits WithdrawalInitiated w/ correct recipient + // - calls Withdrawer.initiateWithdrawal + // finalizeDeposit + // - only callable by l1TokenBridge + // - supported token pair emits DepositFinalized + // - invalid deposit emits DepositFailed + // - invalid deposit calls Withdrawer.initiateWithdrawal +} + diff --git a/packages/contracts/contracts/test/Lib_RLP.t.sol b/packages/contracts/contracts/test/Lib_RLP.t.sol new file mode 100644 index 000000000000..f9f252642142 --- /dev/null +++ b/packages/contracts/contracts/test/Lib_RLP.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Unlicense +pragma solidity >=0.8.0; + +import {Bytes32AddressLib} from "solmate/utils/Bytes32AddressLib.sol"; + +// prettier-ignore +library LibRLP { + using Bytes32AddressLib for bytes32; + + function computeAddress(address deployer, uint256 nonce) public pure returns (address) { + // The integer zero is treated as an empty byte string, and as a result it only has a length prefix, 0x80, computed via 0x80 + 0. + // A one byte integer uses its own value as its length prefix, there is no additional "0x80 + length" prefix that comes before it. + if (nonce == 0x00) return keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))).fromLast20Bytes(); + if (nonce <= 0x7f) return keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))).fromLast20Bytes(); + + // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length. + if (nonce <= type(uint8).max) return keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))).fromLast20Bytes(); + if (nonce <= type(uint16).max) return keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))).fromLast20Bytes(); + if (nonce <= type(uint24).max) return keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))).fromLast20Bytes(); + + // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp + // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce) + // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) + // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex) + // We assume nobody can have a nonce large enough to require more than 32 bytes. + return keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))).fromLast20Bytes(); + } +} diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index 1ac4fbc5fdd9..c77b91e003dc 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -2,8 +2,7 @@ pragma solidity 0.8.10; /* Testing utilities */ -import { DSTest } from "../../lib/ds-test/src/test.sol"; -import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { CommonTest } from "./CommonTest.t.sol"; /* Target contract dependencies */ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; @@ -11,7 +10,7 @@ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; /* Target contract */ import { OptimismPortal } from "../L1/OptimismPortal.sol"; -contract OptimismPortal_Test is DSTest { +contract OptimismPortal_Test is CommonTest { event TransactionDeposited( address indexed from, address indexed to, @@ -22,10 +21,6 @@ contract OptimismPortal_Test is DSTest { bytes data ); - // Utilities - Vm vm = Vm(HEVM_ADDRESS); - bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); - // Dependencies L2OutputOracle oracle; diff --git a/packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol b/packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol deleted file mode 100644 index 5205ff84c2bb..000000000000 --- a/packages/contracts/contracts/test/TestLib_SecureMerkleTrie.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* Library Imports */ -import { - Lib_SecureMerkleTrie -} from "../../lib/optimism/packages/contracts/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; - -/** - * @title TestLib_SecureMerkleTrie - */ -contract TestLib_SecureMerkleTrie { - function verifyInclusionProof( - bytes memory _key, - bytes memory _value, - bytes memory _proof, - bytes32 _root - ) public pure returns (bool) { - return Lib_SecureMerkleTrie.verifyInclusionProof(_key, _value, _proof, _root); - } - - function update( - bytes memory _key, - bytes memory _value, - bytes memory _proof, - bytes32 _root - ) public pure returns (bytes32) { - return Lib_SecureMerkleTrie.update(_key, _value, _proof, _root); - } - - function get( - bytes memory _key, - bytes memory _proof, - bytes32 _root - ) public pure returns (bool, bytes memory) { - return Lib_SecureMerkleTrie.get(_key, _proof, _root); - } - - function getSingleNodeRootHash(bytes memory _key, bytes memory _value) - public - pure - returns (bytes32) - { - return Lib_SecureMerkleTrie.getSingleNodeRootHash(_key, _value); - } -} diff --git a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol index 26525d5caa36..7031c1235d06 100644 --- a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol +++ b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol @@ -2,8 +2,7 @@ pragma solidity 0.8.10; /* Testing utilities */ -import { DSTest } from "../../lib/ds-test/src/test.sol"; -import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { CommonTest } from "./CommonTest.t.sol"; /* Target contract dependencies */ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; @@ -12,14 +11,13 @@ import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; /* Target contract */ import { WithdrawalsRelay } from "../L1/abstracts/WithdrawalsRelay.sol"; - contract Target is WithdrawalsRelay { constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) WithdrawalsRelay(_l2Oracle, _finalizationPeriod) {} } -contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is DSTest { +contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is CommonTest { event TransactionDeposited( address indexed from, address indexed to, @@ -30,10 +28,6 @@ contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is DSTest { bytes data ); - // Utilities - Vm vm = Vm(HEVM_ADDRESS); - bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); - // Dependencies L2OutputOracle oracle; @@ -59,30 +53,24 @@ contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is DSTest { uint256 initTime = 1648757197; // Withdrawal call parameters - uint256 wdNonce = 0; - address wdSender = 0xDe3829A23DF1479438622a08a116E8Eb3f620BB5; - address wdTarget = 0x1111111111111111111111111111111111111111; - uint256 wdValue = 0; - uint256 wdGasLimit = 50_000; - bytes wdData = - hex"111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; - - // Generate an output that we can work with. We can use whatever values we want - // except for the withdrawerStorageRoot. This one was generated by running the withdrawer.spec.ts - // test script against Geth. - bytes32 version = bytes32(hex"00"); - bytes32 stateRoot = keccak256(abi.encode(1)); + uint256 wdNonce = 1; + address wdSender = address(0x02); + address wdTarget = address(0x03); + uint256 wdValue = 4; + uint256 wdGasLimit = 500000; + bytes wdData = hex"06"; + + // Generate an output and corresponding proof that we can work with. We can use whatever values + // we want except for the withdrawerStorageRoot. These roots and the proof were generated by + // running scripts/makeProof.ts with the above withdrawal call parameters as arguments. + bytes32 version = 0x0000000000000000000000000000000000000000000000000000000000000000; + bytes32 stateRoot = 0x187c35d79aa836b74475ff4940e0eff42e2ee5661f136995b4470bb92cf0813d; bytes32 withdrawerStorageRoot = - 0xb8576230d94535779ec872748df80a094fcad002a8fc2b37c5b8fe250b384be6; // eth_getProof (storageHash) - bytes32 latestBlockhash = keccak256(abi.encode(2)); - - // This proof was generated by running - // make devnet-up - // Then in another terminal - // packages/contracts/test/withdrawer.spec.ts - // Invalid large internal hash + 0x7f58036a634aca208c3e571f8306f314f83964313bc0725ceec76d839a097e79; // eth_getProof (storageHash) + bytes32 latestBlockhash = 0x0000000000000000000000000000000000000000000000000000000000000000; + bytes withdrawalProof = - hex"f879b853f8518080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28808080808080a0fc935bb380a99df15c4aae91dacba616986d33af599d458d5388fa5fec3ac80780808080808080a3e2a036125dacbefad1d42a65c3425f7b5c8b559dac475adb31578315e77ec70a3f9701"; + hex"e5a4e3a120453242a1d87fab6d401bd84b3d16c8d3f6a65142a069568067e7c2980af50e2801"; // we'll set this value in the `setUp` function and cache it here for reuse in each test WithdrawalVerifier.OutputRootProof outputRootProof; @@ -125,9 +113,15 @@ contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is DSTest { withdrawerStorageRoot: withdrawerStorageRoot, latestBlockhash: latestBlockhash }); + } function test_verifyWithdrawal() external { + // todo: get FFI working for this test + // string[] memory inputs = new string[](3); + // inputs[0] = "ts-node"; + // inputs[1] = "scripts/makeProof"; + // inputs[2] = string(abi.encode(wdNonce, wdSender, wdTarget, wdValue, wdGasLimit, wdData)); // Warp to after the finality window vm.warp(appendedTimestamp + 7 days); wr.finalizeWithdrawalTransaction( @@ -164,7 +158,7 @@ contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is DSTest { vm.warp(appendedTimestamp + 7 days); vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; - invalidOutpuRootProof.latestBlockhash = 0; + invalidOutpuRootProof.latestBlockhash = bytes32(hex"01"); wr.finalizeWithdrawalTransaction( wdNonce, wdSender, diff --git a/packages/contracts/contracts/test/Withdrawer.t.sol b/packages/contracts/contracts/test/Withdrawer.t.sol index 3836e79df8d4..fe53c91bc5a0 100644 --- a/packages/contracts/contracts/test/Withdrawer.t.sol +++ b/packages/contracts/contracts/test/Withdrawer.t.sol @@ -1,19 +1,19 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -import { DSTest } from "../../lib/ds-test/src/test.sol"; -import { Vm } from "../../lib/forge-std/src/Vm.sol"; +import { DSTest } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; import { Withdrawer } from "../L2/Withdrawer.sol"; import { AddressAliasHelper -} from "../../lib/optimism/packages/contracts/contracts/standards/AddressAliasHelper.sol"; +} from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; import { Lib_RLPWriter -} from "../../lib/optimism/packages/contracts/contracts/libraries/rlp/Lib_RLPWriter.sol"; +} from "@eth-optimism/contracts/libraries/rlp/Lib_RLPWriter.sol"; import { Lib_Bytes32Utils -} from "../../lib/optimism/packages/contracts/contracts/libraries/utils/Lib_Bytes32Utils.sol"; +} from "@eth-optimism/contracts/libraries/utils/Lib_Bytes32Utils.sol"; contract WithdrawerTestCommon is DSTest { diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml index f7b69a49b938..258788e3e239 100644 --- a/packages/contracts/foundry.toml +++ b/packages/contracts/foundry.toml @@ -5,3 +5,8 @@ src = 'contracts' out = 'forge-artifacts' optimizer = true optimizer_runs = 999999 +remappings = [ + '@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/', + '@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/', + '@eth-optimism/contracts/=node_modules/@eth-optimism/contracts/' +] diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index 0c07fe31f348..5f4c4dbb26d1 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -1,4 +1,5 @@ -import { HardhatUserConfig, task } from 'hardhat/config' +import { HardhatUserConfig, task, subtask } from 'hardhat/config' +import { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from 'hardhat/builtin-tasks/task-names' import '@nomiclabs/hardhat-waffle' import '@typechain/hardhat' import 'hardhat-gas-reporter' @@ -7,7 +8,15 @@ import 'hardhat-deploy' import './tasks/deposits' -task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { +subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction( + async (_, __, runSuper) => { + const paths = await runSuper() + + return paths.filter((p: string) => !p.endsWith('.t.sol')) + } +) + +task('accounts', 'Prints the list of accounts', async (_, hre) => { const accounts = await hre.ethers.getSigners() for (const account of accounts) { diff --git a/packages/contracts/helpers/constants.ts b/packages/contracts/helpers/constants.ts new file mode 100644 index 000000000000..f82f9483d074 --- /dev/null +++ b/packages/contracts/helpers/constants.ts @@ -0,0 +1,8 @@ +/** + * Predeploys are Solidity contracts that are injected into the initial L2 state and provide + * various useful functions. + */ +export const bedrockPredeploys = { + L1_BLOCK_ATTRIBUTES: '0x4200000000000000000000000000000000000015', + WITHDRAWER: '0x4200000000000000000000000000000000000016', +} diff --git a/packages/contracts/helpers/generateProofs.ts b/packages/contracts/helpers/generateProofs.ts new file mode 100644 index 000000000000..446edf0e82a7 --- /dev/null +++ b/packages/contracts/helpers/generateProofs.ts @@ -0,0 +1,101 @@ +import { ethers } from 'ethers' +import { toHexString } from '@eth-optimism/core-utils' + +import { TrieTestGenerator } from './trie-test-generator' +import { bedrockPredeploys } from './constants' + +interface WithdrawalArgs { + nonce: number + sender: string + target: string + value: number + gasLimit: number + data: string +} + +interface OutputRootProof { + version: string + stateRoot: string + withdrawerStorageRoot: string + latestBlockhash: string +} + +export const deriveWithdrawalHash = (wd: WithdrawalArgs): string => { + return ethers.utils.keccak256( + ethers.utils.defaultAbiCoder.encode( + ['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes'], + [wd.nonce, wd.sender, wd.target, wd.value, wd.gasLimit, wd.data] + ) + ) +} + +export const generateMockWithdrawalProof = async ( + wd: WithdrawalArgs | string +): Promise<{ + outputRootProof: OutputRootProof + storageTrieWitness: string +}> => { + let withdrawalHash + if (typeof wd == 'string') { + // wd should be an abi encoded string + withdrawalHash = ethers.utils.keccak256(wd) + } else { + withdrawalHash = deriveWithdrawalHash(wd as WithdrawalArgs) + } + + const storageKey = ethers.utils.keccak256( + ethers.utils.hexConcat([ + withdrawalHash, + ethers.utils.hexZeroPad('0x01', 32), + ]) + ) + + const storageGenerator = await TrieTestGenerator.fromNodes({ + nodes: [ + { + key: storageKey, + val: '0x' + '01'.padStart(2, '0'), + }, + ], + secure: true, + }) + + const generator = await TrieTestGenerator.fromAccounts({ + accounts: [ + { + address: bedrockPredeploys.WITHDRAWER, + nonce: 0, + balance: 0, + codeHash: ethers.utils.keccak256('0x1234'), + storageRoot: toHexString(storageGenerator._trie.root), + }, + ], + secure: true, + }) + + return { + outputRootProof: { + version: ethers.constants.HashZero, + stateRoot: toHexString(generator._trie.root), + withdrawerStorageRoot: toHexString(storageGenerator._trie.root), + latestBlockhash: ethers.constants.HashZero, + }, + storageTrieWitness: ( + await storageGenerator.makeInclusionProofTest(storageKey) + ).proof, + } +} + +export const generateOutputRoot = (outputElements: { + version: string + stateRoot: string + withdrawerStorageRoot: string + latestBlockhash: string +}) => { + const { version, stateRoot, withdrawerStorageRoot, latestBlockhash } = + outputElements + return ethers.utils.solidityKeccak256( + ['bytes32', 'bytes32', 'bytes32', 'bytes32'], + [version, stateRoot, withdrawerStorageRoot, latestBlockhash] + ) +} diff --git a/packages/contracts/helpers/index.ts b/packages/contracts/helpers/index.ts index 639f068d0830..4ea5798fa772 100644 --- a/packages/contracts/helpers/index.ts +++ b/packages/contracts/helpers/index.ts @@ -1,216 +1,3 @@ -import * as RLP from '@ethersproject/rlp' -import { BigNumber, BigNumberish } from '@ethersproject/bignumber' -import { getAddress } from '@ethersproject/address' -import { - hexConcat, - stripZeros, - zeroPad, - arrayify, - BytesLike, -} from '@ethersproject/bytes' -import { keccak256 } from '@ethersproject/keccak256' -import { Zero } from '@ethersproject/constants' -import { ContractReceipt, Event } from '@ethersproject/contracts' - -function formatNumber(value: BigNumberish, name: string): Uint8Array { - const result = stripZeros(BigNumber.from(value).toHexString()) - if (result.length > 32) { - throw new Error(`invalid length for ${name}`) - } - return result -} - -function handleNumber(value: string): BigNumber { - if (value === '0x') { - return Zero - } - return BigNumber.from(value) -} - -function handleAddress(value: string): string { - if (value === '0x') { - // @ts-ignore - return null - } - return getAddress(value) -} - -export enum SourceHashDomain { - UserDeposit = 0, - L1InfoDeposit = 1, -} - -interface DepositTxOpts { - sourceHash?: string - from: string - to: string | null - mint: BigNumberish - value: BigNumberish - gas: BigNumberish - data: string - domain?: SourceHashDomain - l1BlockHash?: string - logIndex?: BigNumberish - sequenceNumber?: BigNumberish -} - -interface DepostTxExtraOpts { - domain?: SourceHashDomain - l1BlockHash?: string - logIndex?: BigNumberish - sequenceNumber?: BigNumberish -} - -export class DepositTx { - public type = '0x7E' - private _sourceHash?: string - public from: string - public to: string | null - public mint: BigNumberish - public value: BigNumberish - public gas: BigNumberish - public data: BigNumberish - - public domain?: SourceHashDomain - public l1BlockHash?: string - public logIndex?: BigNumberish - public sequenceNumber?: BigNumberish - - constructor(opts: Partial = {}) { - this._sourceHash = opts.sourceHash - this.from = opts.from! - this.to = opts.to! - this.mint = opts.mint! - this.value = opts.value! - this.gas = opts.gas! - this.data = opts.data! - this.domain = opts.domain - this.l1BlockHash = opts.l1BlockHash - this.logIndex = opts.logIndex - this.sequenceNumber = opts.sequenceNumber - } - - hash() { - const encoded = this.encode() - return keccak256(encoded) - } - - sourceHash() { - if (!this._sourceHash) { - let marker: string - switch (this.domain) { - case SourceHashDomain.UserDeposit: - marker = BigNumber.from(this.logIndex).toHexString() - break - case SourceHashDomain.L1InfoDeposit: - marker = BigNumber.from(this.sequenceNumber).toHexString() - break - default: - throw new Error(`Unknown domain: ${this.domain}`) - } - - if (!this.l1BlockHash) { - throw new Error('Need l1BlockHash to compute sourceHash') - } - - const l1BlockHash = this.l1BlockHash - const input = hexConcat([l1BlockHash, zeroPad(marker, 32)]) - const depositIDHash = keccak256(input) - const domain = BigNumber.from(this.domain).toHexString() - const domainInput = hexConcat([zeroPad(domain, 32), depositIDHash]) - this._sourceHash = keccak256(domainInput) - } - return this._sourceHash - } - - encode() { - const fields: any = [ - this.sourceHash() || '0x', - getAddress(this.from) || '0x', - this.to != null ? getAddress(this.to) : '0x', - formatNumber(this.mint || 0, 'mint'), - formatNumber(this.value || 0, 'value'), - formatNumber(this.gas || 0, 'gas'), - this.data || '0x', - ] - - return hexConcat([this.type, RLP.encode(fields)]) - } - - decode(raw: BytesLike, extra: DepostTxExtraOpts = {}) { - const payload = arrayify(raw) - const transaction = RLP.decode(payload.slice(1)) - - this._sourceHash = transaction[0] - this.from = handleAddress(transaction[1]) - this.to = handleAddress(transaction[2]) - this.mint = handleNumber(transaction[3]) - this.value = handleNumber(transaction[4]) - this.gas = handleNumber(transaction[5]) - this.data = transaction[6] - - if ('l1BlockHash' in extra) { - this.l1BlockHash = extra.l1BlockHash - } - if ('domain' in extra) { - this.domain = extra.domain - } - if ('logIndex' in extra) { - this.logIndex = extra.logIndex - } - if ('sequenceNumber' in extra) { - this.sequenceNumber = extra.sequenceNumber - } - return this - } - - static decode(raw: BytesLike, extra?: DepostTxExtraOpts): DepositTx { - return new this().decode(raw, extra) - } - - fromL1Receipt(receipt: ContractReceipt, index: number): DepositTx { - if (!receipt.events) throw new Error('cannot parse receipt') - const event = receipt.events[index] - if (!event) { - throw new Error(`event index ${index} does not exist`) - } - return this.fromL1Event(event) - } - - static fromL1Receipt(receipt: ContractReceipt, index: number): DepositTx { - return new this({}).fromL1Receipt(receipt, index) - } - - fromL1Event(event: Event): DepositTx { - if (event.event !== 'TransactionDeposited') - throw new Error(`incorrect event type: ${event.event}`) - if (typeof event.args === 'undefined') throw new Error('no event args') - if (typeof event.args.from === 'undefined') - throw new Error('"from" undefined') - this.from = event.args.from - if (typeof event.args.isCreation === 'undefined') - throw new Error('"isCreation" undefined') - if (typeof event.args.to === 'undefined') throw new Error('"to" undefined') - this.to = event.args.isCreation ? null : event.args.to - if (typeof event.args.mint === 'undefined') - throw new Error('"mint" undefined') - this.mint = event.args.mint - if (typeof event.args.value === 'undefined') - throw new Error('"value" undefined') - this.value = event.args.value - if (typeof event.args.gasLimit === 'undefined') - throw new Error('"gasLimit" undefined') - this.gas = event.args.gasLimit - if (typeof event.args.data === 'undefined') - throw new Error('"data" undefined') - this.data = event.args.data - this.domain = SourceHashDomain.UserDeposit - this.l1BlockHash = event.blockHash - this.logIndex = event.logIndex - return this - } - - static fromL1Event(event: Event): DepositTx { - return new this({}).fromL1Event(event) - } -} +export * from './utils' +export * from './generateProofs' +export * from './constants' diff --git a/packages/contracts/helpers/trie-test-generator.ts b/packages/contracts/helpers/trie-test-generator.ts new file mode 100644 index 000000000000..8e5bd6caed1b --- /dev/null +++ b/packages/contracts/helpers/trie-test-generator.ts @@ -0,0 +1,261 @@ +/* External Imports */ +import * as rlp from 'rlp' +// import { default as seedbytes } from 'random-bytes-seed' +import { SecureTrie, BaseTrie } from 'merkle-patricia-tree' +import { fromHexString, toHexString } from '@eth-optimism/core-utils' +import { ethers } from 'ethers' + +interface TrieNode { + key: string + val: string +} + +interface InclusionProofTest { + key: string + val: string + proof: string + root: string +} + +interface NodeUpdateTest extends InclusionProofTest { + newRoot: string +} + +interface EthereumAccount { + address?: string + nonce: number + balance: number + codeHash: string + storageRoot?: string + storage?: TrieNode[] +} + +interface AccountProofTest { + address: string + account: EthereumAccount + accountTrieWitness: string + accountTrieRoot: string +} + +interface AccountUpdateTest extends AccountProofTest { + newAccountTrieRoot: string +} + +const rlpEncodeAccount = (account: EthereumAccount): string => { + return toHexString( + rlp.encode([ + account.nonce, + account.balance, + account.storageRoot || ethers.constants.HashZero, + account.codeHash || ethers.constants.HashZero, + ]) + ) +} + +const rlpDecodeAccount = (encoded: string): EthereumAccount => { + const decoded = rlp.decode(fromHexString(encoded)) as any + return { + nonce: decoded[0].length ? parseInt(decoded[0], 16) : 0, + balance: decoded[1].length ? parseInt(decoded[1], 16) : 0, + storageRoot: decoded[2].length + ? toHexString(decoded[2]) + : ethers.constants.HashZero, + codeHash: decoded[3].length + ? toHexString(decoded[3]) + : ethers.constants.HashZero, + } +} + +const makeTrie = async ( + nodes: TrieNode[], + secure?: boolean +): Promise<{ + trie: SecureTrie | BaseTrie + TrieClass: any +}> => { + const TrieClass = secure ? SecureTrie : BaseTrie + const trie = new TrieClass() + + for (const node of nodes) { + await trie.put(fromHexString(node.key), fromHexString(node.val)) + } + + return { + trie, + TrieClass, + } +} + +export class TrieTestGenerator { + constructor( + public _TrieClass: any, + public _trie: SecureTrie | BaseTrie, + public _nodes: TrieNode[], + public _subGenerators?: TrieTestGenerator[] + ) {} + + static async fromNodes(opts: { + nodes: TrieNode[] + secure?: boolean + }): Promise { + const { trie, TrieClass } = await makeTrie(opts.nodes, opts.secure) + + return new TrieTestGenerator(TrieClass, trie, opts.nodes) + } + + // static async fromRandom(opts: { + // seed: string + // nodeCount: number + // secure?: boolean + // keySize?: number + // valSize?: number + // }): Promise { + // const getRandomBytes = seedbytes(opts.seed) + // const nodes: TrieNode[] = [...Array(opts.nodeCount)].map(() => { + // return { + // key: toHexString(getRandomBytes(opts.keySize || 32)), + // val: toHexString(getRandomBytes(opts.valSize || 32)), + // } + // }) + + // return TrieTestGenerator.fromNodes({ + // nodes, + // secure: opts.secure, + // }) + // } + + static async fromAccounts(opts: { + accounts: EthereumAccount[] + secure?: boolean + }): Promise { + const subGenerators: TrieTestGenerator[] = [] + + for (const account of opts.accounts) { + if (account.storage) { + const subGenerator = await TrieTestGenerator.fromNodes({ + nodes: account.storage, + secure: opts.secure, + }) + + account.storageRoot = toHexString(subGenerator._trie.root) + subGenerators.push(subGenerator) + } + } + + const nodes = opts.accounts.map((account) => { + return { + key: account.address as string, + val: rlpEncodeAccount(account), + } + }) + + const { trie, TrieClass } = await makeTrie(nodes, opts.secure) + + return new TrieTestGenerator(TrieClass, trie, nodes, subGenerators) + } + + public async makeInclusionProofTest( + key: string | number + ): Promise { + if (typeof key === 'number') { + key = this._nodes[key].key + } + + const trie = this._trie.copy() + + const proof = await this.prove(key) + const val = await trie.get(fromHexString(key)) + + return { + proof: toHexString(rlp.encode(proof)), + key: toHexString(key), + val: toHexString(val), + root: toHexString(trie.root), + } + } + + public async makeAllInclusionProofTests(): Promise { + return Promise.all( + this._nodes.map(async (node) => { + return this.makeInclusionProofTest(node.key) + }) + ) + } + + public async makeNodeUpdateTest( + key: string | number, + val: string + ): Promise { + if (typeof key === 'number') { + key = this._nodes[key].key + } + + const trie = this._trie.copy() + + const proof = await this.prove(key) + const oldRoot = trie.root + + await trie.put(fromHexString(key), fromHexString(val)) + const newRoot = trie.root + + return { + proof: toHexString(rlp.encode(proof)), + key: toHexString(key), + val: toHexString(val), + root: toHexString(oldRoot), + newRoot: toHexString(newRoot), + } + } + + public async makeAccountProofTest( + address: string | number + ): Promise { + if (typeof address === 'number') { + address = this._nodes[address].key + } + + const trie = this._trie.copy() + + const proof = await this.prove(address) + const account = await trie.get(fromHexString(address)) + + return { + address, + account: rlpDecodeAccount(toHexString(account)), + accountTrieWitness: toHexString(rlp.encode(proof)), + accountTrieRoot: toHexString(trie.root), + } + } + + public async makeAccountUpdateTest( + address: string | number, + account: EthereumAccount + ): Promise { + if (typeof address === 'number') { + address = this._nodes[address].key + } + + const trie = this._trie.copy() + + const proof = await this.prove(address) + const oldRoot = trie.root + + await trie.put( + fromHexString(address), + fromHexString(rlpEncodeAccount(account)) + ) + const newRoot = trie.root + + return { + address, + account, + accountTrieWitness: toHexString(rlp.encode(proof)), + accountTrieRoot: toHexString(oldRoot), + newAccountTrieRoot: toHexString(newRoot), + } + } + + private async prove(key: string): Promise { + return this._TrieClass.prove(this._trie, fromHexString(key)) + } +} diff --git a/packages/contracts/helpers/utils.ts b/packages/contracts/helpers/utils.ts new file mode 100644 index 000000000000..639f068d0830 --- /dev/null +++ b/packages/contracts/helpers/utils.ts @@ -0,0 +1,216 @@ +import * as RLP from '@ethersproject/rlp' +import { BigNumber, BigNumberish } from '@ethersproject/bignumber' +import { getAddress } from '@ethersproject/address' +import { + hexConcat, + stripZeros, + zeroPad, + arrayify, + BytesLike, +} from '@ethersproject/bytes' +import { keccak256 } from '@ethersproject/keccak256' +import { Zero } from '@ethersproject/constants' +import { ContractReceipt, Event } from '@ethersproject/contracts' + +function formatNumber(value: BigNumberish, name: string): Uint8Array { + const result = stripZeros(BigNumber.from(value).toHexString()) + if (result.length > 32) { + throw new Error(`invalid length for ${name}`) + } + return result +} + +function handleNumber(value: string): BigNumber { + if (value === '0x') { + return Zero + } + return BigNumber.from(value) +} + +function handleAddress(value: string): string { + if (value === '0x') { + // @ts-ignore + return null + } + return getAddress(value) +} + +export enum SourceHashDomain { + UserDeposit = 0, + L1InfoDeposit = 1, +} + +interface DepositTxOpts { + sourceHash?: string + from: string + to: string | null + mint: BigNumberish + value: BigNumberish + gas: BigNumberish + data: string + domain?: SourceHashDomain + l1BlockHash?: string + logIndex?: BigNumberish + sequenceNumber?: BigNumberish +} + +interface DepostTxExtraOpts { + domain?: SourceHashDomain + l1BlockHash?: string + logIndex?: BigNumberish + sequenceNumber?: BigNumberish +} + +export class DepositTx { + public type = '0x7E' + private _sourceHash?: string + public from: string + public to: string | null + public mint: BigNumberish + public value: BigNumberish + public gas: BigNumberish + public data: BigNumberish + + public domain?: SourceHashDomain + public l1BlockHash?: string + public logIndex?: BigNumberish + public sequenceNumber?: BigNumberish + + constructor(opts: Partial = {}) { + this._sourceHash = opts.sourceHash + this.from = opts.from! + this.to = opts.to! + this.mint = opts.mint! + this.value = opts.value! + this.gas = opts.gas! + this.data = opts.data! + this.domain = opts.domain + this.l1BlockHash = opts.l1BlockHash + this.logIndex = opts.logIndex + this.sequenceNumber = opts.sequenceNumber + } + + hash() { + const encoded = this.encode() + return keccak256(encoded) + } + + sourceHash() { + if (!this._sourceHash) { + let marker: string + switch (this.domain) { + case SourceHashDomain.UserDeposit: + marker = BigNumber.from(this.logIndex).toHexString() + break + case SourceHashDomain.L1InfoDeposit: + marker = BigNumber.from(this.sequenceNumber).toHexString() + break + default: + throw new Error(`Unknown domain: ${this.domain}`) + } + + if (!this.l1BlockHash) { + throw new Error('Need l1BlockHash to compute sourceHash') + } + + const l1BlockHash = this.l1BlockHash + const input = hexConcat([l1BlockHash, zeroPad(marker, 32)]) + const depositIDHash = keccak256(input) + const domain = BigNumber.from(this.domain).toHexString() + const domainInput = hexConcat([zeroPad(domain, 32), depositIDHash]) + this._sourceHash = keccak256(domainInput) + } + return this._sourceHash + } + + encode() { + const fields: any = [ + this.sourceHash() || '0x', + getAddress(this.from) || '0x', + this.to != null ? getAddress(this.to) : '0x', + formatNumber(this.mint || 0, 'mint'), + formatNumber(this.value || 0, 'value'), + formatNumber(this.gas || 0, 'gas'), + this.data || '0x', + ] + + return hexConcat([this.type, RLP.encode(fields)]) + } + + decode(raw: BytesLike, extra: DepostTxExtraOpts = {}) { + const payload = arrayify(raw) + const transaction = RLP.decode(payload.slice(1)) + + this._sourceHash = transaction[0] + this.from = handleAddress(transaction[1]) + this.to = handleAddress(transaction[2]) + this.mint = handleNumber(transaction[3]) + this.value = handleNumber(transaction[4]) + this.gas = handleNumber(transaction[5]) + this.data = transaction[6] + + if ('l1BlockHash' in extra) { + this.l1BlockHash = extra.l1BlockHash + } + if ('domain' in extra) { + this.domain = extra.domain + } + if ('logIndex' in extra) { + this.logIndex = extra.logIndex + } + if ('sequenceNumber' in extra) { + this.sequenceNumber = extra.sequenceNumber + } + return this + } + + static decode(raw: BytesLike, extra?: DepostTxExtraOpts): DepositTx { + return new this().decode(raw, extra) + } + + fromL1Receipt(receipt: ContractReceipt, index: number): DepositTx { + if (!receipt.events) throw new Error('cannot parse receipt') + const event = receipt.events[index] + if (!event) { + throw new Error(`event index ${index} does not exist`) + } + return this.fromL1Event(event) + } + + static fromL1Receipt(receipt: ContractReceipt, index: number): DepositTx { + return new this({}).fromL1Receipt(receipt, index) + } + + fromL1Event(event: Event): DepositTx { + if (event.event !== 'TransactionDeposited') + throw new Error(`incorrect event type: ${event.event}`) + if (typeof event.args === 'undefined') throw new Error('no event args') + if (typeof event.args.from === 'undefined') + throw new Error('"from" undefined') + this.from = event.args.from + if (typeof event.args.isCreation === 'undefined') + throw new Error('"isCreation" undefined') + if (typeof event.args.to === 'undefined') throw new Error('"to" undefined') + this.to = event.args.isCreation ? null : event.args.to + if (typeof event.args.mint === 'undefined') + throw new Error('"mint" undefined') + this.mint = event.args.mint + if (typeof event.args.value === 'undefined') + throw new Error('"value" undefined') + this.value = event.args.value + if (typeof event.args.gasLimit === 'undefined') + throw new Error('"gasLimit" undefined') + this.gas = event.args.gasLimit + if (typeof event.args.data === 'undefined') + throw new Error('"data" undefined') + this.data = event.args.data + this.domain = SourceHashDomain.UserDeposit + this.l1BlockHash = event.blockHash + this.logIndex = event.logIndex + return this + } + + static fromL1Event(event: Event): DepositTx { + return new this({}).fromL1Event(event) + } +} diff --git a/packages/contracts/lib/ds-test b/packages/contracts/lib/ds-test deleted file mode 160000 index 0a5da56b0d65..000000000000 --- a/packages/contracts/lib/ds-test +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0a5da56b0d65960e6a994d2ec8245e6edd38c248 diff --git a/packages/contracts/lib/forge-std b/packages/contracts/lib/forge-std index d880879a97ce..6fddb7693357 160000 --- a/packages/contracts/lib/forge-std +++ b/packages/contracts/lib/forge-std @@ -1 +1 @@ -Subproject commit d880879a97cea1857688c13a6ceb869ef48d715f +Subproject commit 6fddb76933574420f769ff7ea367aed578e962a8 diff --git a/packages/contracts/lib/openzeppelin-contracts b/packages/contracts/lib/openzeppelin-contracts deleted file mode 160000 index 52eeebecda14..000000000000 --- a/packages/contracts/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52eeebecda140ebaf4ec8752ed119d8288287fac diff --git a/packages/contracts/lib/optimism b/packages/contracts/lib/optimism deleted file mode 160000 index 70897fa47ea3..000000000000 --- a/packages/contracts/lib/optimism +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 70897fa47ea35f288fd6c1bb6c2eef6c45594761 diff --git a/packages/contracts/lib/solmate b/packages/contracts/lib/solmate new file mode 160000 index 000000000000..290c4eb22b3d --- /dev/null +++ b/packages/contracts/lib/solmate @@ -0,0 +1 @@ +Subproject commit 290c4eb22b3d578d6acdc33a95bf65c297ac7216 diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 7b65a75b5a52..61463249eb30 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -5,12 +5,16 @@ "main": "index.js", "license": "MIT", "dependencies": { + "@eth-optimism/contracts": "^0.5.21", "@ethersproject/address": "^5.6.0", "@ethersproject/bignumber": "^5.6.0", "@ethersproject/bytes": "^5.6.1", "@ethersproject/keccak256": "^5.6.0", "@ethersproject/rlp": "^5.6.0", + "@openzeppelin/contracts": "^4.5.0", + "@openzeppelin/contracts-upgradeable": "^4.5.2", "hardhat": "^2.7.1", + "merkle-patricia-tree": "^4.2.4", "rlp": "^2.2.7" }, "scripts": { diff --git a/packages/contracts/scripts/ffiMakeProof.ts b/packages/contracts/scripts/ffiMakeProof.ts new file mode 100644 index 000000000000..0180f82fe323 --- /dev/null +++ b/packages/contracts/scripts/ffiMakeProof.ts @@ -0,0 +1,18 @@ +// Script for generating an inclusion proof for use in testing +// Intended for use with forge test --ffi, accepts abi encoded input and returns +// only the storageTrieWitness. +import { generateMockWithdrawalProof } from '../helpers' + +let args = process.argv.slice(2)[0] + +args = args + .replace('0x', '') + .split('') + .filter((char) => '0123456789abcdef'.includes(char)) + .join('') + +const main = async () => { + const proof = await generateMockWithdrawalProof('0x' + args) + console.log(proof.storageTrieWitness.slice(2)) +} +main() diff --git a/packages/contracts/scripts/makeProof.ts b/packages/contracts/scripts/makeProof.ts new file mode 100644 index 000000000000..09989e90aaaf --- /dev/null +++ b/packages/contracts/scripts/makeProof.ts @@ -0,0 +1,21 @@ +// Script for generating an inclusion proof for use in testing. +// Meant for manual usage, ie. +// ts-node scripts/makeProof.ts 1 0x0000000000000000000000000000000000000002 0x0000000000000000000000000000000000000003 4 500000 0x06 +import { generateMockWithdrawalProof } from '../helpers' + +const args = process.argv.slice(2) + +const [nonce, sender, target, value, gasLimit, data] = args + +const main = async () => { + const proof = await generateMockWithdrawalProof({ + nonce: +nonce, + sender, + target, + value: +value, + gasLimit: +gasLimit, + data, + }) + console.log(proof) +} +main() diff --git a/packages/contracts/test/withdrawer.spec.ts b/packages/contracts/test/withdrawer.spec.ts deleted file mode 100644 index f14dbea972fa..000000000000 --- a/packages/contracts/test/withdrawer.spec.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { expect } from 'chai' -import { Signer, BigNumber, Wallet, providers, ethers, utils } from 'ethers' -import { - Withdrawer, - Withdrawer__factory, - TestLibSecureMerkleTrie, - TestLibSecureMerkleTrie__factory, - WithdrawalVerifier, - WithdrawalVerifier__factory, - L2OutputOracle, - L2OutputOracle__factory, -} from '../typechain' -import { toRpcHexString, toHexString, Address } from '@eth-optimism/core-utils' -import * as rlp from 'rlp' - -const l2GethProvider = new providers.JsonRpcProvider('http://localhost:9545') -const l1GethProvider = new providers.JsonRpcProvider('http://localhost:8545') - -const withdrawerAddress = '0x4200000000000000000000000000000000000016' - -const NON_ZERO_ADDRESS = '0x' + '11'.repeat(20) -const NON_ZERO_GASLIMIT = BigNumber.from(50_000) -const NON_ZERO_DATA = '0x' + '11'.repeat(42) - -if (!process.env.PRIVATE_KEY) { - throw new Error('You must define PRIVATE_KEY in your environment.') -} - -const encodeWithdrawal = (args: { - nonce: BigNumber | number - sender: string - target: string - value: BigNumber | number - gasLimit: BigNumber | number - data: string -}): string => { - return ethers.utils.defaultAbiCoder.encode( - ['uint256', 'address', 'address', 'uint256', 'uint256', 'bytes'], - [ - utils.hexZeroPad(BigNumber.from(args.nonce).toHexString(), 32), - args.sender, - args.target, - utils.hexZeroPad(BigNumber.from(args.value).toHexString(), 32), - utils.hexZeroPad(BigNumber.from(args.gasLimit).toHexString(), 32), - args.data, - ] - ) -} - -describe('Withdraw', () => { - let wallet: Wallet - let signerAddress: string - let l1Signer: Signer - let l2Signer: Signer - let withdrawer: Withdrawer - let testLibSecureMerkleTrie: TestLibSecureMerkleTrie - let proof: any - let nonceBefore: BigNumber - - before('Setup L2 withdrawer contract', async () => { - wallet = new Wallet(process.env.PRIVATE_KEY!) - signerAddress = await wallet.getAddress() - l1Signer = wallet.connect(l1GethProvider) - l2Signer = wallet.connect(l2GethProvider) - - withdrawer = await new Withdrawer__factory(l2Signer).attach( - withdrawerAddress - ) - - testLibSecureMerkleTrie = await ( - await new TestLibSecureMerkleTrie__factory(l2Signer) - ).deploy() - }) - - describe('Creating a withdrawal on L2', () => { - let withdrawalHash: string - let storageKey: string - before(async () => { - nonceBefore = await withdrawer.nonce() - - await ( - await withdrawer.initiateWithdrawal( - NON_ZERO_ADDRESS, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA - ) - ).wait() - - // locally calculate the expected mapping key - withdrawalHash = ethers.utils.keccak256( - encodeWithdrawal({ - nonce: nonceBefore, - sender: await l2Signer.getAddress(), - target: NON_ZERO_ADDRESS, - value: 0, - gasLimit: NON_ZERO_GASLIMIT, - data: NON_ZERO_DATA, - }) - ) - }) - - it('Should add an entry to the withdrawals mapping', async () => { - const nonceAfter = await withdrawer.nonce() - expect(await withdrawer.withdrawals(withdrawalHash)).to.be.true - expect(nonceAfter.sub(nonceBefore).toNumber()).to.eq(1) - }) - - // Test to ensure we're correctly calculating the storageKey. Per the solidity docs: - // "The value corresponding to a mapping key k is located at keccak256(h(k) . p) where . is - // concatenation and h is a function that is applied to the key..." - it('Should return bytes32(1) when querying the calculated storage key', async () => { - const storageSlot = '00'.repeat(31) + '01' // i.e the second variable declared in the contract - storageKey = ethers.utils.keccak256(withdrawalHash + storageSlot) - - expect( - await l2GethProvider.getStorageAt(withdrawerAddress, storageKey) - ).to.equal(utils.hexZeroPad('0x01', 32)) - }) - - it('should generate a valid proof', async () => { - // Get the proof - proof = await l2GethProvider.send('eth_getProof', [ - withdrawerAddress, - [storageKey], - toRpcHexString((await l2GethProvider.getBlock('latest')).number), - ]) - - // Sanity check expected values of the proof - expect(proof.storageProof[0].key).to.eq(storageKey) - expect(proof.storageProof[0].value).to.eq('0x1') - - // Check the proof directly against the SecureMerkleTrie lib - expect( - await testLibSecureMerkleTrie.verifyInclusionProof( - proof.storageProof[0].key, - '0x01', - toHexString(rlp.encode(proof.storageProof[0].proof)), - proof.storageHash - ) - ).to.be.true - }) - }) - - describe('Finalizing a withdrawal on L1', () => { - let withdrawalVerifier: WithdrawalVerifier - let l2OutputOracle: L2OutputOracle - let l2Timestamp: BigNumber - before('Setup L1 system contracts', async () => { - // Deploy the L2 Output Oracle with a 1 second submission interval so that we can immediately - // test the withdrawal. - l2OutputOracle = await ( - await new L2OutputOracle__factory(l1Signer) - ).deploy( - 1, // submissionInterval - 1, // l2BlockTime - ethers.utils.keccak256('0x00'), // genesisL2Output - 100, // historicalTotalBlocks - signerAddress - ) - - // Deploy the WithdrawalVerifier with a 0 second finalization delay. - withdrawalVerifier = await ( - await new WithdrawalVerifier__factory(l1Signer) - ).deploy(l2OutputOracle.address, 0) - - // create an output root that we can prove against only the storage root matters - // for our purposes. - const outputRoot = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'bytes32', 'bytes32', 'bytes32'], - [ - ethers.constants.HashZero, - ethers.constants.HashZero, - proof.storageHash, - ethers.constants.HashZero, - ] - ) - ) - - l2Timestamp = await l2OutputOracle.nextTimestamp() - await l2OutputOracle.appendL2Output( - outputRoot, - l2Timestamp, - ethers.constants.HashZero, - 0 - ) - }) - - it('should successfully verify the withdrawal on L1', async () => { - const tx = await withdrawalVerifier.verifyWithdrawal( - nonceBefore, - signerAddress, - NON_ZERO_ADDRESS, - 0, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA, - { - timestamp: l2Timestamp, - version: ethers.constants.HashZero, - stateRoot: ethers.constants.HashZero, - withdrawerStorageRoot: proof.storageHash, - latestBlockhash: ethers.constants.HashZero, - }, - toHexString(rlp.encode(proof.storageProof[0].proof)), - { - gasLimit: 1_000_000, - } - ) - const events: any = (await tx.wait()).events - expect(events[0].event).to.equal('WithdrawalVerified') - }) - }).timeout(30000) -}) diff --git a/packages/contracts/yarn.lock b/packages/contracts/yarn.lock index 145a6a6282a9..ffa4115fe6e4 100644 --- a/packages/contracts/yarn.lock +++ b/packages/contracts/yarn.lock @@ -73,6 +73,30 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@eth-optimism/contracts@^0.5.21": + version "0.5.21" + resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.5.21.tgz#8f7d4ab8ca19fce9f4e18397a4b7c94e5c86e169" + integrity sha512-cVHL95buBeeeHxA35g9Dz9zauw9XNOBgcFNDOkKm/3HGNyOlmcfkjZbSlxfAUzUrmXE1EdQz+Y9nLd05GHI6gw== + dependencies: + "@eth-optimism/core-utils" "0.8.3" + "@ethersproject/abstract-provider" "^5.5.1" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/hardware-wallets" "^5.5.0" + +"@eth-optimism/core-utils@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.8.3.tgz#226d6ac4cb80bd165d64f5ffa4f3e0b300568678" + integrity sha512-jM3dPAg9TinskLyH4w9KofEqgLWJsf5VrlC8a2/0zKNlZUJuVzE/ZYfcq243qqlJn1vb4QkBKjYVHKMu1Wjzjg== + dependencies: + "@ethersproject/abstract-provider" "^5.5.1" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/providers" "^5.5.3" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.1" + bufio "^1.0.7" + chai "^4.3.4" + ethers "^5.5.4" + "@eth-optimism/core-utils@^0.7.3": version "0.7.3" resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.7.3.tgz#67a7ec3cd65a555c6b5ef50d03ea66aa8df9f6c8" @@ -253,6 +277,21 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/abi@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.1.tgz#f7de888edeb56b0a657b672bdd1b3a1135cd14f7" + integrity sha512-0cqssYh6FXjlwKWBmLm3+zH2BNARoS5u/hxbz+LpQmcDB3w0W553h2btWui1/uZp2GBM/SI3KniTuMcYyHpA5w== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.0.tgz#ea07cbc1eec2374d32485679c12408005895e9f3" @@ -281,7 +320,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/web" "^5.5.0" -"@ethersproject/abstract-provider@^5.6.0": +"@ethersproject/abstract-provider@5.6.0", "@ethersproject/abstract-provider@^5.5.1", "@ethersproject/abstract-provider@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz#0c4ac7054650dbd9c476cf5907f588bbb6ef3061" integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== @@ -305,7 +344,7 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/properties" "^5.5.0" -"@ethersproject/abstract-signer@^5.4.1", "@ethersproject/abstract-signer@^5.6.0": +"@ethersproject/abstract-signer@5.6.0", "@ethersproject/abstract-signer@^5.4.1", "@ethersproject/abstract-signer@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz#9cd7ae9211c2b123a3b29bf47aab17d4d016e3e7" integrity sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ== @@ -327,7 +366,7 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/rlp" "^5.5.0" -"@ethersproject/address@^5.4.0", "@ethersproject/address@^5.6.0": +"@ethersproject/address@5.6.0", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== @@ -345,7 +384,7 @@ dependencies: "@ethersproject/bytes" "^5.5.0" -"@ethersproject/base64@^5.6.0": +"@ethersproject/base64@5.6.0", "@ethersproject/base64@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.0.tgz#a12c4da2a6fb86d88563216b0282308fc15907c9" integrity sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw== @@ -360,7 +399,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/properties" "^5.5.0" -"@ethersproject/basex@^5.6.0": +"@ethersproject/basex@5.6.0", "@ethersproject/basex@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.0.tgz#9ea7209bf0a1c3ddc2a90f180c3a7f0d7d2e8a69" integrity sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ== @@ -377,7 +416,7 @@ "@ethersproject/logger" "^5.5.0" bn.js "^4.11.9" -"@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.6.0": +"@ethersproject/bignumber@5.6.0", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.0.tgz#116c81b075c57fa765a8f3822648cf718a8a0e26" integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== @@ -393,7 +432,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.6.0", "@ethersproject/bytes@^5.6.1": +"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.6.0", "@ethersproject/bytes@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== @@ -407,7 +446,7 @@ dependencies: "@ethersproject/bignumber" "^5.5.0" -"@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.6.0": +"@ethersproject/constants@5.6.0", "@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.0.tgz#55e3eb0918584d3acc0688e9958b0cedef297088" integrity sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA== @@ -430,7 +469,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/transactions" "^5.5.0" -"@ethersproject/contracts@^5.4.1": +"@ethersproject/contracts@5.6.0", "@ethersproject/contracts@^5.4.1": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.0.tgz#60f2cfc7addd99a865c6c8cfbbcec76297386067" integrity sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw== @@ -446,6 +485,18 @@ "@ethersproject/properties" "^5.6.0" "@ethersproject/transactions" "^5.6.0" +"@ethersproject/hardware-wallets@^5.5.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hardware-wallets/-/hardware-wallets-5.6.0.tgz#10176a4e8dfc2c5d691410547ebb9dec53ce9f3a" + integrity sha512-jq/9osE7mfH6Ur4/N2/EdrgRuXacXlCzp5Irvyy8sWM3xMuzg2Git8czEFdFFTfLO6IBVxfEi1ANb+76tsa8BA== + dependencies: + "@ledgerhq/hw-app-eth" "5.27.2" + "@ledgerhq/hw-transport" "5.26.0" + "@ledgerhq/hw-transport-u2f" "5.26.0" + ethers "^5.6.0" + optionalDependencies: + "@ledgerhq/hw-transport-node-hid" "5.26.0" + "@ethersproject/hash@5.5.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" @@ -460,7 +511,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/hash@^5.6.0": +"@ethersproject/hash@5.6.0", "@ethersproject/hash@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.0.tgz#d24446a5263e02492f9808baa99b6e2b4c3429a2" integrity sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA== @@ -492,7 +543,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" -"@ethersproject/hdnode@^5.6.0": +"@ethersproject/hdnode@5.6.0", "@ethersproject/hdnode@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.0.tgz#9dcbe8d629bbbcf144f2cae476337fe92d320998" integrity sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw== @@ -529,7 +580,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/json-wallets@^5.6.0": +"@ethersproject/json-wallets@5.6.0", "@ethersproject/json-wallets@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz#4c2fc27f17e36c583e7a252fb938bc46f98891e5" integrity sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ== @@ -556,7 +607,7 @@ "@ethersproject/bytes" "^5.5.0" js-sha3 "0.8.0" -"@ethersproject/keccak256@^5.6.0": +"@ethersproject/keccak256@5.6.0", "@ethersproject/keccak256@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.0.tgz#fea4bb47dbf8f131c2e1774a1cecbfeb9d606459" integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== @@ -569,7 +620,7 @@ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== -"@ethersproject/logger@^5.6.0": +"@ethersproject/logger@5.6.0", "@ethersproject/logger@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== @@ -581,6 +632,13 @@ dependencies: "@ethersproject/logger" "^5.5.0" +"@ethersproject/networks@5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.2.tgz#2bacda62102c0b1fcee408315f2bed4f6fbdf336" + integrity sha512-9uEzaJY7j5wpYGTojGp8U89mSsgQLc40PCMJLMCnFXTs7nhBveZ0t7dbqWUNrepWTszDbFkYD6WlL8DKx5huHA== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks@^5.6.0": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.1.tgz#7a21ed1f83e86121737b16841961ec99ccf5c9c7" @@ -596,7 +654,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/sha2" "^5.5.0" -"@ethersproject/pbkdf2@^5.6.0": +"@ethersproject/pbkdf2@5.6.0", "@ethersproject/pbkdf2@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz#04fcc2d7c6bff88393f5b4237d906a192426685a" integrity sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ== @@ -611,7 +669,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/properties@^5.6.0": +"@ethersproject/properties@5.6.0", "@ethersproject/properties@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== @@ -643,6 +701,31 @@ bech32 "1.1.4" ws "7.4.6" +"@ethersproject/providers@5.6.4", "@ethersproject/providers@^5.5.3": + version "5.6.4" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.4.tgz#1a49c211b57b0b2703c320819abbbfa35c83dff7" + integrity sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + bech32 "1.1.4" + ws "7.4.6" + "@ethersproject/providers@^5.4.4": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.2.tgz#b9807b1c8c6f59fa2ee4b3cf6519724d07a9f422" @@ -676,7 +759,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/random@^5.6.0": +"@ethersproject/random@5.6.0", "@ethersproject/random@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.0.tgz#1505d1ab6a250e0ee92f436850fa3314b2cb5ae6" integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== @@ -692,7 +775,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/rlp@^5.6.0": +"@ethersproject/rlp@5.6.0", "@ethersproject/rlp@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.0.tgz#55a7be01c6f5e64d6e6e7edb6061aa120962a717" integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== @@ -709,7 +792,7 @@ "@ethersproject/logger" "^5.5.0" hash.js "1.1.7" -"@ethersproject/sha2@^5.6.0": +"@ethersproject/sha2@5.6.0", "@ethersproject/sha2@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.0.tgz#364c4c11cc753bda36f31f001628706ebadb64d9" integrity sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA== @@ -730,7 +813,7 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/signing-key@^5.6.0": +"@ethersproject/signing-key@5.6.0", "@ethersproject/signing-key@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.0.tgz#4f02e3fb09e22b71e2e1d6dc4bcb5dafa69ce042" integrity sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA== @@ -754,7 +837,7 @@ "@ethersproject/sha2" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/solidity@^5.4.0": +"@ethersproject/solidity@5.6.0", "@ethersproject/solidity@^5.4.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.0.tgz#64657362a596bf7f5630bdc921c07dd78df06dc3" integrity sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww== @@ -775,7 +858,7 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/strings@^5.6.0": +"@ethersproject/strings@5.6.0", "@ethersproject/strings@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.0.tgz#9891b26709153d996bf1303d39a7f4bc047878fd" integrity sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg== @@ -799,7 +882,7 @@ "@ethersproject/rlp" "^5.5.0" "@ethersproject/signing-key" "^5.5.0" -"@ethersproject/transactions@^5.4.0", "@ethersproject/transactions@^5.6.0": +"@ethersproject/transactions@5.6.0", "@ethersproject/transactions@^5.4.0", "@ethersproject/transactions@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.0.tgz#4b594d73a868ef6e1529a2f8f94a785e6791ae4e" integrity sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg== @@ -823,6 +906,15 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" +"@ethersproject/units@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.0.tgz#e5cbb1906988f5740254a21b9ded6bd51e826d9c" + integrity sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/wallet@5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.5.0.tgz#322a10527a440ece593980dca6182f17d54eae75" @@ -844,7 +936,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" -"@ethersproject/wallet@^5.4.0": +"@ethersproject/wallet@5.6.0", "@ethersproject/wallet@^5.4.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.0.tgz#33d11a806d783864208f348709a5a3badac8e22a" integrity sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg== @@ -876,7 +968,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/web@^5.6.0": +"@ethersproject/web@5.6.0", "@ethersproject/web@^5.5.1", "@ethersproject/web@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.0.tgz#4bf8b3cbc17055027e1a5dd3c357e37474eaaeb8" integrity sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg== @@ -898,7 +990,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/wordlists@^5.6.0": +"@ethersproject/wordlists@5.6.0", "@ethersproject/wordlists@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.0.tgz#79e62c5276e091d8575f6930ba01a29218ded032" integrity sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q== @@ -923,6 +1015,97 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@ledgerhq/cryptoassets@^5.27.2": + version "5.53.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/cryptoassets/-/cryptoassets-5.53.0.tgz#11dcc93211960c6fd6620392e4dd91896aaabe58" + integrity sha512-M3ibc3LRuHid5UtL7FI3IC6nMEppvly98QHFoSa7lJU0HDzQxY6zHec/SPM4uuJUC8sXoGVAiRJDkgny54damw== + dependencies: + invariant "2" + +"@ledgerhq/devices@^5.26.0", "@ledgerhq/devices@^5.51.1": + version "5.51.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.51.1.tgz#d741a4a5d8f17c2f9d282fd27147e6fe1999edb7" + integrity sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA== + dependencies: + "@ledgerhq/errors" "^5.50.0" + "@ledgerhq/logs" "^5.50.0" + rxjs "6" + semver "^7.3.5" + +"@ledgerhq/errors@^5.26.0", "@ledgerhq/errors@^5.50.0": + version "5.50.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.50.0.tgz#e3a6834cb8c19346efca214c1af84ed28e69dad9" + integrity sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow== + +"@ledgerhq/hw-app-eth@5.27.2": + version "5.27.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-5.27.2.tgz#65a2ed613a69340e0cd69c942147455ec513d006" + integrity sha512-llNdrE894cCN8j6yxJEUniciyLVcLmu5N0UmIJLOObztG+5rOF4bX54h4SreTWK+E10Z0CzHSeyE5Lz/tVcqqQ== + dependencies: + "@ledgerhq/cryptoassets" "^5.27.2" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + bignumber.js "^9.0.1" + rlp "^2.2.6" + +"@ledgerhq/hw-transport-node-hid-noevents@^5.26.0": + version "5.51.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.51.1.tgz#71f37f812e448178ad0bcc2258982150d211c1ab" + integrity sha512-9wFf1L8ZQplF7XOY2sQGEeOhpmBRzrn+4X43kghZ7FBDoltrcK+s/D7S+7ffg3j2OySyP6vIIIgloXylao5Scg== + dependencies: + "@ledgerhq/devices" "^5.51.1" + "@ledgerhq/errors" "^5.50.0" + "@ledgerhq/hw-transport" "^5.51.1" + "@ledgerhq/logs" "^5.50.0" + node-hid "2.1.1" + +"@ledgerhq/hw-transport-node-hid@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-5.26.0.tgz#69bc4f8067cdd9c09ef4aed0e0b3c58328936e4b" + integrity sha512-qhaefZVZatJ6UuK8Wb6WSFNOLWc2mxcv/xgsfKi5HJCIr4bPF/ecIeN+7fRcEaycxj4XykY6Z4A7zDVulfFH4w== + dependencies: + "@ledgerhq/devices" "^5.26.0" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + "@ledgerhq/hw-transport-node-hid-noevents" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" + lodash "^4.17.20" + node-hid "1.3.0" + usb "^1.6.3" + +"@ledgerhq/hw-transport-u2f@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.26.0.tgz#b7d9d13193eb82b051fd7a838cd652372f907ec5" + integrity sha512-QTxP1Rsh+WZ184LUOelYVLeaQl3++V3I2jFik+l9JZtakwEHjD0XqOT750xpYNL/vfHsy31Wlz+oicdxGzFk+w== + dependencies: + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" + u2f-api "0.2.7" + +"@ledgerhq/hw-transport@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.26.0.tgz#bfedc3d48400ad2fe48278d9444344b72aa9d0fe" + integrity sha512-NFeJOJmyEfAX8uuIBTpocWHcz630sqPcXbu864Q+OCBm4EK5UOKV1h/pX7e0xgNIKY8zhJ/O4p4cIZp9tnXLHQ== + dependencies: + "@ledgerhq/devices" "^5.26.0" + "@ledgerhq/errors" "^5.26.0" + events "^3.2.0" + +"@ledgerhq/hw-transport@^5.26.0", "@ledgerhq/hw-transport@^5.51.1": + version "5.51.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz#8dd14a8e58cbee4df0c29eaeef983a79f5f22578" + integrity sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw== + dependencies: + "@ledgerhq/devices" "^5.51.1" + "@ledgerhq/errors" "^5.50.0" + events "^3.3.0" + +"@ledgerhq/logs@^5.26.0", "@ledgerhq/logs@^5.50.0": + version "5.50.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.50.0.tgz#29c6419e8379d496ab6d0426eadf3c4d100cd186" + integrity sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -970,6 +1153,16 @@ "@types/sinon-chai" "^3.2.3" "@types/web3" "1.0.19" +"@openzeppelin/contracts-upgradeable@^4.5.2": + version "4.5.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz#90d9e47bacfd8693bfad0ac8a394645575528d05" + integrity sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA== + +"@openzeppelin/contracts@^4.5.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.5.0.tgz#3fd75d57de172b3743cdfc1206883f56430409cc" + integrity sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA== + "@resolver-engine/core@^0.3.3": version "0.3.3" resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" @@ -1665,6 +1858,19 @@ anymatch@~3.1.1, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -2469,6 +2675,15 @@ bip66@^1.1.5: dependencies: safe-buffer "^5.0.1" +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + blakejs@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" @@ -2682,6 +2897,11 @@ bufferutil@^4.0.1: dependencies: node-gyp-build "^4.3.0" +bufio@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.0.7.tgz#b7f63a1369a0829ed64cc14edf0573b3e382a33e" + integrity sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A== + bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -2910,7 +3130,7 @@ chokidar@^3.5.2: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.4: +chownr@^1.1.1, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -3099,6 +3319,11 @@ concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -3356,6 +3581,13 @@ decompress-response@^3.2.0, decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + deep-eql@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" @@ -3375,6 +3607,11 @@ deep-equal@~1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -3447,6 +3684,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -3472,6 +3714,11 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + detect-port@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" @@ -3635,7 +3882,7 @@ encoding@^0.1.11: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0: +end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -4407,6 +4654,17 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereu ethereum-cryptography "^0.1.3" rlp "^2.2.4" +ethereumjs-util@^7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458" + integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + ethereumjs-vm@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" @@ -4511,6 +4769,42 @@ ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.5, ethers@^5.4.7: "@ethersproject/web" "5.5.1" "@ethersproject/wordlists" "5.5.0" +ethers@^5.5.4, ethers@^5.6.0: + version "5.6.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.4.tgz#23629e9a7d4bc5802dfb53d4da420d738744b53c" + integrity sha512-62UIfxAQXdf67TeeOaoOoPctm5hUlYgfd0iW3wxfj7qRYKDcvvy0f+sJ3W2/Pyx77R8dblvejA8jokj+lS+ATQ== + dependencies: + "@ethersproject/abi" "5.6.1" + "@ethersproject/abstract-provider" "5.6.0" + "@ethersproject/abstract-signer" "5.6.0" + "@ethersproject/address" "5.6.0" + "@ethersproject/base64" "5.6.0" + "@ethersproject/basex" "5.6.0" + "@ethersproject/bignumber" "5.6.0" + "@ethersproject/bytes" "5.6.1" + "@ethersproject/constants" "5.6.0" + "@ethersproject/contracts" "5.6.0" + "@ethersproject/hash" "5.6.0" + "@ethersproject/hdnode" "5.6.0" + "@ethersproject/json-wallets" "5.6.0" + "@ethersproject/keccak256" "5.6.0" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.2" + "@ethersproject/pbkdf2" "5.6.0" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.4" + "@ethersproject/random" "5.6.0" + "@ethersproject/rlp" "5.6.0" + "@ethersproject/sha2" "5.6.0" + "@ethersproject/signing-key" "5.6.0" + "@ethersproject/solidity" "5.6.0" + "@ethersproject/strings" "5.6.0" + "@ethersproject/transactions" "5.6.0" + "@ethersproject/units" "5.6.0" + "@ethersproject/wallet" "5.6.0" + "@ethersproject/web" "5.6.0" + "@ethersproject/wordlists" "5.6.0" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -4537,7 +4831,7 @@ eventemitter3@4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== -events@^3.0.0: +events@^3.0.0, events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -4581,6 +4875,11 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + express@^4.14.0: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -4971,6 +5270,11 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -5111,6 +5415,20 @@ ganache-core@^2.13.2: ethereumjs-wallet "0.6.5" web3 "1.2.11" +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" @@ -5187,6 +5505,11 @@ ghost-testrpc@^0.0.2: chalk "^2.4.2" node-emoji "^1.10.0" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= + glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -5521,6 +5844,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -5788,7 +6116,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.5: +ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -5826,7 +6154,7 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -invariant@^2.2.2: +invariant@2, invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -6731,7 +7059,7 @@ lodash@4.17.20: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6959,6 +7287,18 @@ merkle-patricia-tree@^4.2.0, merkle-patricia-tree@^4.2.2: rlp "^2.2.4" semaphore-async-await "^1.5.1" +merkle-patricia-tree@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.4.tgz#ff988d045e2bf3dfa2239f7fabe2d59618d57413" + integrity sha512-eHbf/BG6eGNsqqfbLED9rIqbsF4+sykEaBn6OLNs71tjclbMcMOk1tEPmJKcNcNCLkvbpY/lwyOlizWsqPNo8w== + dependencies: + "@types/levelup" "^4.3.0" + ethereumjs-util "^7.1.4" + level-mem "^5.0.1" + level-ws "^2.0.0" + readable-stream "^3.6.0" + semaphore-async-await "^1.5.1" + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -7031,6 +7371,11 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -7060,6 +7405,11 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.3: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" @@ -7083,6 +7433,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -7245,6 +7600,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -7270,11 +7630,28 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-abi@^2.18.0, node-abi@^2.21.0, node-abi@^2.7.0: + version "2.30.1" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.1.tgz#c437d4b1fe0e285aaf290d45b45d4d7afedac4cf" + integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w== + dependencies: + semver "^5.4.1" + node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +node-addon-api@^3.0.2: + version "3.2.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + +node-addon-api@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + node-emoji@^1.10.0: version "1.11.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" @@ -7315,11 +7692,35 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== +node-hid@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-1.3.0.tgz#346a468505cee13d69ccd760052cbaf749f66a41" + integrity sha512-BA6G4V84kiNd1uAChub/Z/5s/xS3EHBCxotQ0nyYrUG65mXewUDHE1tWOSqA2dp3N+mV0Ffq9wo2AW9t4p/G7g== + dependencies: + bindings "^1.5.0" + nan "^2.14.0" + node-abi "^2.18.0" + prebuild-install "^5.3.4" + +node-hid@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-2.1.1.tgz#f83c8aa0bb4e6758b5f7383542477da93f67359d" + integrity sha512-Skzhqow7hyLZU93eIPthM9yjot9lszg9xrKxESleEs05V2NcbUptZc5HFqzjOkSmL0sFlZFr3kmvaYebx06wrw== + dependencies: + bindings "^1.5.0" + node-addon-api "^3.0.2" + prebuild-install "^6.0.0" + nofilter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e" integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA== +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= + nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -7354,6 +7755,16 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npmlog@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -7845,6 +8256,46 @@ postinstall-postinstall@^2.1.0: resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== +prebuild-install@^5.3.4: + version "5.3.6" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz#7c225568d864c71d89d07f8796042733a3f54291" + integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^2.7.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + which-pm-runs "^1.0.0" + +prebuild-install@^6.0.0: + version "6.1.4" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.4.tgz#ae3c0142ad611d58570b89af4986088a4937e00f" + integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^2.21.0" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + precond@0.2: version "0.2.3" resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" @@ -8133,6 +8584,16 @@ raw-body@2.4.2, raw-body@^2.4.1: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -8160,7 +8621,7 @@ readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -8173,7 +8634,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -8480,7 +8941,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.6, rlp@^2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== @@ -8504,7 +8965,7 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rxjs@^6.4.0: +rxjs@6, rxjs@^6.4.0: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== @@ -8615,7 +9076,7 @@ semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -8677,7 +9138,7 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" -set-blocking@^2.0.0: +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -8794,6 +9255,15 @@ simple-get@^2.7.0: once "^1.3.1" simple-concat "^1.0.0" +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -9120,6 +9590,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -9129,15 +9608,6 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string.prototype.trim@~1.2.4: version "1.2.5" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz#a587bcc8bfad8cb9829a577f5de30dd170c1682c" @@ -9234,7 +9704,7 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" -strip-json-comments@2.0.1, strip-json-comments@^2.0.1: +strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -9352,6 +9822,27 @@ tape@^4.6.3: string.prototype.trim "~1.2.4" through "~2.3.8" +tar-fs@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tar@^4.0.2: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" @@ -9724,6 +10215,11 @@ typical@^2.6.0, typical@^2.6.1: resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= +u2f-api@0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" + integrity sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg== + uglify-js@^3.1.4: version "3.14.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.4.tgz#68756f17d1b90b9d289341736cb9a567d6882f90" @@ -9831,6 +10327,14 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +usb@^1.6.3: + version "1.9.2" + resolved "https://registry.yarnpkg.com/usb/-/usb-1.9.2.tgz#fb6b36f744ecc707a196c45a6ec72442cb6f2b73" + integrity sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg== + dependencies: + node-addon-api "^4.2.0" + node-gyp-build "^4.3.0" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -10503,6 +11007,11 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-pm-runs@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.1.0.tgz#35ccf7b1a0fce87bd8b92a478c9d045785d3bf35" + integrity sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA== + which-typed-array@^1.1.2: version "1.1.7" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" @@ -10536,6 +11045,13 @@ wide-align@1.1.3: dependencies: string-width "^1.0.2 || 2" +wide-align@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" From 88771cca6f05bdc99db630c2f91bbff2189d5eef Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Sun, 1 May 2022 17:48:36 -0700 Subject: [PATCH 505/585] contracts: fix abi encoding in proof verification (#395) Use `abi.encode` instead of `abi.encodePacked` to ensure a constant serialization. `abi.encode` will be sure to pad the value to its size while `abi.encodePacked` will not when operating on integers. There should not have been a bug here because it was being called with a `bytes32`, which should always be 32 bytes when returned from `abi.encodePacked`. --- .../contracts/contracts/libraries/Lib_WithdrawalVerifier.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol index a5fea789cf69..9d998afba2be 100644 --- a/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol @@ -82,7 +82,7 @@ library WithdrawalVerifier { return Lib_SecureMerkleTrie.verifyInclusionProof( - abi.encodePacked(storageKey), + abi.encode(storageKey), hex"01", _withdrawalProof, _withdrawerStorageRoot From bb58a26986c05bb058a56c58507da92c3d39dc3b Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Mon, 2 May 2022 17:49:28 -0700 Subject: [PATCH 506/585] contracts: don't unalias on L2->L1 Co-authored-by: smartcontracts --- packages/contracts/.gas-snapshot | 8 ++++---- packages/contracts/contracts/L2/Withdrawer.sol | 4 ---- .../contracts/contracts/test/L2CrossDomainMessenger.t.sol | 2 +- packages/contracts/contracts/test/Withdrawer.t.sol | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 28cf87783984..46cae89f11c2 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -31,8 +31,8 @@ L2CrossDomainMessenger_Test:test_L2MessengerCannotCallL2MessagePasser() (gas: 44 L2CrossDomainMessenger_Test:test_L2MessengerCannotRelaySameMessageTwice() (gas: 69883) L2CrossDomainMessenger_Test:test_L2MessengerCorrectL1Messenger() (gas: 9688) L2CrossDomainMessenger_Test:test_L2MessengerRevertInvalidL1XDomainMessenger() (gas: 13781) -L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 124835) -L2CrossDomainMessenger_Test:test_L2MessengerSendSameMessageTwice() (gas: 162907) +L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 124788) +L2CrossDomainMessenger_Test:test_L2MessengerSendSameMessageTwice() (gas: 162859) L2CrossDomainMessenger_Test:test_L2MessengerXDomainMessageSenderReset() (gas: 71843) L2CrossDomainMessenger_Test:test_L2MessengerxDomainMsgSender() (gas: 13320) L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20865) @@ -56,5 +56,5 @@ WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProo WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 35297) WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 192101) WithdawerBurnTest:test_burn() (gas: 50276) -WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 72023) -WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72488) +WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71990) +WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72475) diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/Withdrawer.sol index 0175970e26cb..0d7147c34008 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/Withdrawer.sol @@ -65,10 +65,6 @@ contract Withdrawer { bytes calldata _data ) external payable { address from = msg.sender; - // Transform the from-address to its L1 alias if the caller is a contract. - if (msg.sender != tx.origin) { - from = AddressAliasHelper.undoL1ToL2Alias(msg.sender); - } bytes32 withdrawalHash = WithdrawalVerifier._deriveWithdrawalHash( nonce, diff --git a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol index b902f9b37b2b..708839aa62c5 100644 --- a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol +++ b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol @@ -89,7 +89,7 @@ contract L2CrossDomainMessenger_Test is CommonTest, L2OutputOracle_Initializer { uint32 gasLimit = 1000; uint256 nonce = W.nonce(); - address sender = AddressAliasHelper.undoL1ToL2Alias(address(L2Messenger)); + address sender = address(L2Messenger); vm.expectEmit(true, true, true, true); emit SentMessage(target, address(this), message, nonce, gasLimit); diff --git a/packages/contracts/contracts/test/Withdrawer.t.sol b/packages/contracts/contracts/test/Withdrawer.t.sol index fe53c91bc5a0..bc155dad9263 100644 --- a/packages/contracts/contracts/test/Withdrawer.t.sol +++ b/packages/contracts/contracts/test/Withdrawer.t.sol @@ -48,7 +48,7 @@ contract WithdrawerTestInitiateWithdrawal is WithdrawerTestCommon { vm.expectEmit(true, true, true, true); emit WithdrawalInitiated( 0, - AddressAliasHelper.undoL1ToL2Alias(address(this)), + address(this), NON_ZERO_ADDRESS, NON_ZERO_VALUE, NON_ZERO_GASLIMIT, From 168eed2804663e18aaac8394f5c905064135554f Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Tue, 3 May 2022 08:01:46 +0200 Subject: [PATCH 507/585] opnode: attach p2p host and discovery to rollup node, update e2e test (#388) --- go.mod | 5 +++ go.sum | 12 +++++++ opnode/node/config.go | 10 +++++- opnode/node/node.go | 58 ++++++++++++++++++++++++++++-- opnode/p2p/config.go | 15 ++++++++ opnode/p2p/discovery.go | 3 ++ opnode/p2p/host.go | 3 ++ opnode/p2p/prepared.go | 41 ++++++++++++++++++++++ opnode/test/setup.go | 72 ++++++++++++++++++++++++++++++++++++-- opnode/test/system_test.go | 40 +++++++++++++++++---- 10 files changed, 247 insertions(+), 12 deletions(-) create mode 100644 opnode/p2p/prepared.go diff --git a/go.mod b/go.mod index 16b5255d6120..4a52b43bbae2 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/libp2p/go-libp2p-mplex v0.6.0 github.com/libp2p/go-libp2p-noise v0.3.0 github.com/libp2p/go-libp2p-peerstore v0.6.0 + github.com/libp2p/go-libp2p-pubsub v0.6.1 github.com/libp2p/go-libp2p-swarm v0.10.2 github.com/libp2p/go-libp2p-tls v0.3.1 github.com/libp2p/go-libp2p-yamux v0.9.0 @@ -65,6 +66,7 @@ require ( github.com/huin/goupnp v1.0.3 // indirect github.com/ipfs/go-cid v0.0.7 // indirect github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log/v2 v2.5.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect @@ -79,6 +81,7 @@ require ( github.com/libp2p/go-flow-metrics v0.0.3 // indirect github.com/libp2p/go-libp2p-asn-util v0.1.0 // indirect github.com/libp2p/go-libp2p-blankhost v0.3.0 // indirect + github.com/libp2p/go-libp2p-discovery v0.6.0 // indirect github.com/libp2p/go-libp2p-nat v0.1.0 // indirect github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect github.com/libp2p/go-libp2p-quic-transport v0.16.1 // indirect @@ -122,6 +125,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/ginkgo v1.16.4 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.0 // indirect @@ -144,6 +148,7 @@ require ( github.com/tklauser/numcpus v0.4.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect + github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect diff --git a/go.sum b/go.sum index fac6b1cd82c9..84fd706eacb2 100644 --- a/go.sum +++ b/go.sum @@ -106,6 +106,8 @@ github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7 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/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -478,6 +480,7 @@ github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2PO github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= @@ -578,6 +581,8 @@ github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFS github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= github.com/libp2p/go-libp2p-circuit v0.6.0 h1:rw/HlhmUB3OktS/Ygz6+2XABOmHKzZpPUuMNUMosj8w= github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= +github.com/libp2p/go-libp2p-connmgr v0.2.4 h1:TMS0vc0TCBomtQJyWr7fYxcVYYhx+q/2gF++G5Jkl/w= +github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0= github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= @@ -592,6 +597,8 @@ github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQR github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= github.com/libp2p/go-libp2p-core v0.15.0 h1:hKpgy/bRVwO7Ah5x9u92Vo+gogAaOolafZF5kW0rVm0= github.com/libp2p/go-libp2p-core v0.15.0/go.mod h1:agSaboYM4hzB1cWekgVReqV5M4g5M+2eNNejV+1EEhs= +github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= +github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= @@ -605,6 +612,8 @@ github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnH github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= +github.com/libp2p/go-libp2p-pubsub v0.6.1 h1:wycbV+f4rreCoVY61Do6g/BUk0RIrbNRcYVbn+QkjGk= +github.com/libp2p/go-libp2p-pubsub v0.6.1/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= github.com/libp2p/go-libp2p-quic-transport v0.16.1 h1:N/XqYXHurphPLDfXYhll8NyqzdZYQqAF4GIr7+SmLV8= @@ -864,6 +873,7 @@ github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKw 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/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= @@ -1060,6 +1070,8 @@ github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1 github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= diff --git a/opnode/node/config.go b/opnode/node/config.go index ac60d3b4edb6..59b77f3cc746 100644 --- a/opnode/node/config.go +++ b/opnode/node/config.go @@ -4,6 +4,8 @@ import ( "crypto/ecdsa" "fmt" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" ) @@ -30,6 +32,8 @@ type Config struct { RPCListenAddr string RPCListenPort int WithdrawalContractAddr common.Address + + P2P p2p.SetupP2P } // Check verifies that the given configuration makes sense @@ -37,6 +41,10 @@ func (cfg *Config) Check() error { if err := cfg.Rollup.Check(); err != nil { return fmt.Errorf("rollup config error: %v", err) } - + if cfg.P2P != nil { + if err := cfg.P2P.Check(); err != nil { + return fmt.Errorf("p2p config error: %v", err) + } + } return nil } diff --git a/opnode/node/node.go b/opnode/node/node.go index 4834d559c290..e4dbccac8332 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -6,6 +6,11 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/libp2p/go-libp2p-core/host" + pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/ethereum-optimism/optimistic-specs/opnode/backoff" "github.com/ethereum-optimism/optimistic-specs/opnode/bss" @@ -26,7 +31,13 @@ type OpNode struct { l1Source *l1.Source // Source to fetch data from (also implements the Downloader interface) l2Engines []*driver.Driver // engines to keep synced l2Nodes []*rpc.Client // L2 Execution Engines to close at shutdown - server *rpcServer + server *rpcServer // RPC server hosting the rollup-node API + host host.Host // p2p host (optional, may be nil) + dv5Local *enode.LocalNode // p2p discovery identity (optional, may be nil) + dv5Udp *discover.UDPv5 // p2p discovery service (optional, may be nil) + p2pCtx context.Context // all p2p activity take this context so p2p can be shut down without stopping the node. + p2pClose context.CancelFunc + gs *pubsub.PubSub done chan struct{} wg sync.WaitGroup } @@ -124,6 +135,36 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* l2Nodes: l2Nodes, } + if cfg.P2P != nil { + // All nil if disabled. + n.dv5Local, n.dv5Udp, err = cfg.P2P.Discovery(log.New("p2p", "discv5")) + if err != nil { + return nil, fmt.Errorf("failed to start discv5: %v", err) + } + + // nil if disabled. + n.host, err = cfg.P2P.Host() + if err != nil { + return nil, fmt.Errorf("failed to start p2p host: %v", err) + } + if n.host != nil { + // not a context leak, gossipsub is closed with a context. + // TODO: maybe we can improve this, or closing the Host is enough? + n.p2pCtx, n.p2pClose = context.WithCancel(context.Background()) + gs, err := pubsub.NewGossipSub(n.p2pCtx, n.host) // TODO options + if err != nil { + // close p2p stack if we cannot create the opnode successfully + if n.dv5Udp != nil { + n.dv5Udp.Close() + } + _ = n.host.Close() + n.p2pClose() + return nil, fmt.Errorf("failed to start gossipsub router: %v", err) + } + n.gs = gs + } + } + return n, nil } @@ -195,13 +236,26 @@ func (c *OpNode) Start(ctx context.Context) error { // TODO: maybe log other info on interval or other chain events (individual engines also log things) case <-c.done: c.log.Info("Closing OpNode") + if c.dv5Udp != nil { + c.dv5Udp.Close() + } + if c.host != nil { + if err := c.host.Close(); err != nil { + c.log.Error("failed to close p2p host cleanly: %v", err) + } + } + if c.p2pClose != nil { + c.p2pClose() + } // close all tasks for _, f := range unsub { f() } // close L2 engines for _, eng := range c.l2Engines { - eng.Close() + if err := eng.Close(); err != nil { + c.log.Error("failed to close L2 engine driver cleanly: %v", err) + } } // close L2 nodes for _, n := range c.l2Nodes { diff --git a/opnode/p2p/config.go b/opnode/p2p/config.go index 01d0ecfe15a3..d44d5cb44cfc 100644 --- a/opnode/p2p/config.go +++ b/opnode/p2p/config.go @@ -12,6 +12,10 @@ import ( "strings" "time" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/libp2p/go-libp2p-core/host" + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" "github.com/ethereum/go-ethereum/p2p/enode" ds "github.com/ipfs/go-datastore" @@ -32,6 +36,17 @@ import ( "github.com/urfave/cli" ) +// SetupP2P provides a host and discovery service for usage in the rollup node. +type SetupP2P interface { + Check() error + // Host creates a libp2p host service. Returns nil, nil if p2p is disabled. + Host() (host.Host, error) + // Discovery creates a disc-v5 service. Returns nil, nil, nil if discovery is disabled. + Discovery(log log.Logger) (*enode.LocalNode, *discover.UDPv5, error) +} + +// Config sets up a p2p host and discv5 service from configuration. +// This implements SetupP2P. type Config struct { Priv *ecdsa.PrivateKey diff --git a/opnode/p2p/discovery.go b/opnode/p2p/discovery.go index c566660453dd..ea2b1cc0e30e 100644 --- a/opnode/p2p/discovery.go +++ b/opnode/p2p/discovery.go @@ -9,6 +9,9 @@ import ( ) func (conf *Config) Discovery(log log.Logger) (*enode.LocalNode, *discover.UDPv5, error) { + if conf.NoDiscovery { + return nil, nil, nil + } localNode := enode.NewLocalNode(conf.DiscoveryDB, conf.Priv) if conf.AdvertiseIP != nil { localNode.SetStaticIP(conf.AdvertiseIP) diff --git a/opnode/p2p/host.go b/opnode/p2p/host.go index 08d412353703..5aabfda4e3e2 100644 --- a/opnode/p2p/host.go +++ b/opnode/p2p/host.go @@ -18,6 +18,9 @@ import ( ) func (conf *Config) Host() (host.Host, error) { + if conf.DisableP2P { + return nil, nil + } // we cast the ecdsa key type to the libp2p wrapper, to then use the libp2p pubkey and ID interfaces. var priv crypto.PrivKey = (*crypto.Secp256k1PrivateKey)(conf.Priv) pub := priv.GetPublic() diff --git a/opnode/p2p/prepared.go b/opnode/p2p/prepared.go new file mode 100644 index 000000000000..482dfdd92be0 --- /dev/null +++ b/opnode/p2p/prepared.go @@ -0,0 +1,41 @@ +package p2p + +import ( + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/libp2p/go-libp2p-core/host" +) + +// Prepared provides a p2p host and discv5 service that is already set up. +// This implements SetupP2P. +type Prepared struct { + HostP2P host.Host + LocalNode *enode.LocalNode + UDPv5 *discover.UDPv5 +} + +var _ SetupP2P = (*Prepared)(nil) + +func (p *Prepared) Check() error { + if (p.LocalNode == nil) != (p.UDPv5 == nil) { + return fmt.Errorf("inconsistent discv5 setup: %v <> %v", p.LocalNode, p.UDPv5) + } + if p.LocalNode != nil && p.HostP2P == nil { + return errors.New("cannot provide discovery without p2p host") + } + return nil +} + +// Host creates a libp2p host service. Returns nil, nil if p2p is disabled. +func (p *Prepared) Host() (host.Host, error) { + return p.HostP2P, nil +} + +// Discovery creates a disc-v5 service. Returns nil, nil, nil if discovery is disabled. +func (p *Prepared) Discovery(log log.Logger) (*enode.LocalNode, *discover.UDPv5, error) { + return p.LocalNode, p.UDPv5, nil +} diff --git a/opnode/test/setup.go b/opnode/test/setup.go index a1d701825bef..275c8cf9b4df 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -4,9 +4,13 @@ import ( "context" "fmt" "math/big" + "strings" "time" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" @@ -75,6 +79,13 @@ type SystemConfig struct { Nodes map[string]rollupNode.Config // Per node config. Don't use populate rollup.Config Loggers map[string]log.Logger RollupConfig rollup.Config // Shared rollup configs + + L1BlockTime uint64 + + // map of outbound connections to other nodes. Node names prefixed with "~" are unconnected but linked. + // A nil map disables P2P completely. + // Any node name not in the topology will not have p2p enabled. + P2PTopology map[string][]string } type System struct { @@ -91,6 +102,7 @@ type System struct { rollupNodes map[string]*rollupNode.OpNode L2OOContractAddr common.Address DepositContractAddr common.Address + Mocknet mocknet.Mocknet } func precompileAlloc() core.GenesisAlloc { @@ -126,6 +138,7 @@ func (sys *System) Close() { for _, node := range sys.nodes { node.Close() } + sys.Mocknet.Close() } func (cfg SystemConfig) start() (*System, error) { @@ -209,7 +222,7 @@ func (cfg SystemConfig) start() (*System, error) { BerlinBlock: common.Big0, LondonBlock: common.Big0, Clique: ¶ms.CliqueConfig{ - Period: 2, + Period: cfg.L1BlockTime, Epoch: 30000, }, }, @@ -363,11 +376,63 @@ func (cfg SystemConfig) start() (*System, error) { if err != nil { return nil, err } - _, err = waitForTransaction(tx.Hash(), l1Client, 4*time.Second) + _, err = waitForTransaction(tx.Hash(), l1Client, time.Duration(cfg.L1BlockTime)*time.Second*2) if err != nil { return nil, fmt.Errorf("waiting for OptimismPortal: %w", err) } + sys.Mocknet = mocknet.New() + + p2pNodes := make(map[string]*p2p.Prepared) + if cfg.P2PTopology != nil { + // create the peer if it doesn't exist yet. + initHostMaybe := func(name string) (*p2p.Prepared, error) { + if p, ok := p2pNodes[name]; ok { + return p, nil + } + h, err := sys.Mocknet.GenPeer() + if err != nil { + return nil, fmt.Errorf("failed to init p2p host for node %s", name) + } + _, ok := cfg.Nodes[name] + if !ok { + return nil, fmt.Errorf("node %s from p2p topology not found in actual nodes map", name) + } + // TODO we can enable discv5 in the testnodes to test discovery of new peers. + // Would need to mock though, and the discv5 implementation does not provide nice mocks here. + p := &p2p.Prepared{ + HostP2P: h, + LocalNode: nil, + UDPv5: nil, + } + p2pNodes[name] = p + return p, nil + } + for k, vs := range cfg.P2PTopology { + peerA, err := initHostMaybe(k) + if err != nil { + return nil, fmt.Errorf("failed to setup mocknet peer %s", k) + } + for _, v := range vs { + unconnected := strings.HasPrefix(v, "~") + if unconnected { + v = v[1:] + } + peerB, err := initHostMaybe(v) + if err != nil { + return nil, fmt.Errorf("failed to setup mocknet peer %s (peer of %s)", v, k) + } + if _, err := sys.Mocknet.LinkPeers(peerA.HostP2P.ID(), peerB.HostP2P.ID()); err != nil { + return nil, fmt.Errorf("failed to setup mocknet link between %s and %s", k, v) + } + if !unconnected { + if _, err := sys.Mocknet.ConnectPeers(peerA.HostP2P.ID(), peerB.HostP2P.ID()); err != nil { + return nil, fmt.Errorf("failed to setup mocknet connection between %s and %s", k, v) + } + } + } + } + } // Rollup nodes for name, nodeConfig := range cfg.Nodes { c := nodeConfig @@ -376,6 +441,9 @@ func (cfg SystemConfig) start() (*System, error) { if c.Sequencer { c.SubmitterPrivKey = bssPrivKey } + if p, ok := p2pNodes[name]; ok { + c.P2P = p + } node, err := rollupNode.New(context.Background(), &c, cfg.Loggers[name], "") if err != nil { diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index d57ed3ee6c80..3811eb2b36bf 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -77,6 +77,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { DeployerHDPath: l2OutputHDPath, CliqueSignerDerivationPath: cliqueSignerHDPath, L1InfoPredeployAddress: derive.L1InfoPredeployAddr, + L1BlockTime: 2, L1WsAddr: "127.0.0.1", L1WsPort: 9090, L1ChainID: big.NewInt(900), @@ -114,6 +115,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { // Batch Sender address is filled out in system start DepositContractAddress: MockDepositContractAddr, }, + P2PTopology: nil, // no P2P connectivity by default } } @@ -252,13 +254,13 @@ func TestSystemE2E(t *testing.T) { tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, 1_000_000, false, nil) require.Nil(t, err, "with deposit tx") - receipt, err := waitForTransaction(tx.Hash(), l1Client, 6*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for deposit tx on L1") reconstructedDep, err := derive.UnmarshalLogEvent(receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second) require.NoError(t, err) require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) @@ -286,10 +288,10 @@ func TestSystemE2E(t *testing.T) { err = l2Seq.SendTransaction(context.Background(), tx) require.Nil(t, err, "Sending L2 tx to sequencer") - _, err = waitForTransaction(tx.Hash(), l2Seq, 6*time.Second) + _, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on sequencer") - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on verifier") require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded") @@ -342,13 +344,13 @@ func TestMintOnRevertedDeposit(t *testing.T) { tx, err := depositContract.DepositTransaction(opts, toAddr, value, 1_000_000, false, nil) require.Nil(t, err, "with deposit tx") - receipt, err := waitForTransaction(tx.Hash(), l1Client, 6*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for deposit tx on L1") reconstructedDep, err := derive.UnmarshalLogEvent(receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Second) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second) require.NoError(t, err) require.Equal(t, receipt.Status, types.ReceiptStatusFailed) @@ -414,7 +416,7 @@ func TestMissingBatchE2E(t *testing.T) { require.Nil(t, err, "Sending L2 tx to sequencer") // Let it show up on the unsafe chain - receipt, err := waitForTransaction(tx.Hash(), l2Seq, 6*time.Second) + receipt, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on sequencer") // Wait until the block it was first included in shows up in the safe chain on the verifier @@ -479,6 +481,30 @@ func L1InfoFromState(ctx context.Context, contract *l1block.L1Block, l2Number *b return out, nil } +// TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that +// the nodes can sync L2 blocks before they are confirmed on L1. +func TestSystemMockP2P(t *testing.T) { + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } + + cfg := defaultSystemConfig(t) + // slow down L1 blocks so we can see the L2 blocks arrive before the L1 blocks do. + cfg.L1BlockTime = 10 + // connect the nodes + cfg.P2PTopology = map[string][]string{ + "verifier": []string{"sequencer"}, + } + + sys, err := cfg.start() + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + t.Log("successfully set up network") + + // TODO: await L2 blocks going from sequencer to verifier, ahead of L1 +} + func TestL1InfoContract(t *testing.T) { if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) From bbe861a65b7a03270a32768d0870835228443b94 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 3 May 2022 12:18:59 -0700 Subject: [PATCH 508/585] deps: update forge-std --- packages/contracts/lib/forge-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/lib/forge-std b/packages/contracts/lib/forge-std index 6fddb7693357..e26ae2954bb6 160000 --- a/packages/contracts/lib/forge-std +++ b/packages/contracts/lib/forge-std @@ -1 +1 @@ -Subproject commit 6fddb76933574420f769ff7ea367aed578e962a8 +Subproject commit e26ae2954bb6d883643b92760d443dd07f413647 From 56713a2cb28cc658b6ccdd63028c85524eaeab41 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 3 May 2022 13:12:25 -0700 Subject: [PATCH 509/585] contracts: fix build --- packages/contracts/.gas-snapshot | 106 +++++++++--------- .../contracts/contracts/test/CommonTest.t.sol | 5 +- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 46cae89f11c2..eb6cd674abda 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,60 +1,60 @@ -DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 11345) -DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 26479) -DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 26944) -DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 26497) -DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 26984) -DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 33520) -DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 25135) -DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 33188) -DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 33924) +DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 9290) +DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 24388) +DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 24734) +DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 24451) +DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 24707) +DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 31429) +DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 22859) +DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 31098) +DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 31713) L1BLockTest:test_basefee() (gas: 7509) L1BLockTest:test_hash() (gas: 7508) L1BLockTest:test_number() (gas: 7509) L1BLockTest:test_timestamp() (gas: 7463) -L1CrossDomainMessenger_Test:testCannot_pause() (gas: 13061) -L1CrossDomainMessenger_Test:test_blockAndUnblockSuccessfulMessage() (gas: 108194) -L1CrossDomainMessenger_Test:test_pause() (gas: 31719) -L1CrossDomainMessenger_Test:test_relayMessageBlockingAuth() (gas: 20956) -L1CrossDomainMessenger_Test:test_relayMessageInsideFraudProofWindow() (gas: 14531) -L1CrossDomainMessenger_Test:test_relayMessageSucceeds() (gas: 84960) -L1CrossDomainMessenger_Test:test_relayMessageToSystemContract() (gas: 32472) -L1CrossDomainMessenger_Test:test_relayRevertOnBlockedMessage() (gas: 58192) -L1CrossDomainMessenger_Test:test_relayShouldRevertIfPaused() (gas: 43739) -L1CrossDomainMessenger_Test:test_relayShouldRevertSendingSameMessageTwice() (gas: 210) -L1CrossDomainMessenger_Test:test_revertOnInvalidOutputRootProof() (gas: 18192) -L1CrossDomainMessenger_Test:test_sendMessage() (gas: 46192) -L1CrossDomainMessenger_Test:test_sendMessageTwice() (gas: 49016) -L1CrossDomainMessenger_Test:test_xDomainMessageSenderResets() (gas: 83962) -L1StandardBridge_Test:test_L1BridgeSetsPortalAndL2Bridge() (gas: 14780) -L2CrossDomainMessenger_Test:test_L2MessengerCallsTarget() (gas: 66275) -L2CrossDomainMessenger_Test:test_L2MessengerCannotCallL2MessagePasser() (gas: 44127) -L2CrossDomainMessenger_Test:test_L2MessengerCannotRelaySameMessageTwice() (gas: 69883) -L2CrossDomainMessenger_Test:test_L2MessengerCorrectL1Messenger() (gas: 9688) -L2CrossDomainMessenger_Test:test_L2MessengerRevertInvalidL1XDomainMessenger() (gas: 13781) -L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 124788) -L2CrossDomainMessenger_Test:test_L2MessengerSendSameMessageTwice() (gas: 162859) -L2CrossDomainMessenger_Test:test_L2MessengerXDomainMessageSenderReset() (gas: 71843) -L2CrossDomainMessenger_Test:test_L2MessengerxDomainMsgSender() (gas: 13320) -L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 20865) -L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 19041) -L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 21020) -L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 18309) -L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 21223) -L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 13139) -L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18390) -L2OutputOracleTest:testCannot_deleteL2Output_ifWrongOutput() (gas: 25529) -L2OutputOracleTest:test_appendingAnotherOutput() (gas: 49533) -L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14972) -L2OutputOracleTest:test_deleteL2Output() (gas: 32896) -L2OutputOracleTest:test_getL2Output() (gas: 15093) -L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9669) -L2OutputOracleTest:test_nextTimestamp() (gas: 12024) -L2OutputOracleTest_Constructor:test_constructor() (gas: 29190) -L2StandardBridge_Test:test_L2BridgeCorrectL1Bridge() (gas: 9629) -OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 24189) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 39599) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 35297) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 192101) +L1CrossDomainMessenger_Test:testCannot_pause() (gas: 10843) +L1CrossDomainMessenger_Test:test_blockAndUnblockSuccessfulMessage() (gas: 105412) +L1CrossDomainMessenger_Test:test_pause() (gas: 31793) +L1CrossDomainMessenger_Test:test_relayMessageBlockingAuth() (gas: 18542) +L1CrossDomainMessenger_Test:test_relayMessageInsideFraudProofWindow() (gas: 12305) +L1CrossDomainMessenger_Test:test_relayMessageSucceeds() (gas: 82425) +L1CrossDomainMessenger_Test:test_relayMessageToSystemContract() (gas: 30160) +L1CrossDomainMessenger_Test:test_relayRevertOnBlockedMessage() (gas: 55761) +L1CrossDomainMessenger_Test:test_relayShouldRevertIfPaused() (gas: 41560) +L1CrossDomainMessenger_Test:test_relayShouldRevertSendingSameMessageTwice() (gas: 188) +L1CrossDomainMessenger_Test:test_revertOnInvalidOutputRootProof() (gas: 16067) +L1CrossDomainMessenger_Test:test_sendMessage() (gas: 44041) +L1CrossDomainMessenger_Test:test_sendMessageTwice() (gas: 49061) +L1CrossDomainMessenger_Test:test_xDomainMessageSenderResets() (gas: 81565) +L1StandardBridge_Test:test_L1BridgeSetsPortalAndL2Bridge() (gas: 14825) +L2CrossDomainMessenger_Test:test_L2MessengerCallsTarget() (gas: 64095) +L2CrossDomainMessenger_Test:test_L2MessengerCannotCallL2MessagePasser() (gas: 42128) +L2CrossDomainMessenger_Test:test_L2MessengerCannotRelaySameMessageTwice() (gas: 67491) +L2CrossDomainMessenger_Test:test_L2MessengerCorrectL1Messenger() (gas: 9762) +L2CrossDomainMessenger_Test:test_L2MessengerRevertInvalidL1XDomainMessenger() (gas: 11535) +L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122584) +L2CrossDomainMessenger_Test:test_L2MessengerSendSameMessageTwice() (gas: 162903) +L2CrossDomainMessenger_Test:test_L2MessengerXDomainMessageSenderReset() (gas: 69285) +L2CrossDomainMessenger_Test:test_L2MessengerxDomainMsgSender() (gas: 11159) +L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 18605) +L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 16724) +L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 18642) +L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 16088) +L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 18893) +L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 11048) +L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 16287) +L2OutputOracleTest:testCannot_deleteL2Output_ifWrongOutput() (gas: 23243) +L2OutputOracleTest:test_appendingAnotherOutput() (gas: 47332) +L2OutputOracleTest:test_computeL2BlockNumber() (gas: 15003) +L2OutputOracleTest:test_deleteL2Output() (gas: 30647) +L2OutputOracleTest:test_getL2Output() (gas: 15071) +L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9699) +L2OutputOracleTest:test_nextTimestamp() (gas: 12031) +L2OutputOracleTest_Constructor:test_constructor() (gas: 29173) +L2StandardBridge_Test:test_L2BridgeCorrectL1Bridge() (gas: 9726) +OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 21979) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 37418) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 33219) +WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 190048) WithdawerBurnTest:test_burn() (gas: 50276) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71990) WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72475) diff --git a/packages/contracts/contracts/test/CommonTest.t.sol b/packages/contracts/contracts/test/CommonTest.t.sol index 8f44709c5189..f3442f14ab14 100644 --- a/packages/contracts/contracts/test/CommonTest.t.sol +++ b/packages/contracts/contracts/test/CommonTest.t.sol @@ -2,11 +2,10 @@ pragma solidity 0.8.10; /* Testing utilities */ -import { DSTest } from "forge-std/Test.sol"; +import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; -contract CommonTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); +contract CommonTest is Test { address immutable ZERO_ADDRESS = address(0); address immutable NON_ZERO_ADDRESS = address(1); uint256 immutable NON_ZERO_VALUE = 100; From 99126bf03e2847086f7012d9e3c5b3ba927b42c4 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 3 May 2022 13:29:11 -0700 Subject: [PATCH 510/585] build: fix bindings build --- l2os/Makefile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/l2os/Makefile b/l2os/Makefile index 52f3d11c8b11..0d8fce20ca49 100644 --- a/l2os/Makefile +++ b/l2os/Makefile @@ -25,11 +25,10 @@ bindings: bindings-l2-output-oracle bindings-l2-output-oracle: $(eval temp := $(shell mktemp -d)) - solc \ - --abi $(L2_OUTPUT_ORACLE_SOL) \ - --bin $(L2_OUTPUT_ORACLE_SOL) \ - --allow-paths ../ \ - -o $(temp) + cd ../packages/contracts; \ + forge build \ + && forge inspect L2OutputOracle abi > $(temp)/L2OutputOracle.abi \ + && forge inspect L2OutputOracle bytecode > $(temp)/L2OutputOracle.bin abigen \ --abi $(temp)/L2OutputOracle.abi \ --bin $(temp)/L2OutputOracle.bin \ @@ -37,7 +36,6 @@ bindings-l2-output-oracle: --type L2OutputOracle \ --out ./bindings/l2oo/l2_output_oracle.go - .PHONY: \ bindings \ bindings-mock-l2-output-oracle \ From 675541876f3b74a4875a54f1d5410ee5b2b8bdd9 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 3 May 2022 13:50:22 -0700 Subject: [PATCH 511/585] fix: builds --- l2os/Makefile | 2 -- opnode/contracts/Makefile | 33 ++++++++++++++++----------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/l2os/Makefile b/l2os/Makefile index 0d8fce20ca49..3b5d4758204d 100644 --- a/l2os/Makefile +++ b/l2os/Makefile @@ -7,8 +7,6 @@ LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) LDFLAGSSTRING +=-X main.Version=$(VERSION) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" -L2_OUTPUT_ORACLE_SOL := ../packages/contracts/contracts/L1/L2OutputOracle.sol - l2os: env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/l2os diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index eb1b153acdd4..6a2ac485fbfe 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -20,30 +20,29 @@ deployed-bin-l1-block-info: bindings-l1-block-info bindings-l1-block-info: $(eval temp := $(shell mktemp -d)) - solc \ - --abi $(L1_BLOCK_INFO) \ - --bin $(L1_BLOCK_INFO) \ - --combined-json abi,bin,bin-runtime \ - --allow-paths $(CONTRACTS_PATH) \ - -o $(temp) + $(eval cwd := $(shell pwd)) + mkdir -p bin + cd ../../packages/contracts; \ + forge build \ + && forge inspect L1Block abi > $(temp)/L1Block.abi \ + && forge inspect L1Block bytecode > $(temp)/L1Block.bin \ + && forge inspect L1Block deployedBytecode > $(cwd)/bin/l1block_deployed.hex abigen \ - --combined-json $(temp)/combined.json \ + --abi $(temp)/L1Block.abi \ + --bin $(temp)/L1Block.bin \ --pkg l1block \ --type l1block \ --out ./l1block/l1_block_info_raw.go - cat $(temp)/combined.json | jq -r ".contracts | with_entries(select(.key | match(\"L1Block\")))[] | .\"bin-runtime\"" > bin/l1block_deployed.hex - bindings-optimism-portal: $(eval temp := $(shell mktemp -d)) - solc \ - --abi $(OPTIMISM_PORTAL) \ - --bin $(OPTIMISM_PORTAL) \ - --combined-json abi,bin,bin-runtime \ - --allow-paths $(CONTRACTS_PATH) \ - -o $(temp) + cd ../../packages/contracts; \ + forge build \ + && forge inspect OptimismPortal abi > $(temp)/OptimismPortal.abi \ + && forge inspect OptimismPortal bytecode > $(temp)/OptimismPortal.bin abigen \ - --combined-json $(temp)/combined.json \ + --abi $(temp)/OptimismPortal.abi \ + --bin $(temp)/OptimismPortal.bin \ --pkg deposit \ --type deposit \ - --out ./deposit/deposit_feed_raw.go \ No newline at end of file + --out ./deposit/deposit_feed_raw.go From e4f208006eb83c0b3ba586b595eb0ae3cd002d16 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 3 May 2022 14:05:20 -0700 Subject: [PATCH 512/585] forge install: ds-test --- .gitmodules | 3 +++ packages/contracts/lib/ds-test | 1 + 2 files changed, 4 insertions(+) create mode 160000 packages/contracts/lib/ds-test diff --git a/.gitmodules b/.gitmodules index ade85d7b22f1..cd75690a4831 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "packages/contracts/lib/solmate"] path = packages/contracts/lib/solmate url = https://github.com/rari-capital/solmate +[submodule "packages/contracts/lib/ds-test"] + path = packages/contracts/lib/ds-test + url = https://github.com/dapphub/ds-test diff --git a/packages/contracts/lib/ds-test b/packages/contracts/lib/ds-test new file mode 160000 index 000000000000..2c7dbcc8586b --- /dev/null +++ b/packages/contracts/lib/ds-test @@ -0,0 +1 @@ +Subproject commit 2c7dbcc8586b33f358e3307a443e524490c17666 From 1a068375dbf8b5f9aaaa12bd94f9d8c0acd30b3c Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 3 May 2022 14:14:25 -0700 Subject: [PATCH 513/585] build: fix for good --- opnode/contracts/Makefile | 4 +- opnode/contracts/deposit/deposit_feed_raw.go | 4158 ++--------------- .../l1block/l1_block_info_deployed.go | 2 +- opnode/contracts/l1block/l1_block_info_raw.go | 2 +- 4 files changed, 331 insertions(+), 3835 deletions(-) diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index 6a2ac485fbfe..dd89831eb026 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -31,7 +31,7 @@ bindings-l1-block-info: --abi $(temp)/L1Block.abi \ --bin $(temp)/L1Block.bin \ --pkg l1block \ - --type l1block \ + --type L1Block \ --out ./l1block/l1_block_info_raw.go bindings-optimism-portal: @@ -44,5 +44,5 @@ bindings-optimism-portal: --abi $(temp)/OptimismPortal.abi \ --bin $(temp)/OptimismPortal.bin \ --pkg deposit \ - --type deposit \ + --type OptimismPortal \ --out ./deposit/deposit_feed_raw.go diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/opnode/contracts/deposit/deposit_feed_raw.go index 1ae6a191af2c..db95f79f9fe9 100644 --- a/opnode/contracts/deposit/deposit_feed_raw.go +++ b/opnode/contracts/deposit/deposit_feed_raw.go @@ -36,3576 +36,23 @@ type WithdrawalVerifierOutputRootProof struct { LatestBlockhash [32]byte } -// AddressAliasHelperMetaData contains all meta data concerning the AddressAliasHelper contract. -var AddressAliasHelperMetaData = &bind.MetaData{ - ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c7fa45f5503f62c2292b9c4a466d09aacd158cdc3685a7753531ac6bf8bda5ef64736f6c634300080a0033", -} - -// AddressAliasHelperABI is the input ABI used to generate the binding from. -// Deprecated: Use AddressAliasHelperMetaData.ABI instead. -var AddressAliasHelperABI = AddressAliasHelperMetaData.ABI - -// AddressAliasHelperBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use AddressAliasHelperMetaData.Bin instead. -var AddressAliasHelperBin = AddressAliasHelperMetaData.Bin - -// DeployAddressAliasHelper deploys a new Ethereum contract, binding an instance of AddressAliasHelper to it. -func DeployAddressAliasHelper(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *AddressAliasHelper, error) { - parsed, err := AddressAliasHelperMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AddressAliasHelperBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &AddressAliasHelper{AddressAliasHelperCaller: AddressAliasHelperCaller{contract: contract}, AddressAliasHelperTransactor: AddressAliasHelperTransactor{contract: contract}, AddressAliasHelperFilterer: AddressAliasHelperFilterer{contract: contract}}, nil -} - -// AddressAliasHelper is an auto generated Go binding around an Ethereum contract. -type AddressAliasHelper struct { - AddressAliasHelperCaller // Read-only binding to the contract - AddressAliasHelperTransactor // Write-only binding to the contract - AddressAliasHelperFilterer // Log filterer for contract events -} - -// AddressAliasHelperCaller is an auto generated read-only Go binding around an Ethereum contract. -type AddressAliasHelperCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// AddressAliasHelperTransactor is an auto generated write-only Go binding around an Ethereum contract. -type AddressAliasHelperTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// AddressAliasHelperFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type AddressAliasHelperFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// AddressAliasHelperSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type AddressAliasHelperSession struct { - Contract *AddressAliasHelper // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// AddressAliasHelperCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type AddressAliasHelperCallerSession struct { - Contract *AddressAliasHelperCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// AddressAliasHelperTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type AddressAliasHelperTransactorSession struct { - Contract *AddressAliasHelperTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// AddressAliasHelperRaw is an auto generated low-level Go binding around an Ethereum contract. -type AddressAliasHelperRaw struct { - Contract *AddressAliasHelper // Generic contract binding to access the raw methods on -} - -// AddressAliasHelperCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type AddressAliasHelperCallerRaw struct { - Contract *AddressAliasHelperCaller // Generic read-only contract binding to access the raw methods on -} - -// AddressAliasHelperTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type AddressAliasHelperTransactorRaw struct { - Contract *AddressAliasHelperTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewAddressAliasHelper creates a new instance of AddressAliasHelper, bound to a specific deployed contract. -func NewAddressAliasHelper(address common.Address, backend bind.ContractBackend) (*AddressAliasHelper, error) { - contract, err := bindAddressAliasHelper(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &AddressAliasHelper{AddressAliasHelperCaller: AddressAliasHelperCaller{contract: contract}, AddressAliasHelperTransactor: AddressAliasHelperTransactor{contract: contract}, AddressAliasHelperFilterer: AddressAliasHelperFilterer{contract: contract}}, nil -} - -// NewAddressAliasHelperCaller creates a new read-only instance of AddressAliasHelper, bound to a specific deployed contract. -func NewAddressAliasHelperCaller(address common.Address, caller bind.ContractCaller) (*AddressAliasHelperCaller, error) { - contract, err := bindAddressAliasHelper(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &AddressAliasHelperCaller{contract: contract}, nil -} - -// NewAddressAliasHelperTransactor creates a new write-only instance of AddressAliasHelper, bound to a specific deployed contract. -func NewAddressAliasHelperTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressAliasHelperTransactor, error) { - contract, err := bindAddressAliasHelper(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &AddressAliasHelperTransactor{contract: contract}, nil -} - -// NewAddressAliasHelperFilterer creates a new log filterer instance of AddressAliasHelper, bound to a specific deployed contract. -func NewAddressAliasHelperFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressAliasHelperFilterer, error) { - contract, err := bindAddressAliasHelper(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &AddressAliasHelperFilterer{contract: contract}, nil -} - -// bindAddressAliasHelper binds a generic wrapper to an already deployed contract. -func bindAddressAliasHelper(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(AddressAliasHelperABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_AddressAliasHelper *AddressAliasHelperRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _AddressAliasHelper.Contract.AddressAliasHelperCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_AddressAliasHelper *AddressAliasHelperRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _AddressAliasHelper.Contract.AddressAliasHelperTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_AddressAliasHelper *AddressAliasHelperRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _AddressAliasHelper.Contract.AddressAliasHelperTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_AddressAliasHelper *AddressAliasHelperCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _AddressAliasHelper.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_AddressAliasHelper *AddressAliasHelperTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _AddressAliasHelper.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_AddressAliasHelper *AddressAliasHelperTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _AddressAliasHelper.Contract.contract.Transact(opts, method, params...) -} - -// ContextMetaData contains all meta data concerning the Context contract. -var ContextMetaData = &bind.MetaData{ - ABI: "[]", -} - -// ContextABI is the input ABI used to generate the binding from. -// Deprecated: Use ContextMetaData.ABI instead. -var ContextABI = ContextMetaData.ABI - -// Context is an auto generated Go binding around an Ethereum contract. -type Context struct { - ContextCaller // Read-only binding to the contract - ContextTransactor // Write-only binding to the contract - ContextFilterer // Log filterer for contract events -} - -// ContextCaller is an auto generated read-only Go binding around an Ethereum contract. -type ContextCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContextTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ContextTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ContextFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContextSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ContextSession struct { - Contract *Context // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ContextCallerSession struct { - Contract *ContextCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ContextTransactorSession struct { - Contract *ContextTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ContextRaw is an auto generated low-level Go binding around an Ethereum contract. -type ContextRaw struct { - Contract *Context // Generic contract binding to access the raw methods on -} - -// ContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ContextCallerRaw struct { - Contract *ContextCaller // Generic read-only contract binding to access the raw methods on -} - -// ContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ContextTransactorRaw struct { - Contract *ContextTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewContext creates a new instance of Context, bound to a specific deployed contract. -func NewContext(address common.Address, backend bind.ContractBackend) (*Context, error) { - contract, err := bindContext(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Context{ContextCaller: ContextCaller{contract: contract}, ContextTransactor: ContextTransactor{contract: contract}, ContextFilterer: ContextFilterer{contract: contract}}, nil -} - -// NewContextCaller creates a new read-only instance of Context, bound to a specific deployed contract. -func NewContextCaller(address common.Address, caller bind.ContractCaller) (*ContextCaller, error) { - contract, err := bindContext(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ContextCaller{contract: contract}, nil -} - -// NewContextTransactor creates a new write-only instance of Context, bound to a specific deployed contract. -func NewContextTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextTransactor, error) { - contract, err := bindContext(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ContextTransactor{contract: contract}, nil -} - -// NewContextFilterer creates a new log filterer instance of Context, bound to a specific deployed contract. -func NewContextFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextFilterer, error) { - contract, err := bindContext(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ContextFilterer{contract: contract}, nil -} - -// bindContext binds a generic wrapper to an already deployed contract. -func bindContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(ContextABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Context *ContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Context.Contract.ContextCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Context *ContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Context.Contract.ContextTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Context *ContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Context.Contract.ContextTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Context *ContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Context.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Context *ContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Context.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Context.Contract.contract.Transact(opts, method, params...) -} - -// DepositFeedMetaData contains all meta data concerning the DepositFeed contract. -var DepositFeedMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", -} - -// DepositFeedABI is the input ABI used to generate the binding from. -// Deprecated: Use DepositFeedMetaData.ABI instead. -var DepositFeedABI = DepositFeedMetaData.ABI - -// DepositFeed is an auto generated Go binding around an Ethereum contract. -type DepositFeed struct { - DepositFeedCaller // Read-only binding to the contract - DepositFeedTransactor // Write-only binding to the contract - DepositFeedFilterer // Log filterer for contract events -} - -// DepositFeedCaller is an auto generated read-only Go binding around an Ethereum contract. -type DepositFeedCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DepositFeedTransactor is an auto generated write-only Go binding around an Ethereum contract. -type DepositFeedTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DepositFeedFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type DepositFeedFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DepositFeedSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type DepositFeedSession struct { - Contract *DepositFeed // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// DepositFeedCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type DepositFeedCallerSession struct { - Contract *DepositFeedCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// DepositFeedTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type DepositFeedTransactorSession struct { - Contract *DepositFeedTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// DepositFeedRaw is an auto generated low-level Go binding around an Ethereum contract. -type DepositFeedRaw struct { - Contract *DepositFeed // Generic contract binding to access the raw methods on -} - -// DepositFeedCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type DepositFeedCallerRaw struct { - Contract *DepositFeedCaller // Generic read-only contract binding to access the raw methods on -} - -// DepositFeedTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type DepositFeedTransactorRaw struct { - Contract *DepositFeedTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewDepositFeed creates a new instance of DepositFeed, bound to a specific deployed contract. -func NewDepositFeed(address common.Address, backend bind.ContractBackend) (*DepositFeed, error) { - contract, err := bindDepositFeed(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &DepositFeed{DepositFeedCaller: DepositFeedCaller{contract: contract}, DepositFeedTransactor: DepositFeedTransactor{contract: contract}, DepositFeedFilterer: DepositFeedFilterer{contract: contract}}, nil -} - -// NewDepositFeedCaller creates a new read-only instance of DepositFeed, bound to a specific deployed contract. -func NewDepositFeedCaller(address common.Address, caller bind.ContractCaller) (*DepositFeedCaller, error) { - contract, err := bindDepositFeed(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &DepositFeedCaller{contract: contract}, nil -} - -// NewDepositFeedTransactor creates a new write-only instance of DepositFeed, bound to a specific deployed contract. -func NewDepositFeedTransactor(address common.Address, transactor bind.ContractTransactor) (*DepositFeedTransactor, error) { - contract, err := bindDepositFeed(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &DepositFeedTransactor{contract: contract}, nil -} - -// NewDepositFeedFilterer creates a new log filterer instance of DepositFeed, bound to a specific deployed contract. -func NewDepositFeedFilterer(address common.Address, filterer bind.ContractFilterer) (*DepositFeedFilterer, error) { - contract, err := bindDepositFeed(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &DepositFeedFilterer{contract: contract}, nil -} - -// bindDepositFeed binds a generic wrapper to an already deployed contract. -func bindDepositFeed(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(DepositFeedABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_DepositFeed *DepositFeedRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DepositFeed.Contract.DepositFeedCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_DepositFeed *DepositFeedRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DepositFeed.Contract.DepositFeedTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DepositFeed *DepositFeedRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DepositFeed.Contract.DepositFeedTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_DepositFeed *DepositFeedCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DepositFeed.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_DepositFeed *DepositFeedTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DepositFeed.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DepositFeed *DepositFeedTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DepositFeed.Contract.contract.Transact(opts, method, params...) -} - -// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. -// -// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_DepositFeed *DepositFeedTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _DepositFeed.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) -} - -// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. -// -// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_DepositFeed *DepositFeedSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _DepositFeed.Contract.DepositTransaction(&_DepositFeed.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) -} - -// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. -// -// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_DepositFeed *DepositFeedTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _DepositFeed.Contract.DepositTransaction(&_DepositFeed.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) -} - -// DepositFeedTransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the DepositFeed contract. -type DepositFeedTransactionDepositedIterator struct { - Event *DepositFeedTransactionDeposited // 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 *DepositFeedTransactionDepositedIterator) 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(DepositFeedTransactionDeposited) - 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(DepositFeedTransactionDeposited) - 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 *DepositFeedTransactionDepositedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *DepositFeedTransactionDepositedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// DepositFeedTransactionDeposited represents a TransactionDeposited event raised by the DepositFeed contract. -type DepositFeedTransactionDeposited struct { - From common.Address - To common.Address - Mint *big.Int - Value *big.Int - GasLimit uint64 - IsCreation bool - Data []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. -// -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) -func (_DepositFeed *DepositFeedFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DepositFeedTransactionDepositedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _DepositFeed.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule) - if err != nil { - return nil, err - } - return &DepositFeedTransactionDepositedIterator{contract: _DepositFeed.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil -} - -// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. -// -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) -func (_DepositFeed *DepositFeedFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *DepositFeedTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _DepositFeed.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule) - 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(DepositFeedTransactionDeposited) - if err := _DepositFeed.contract.UnpackLog(event, "TransactionDeposited", 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 -} - -// ParseTransactionDeposited is a log parse operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. -// -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) -func (_DepositFeed *DepositFeedFilterer) ParseTransactionDeposited(log types.Log) (*DepositFeedTransactionDeposited, error) { - event := new(DepositFeedTransactionDeposited) - if err := _DepositFeed.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. -var L2OutputOracleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620016eb380380620016eb8339818101604052810190620000389190620002b3565b620000586200004c6200010760201b60201c565b6200010f60201b60201c565b600085876200006891906200037e565b14620000ab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000a2906200043d565b60405180910390fd5b85608081815250508460a081815250508360026000848152602001908152602001600020819055508260c08181525050816001819055508160e08181525050620000fb816200010f60201b60201c565b5050505050506200045f565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b620001ed81620001d8565b8114620001f957600080fd5b50565b6000815190506200020d81620001e2565b92915050565b6000819050919050565b620002288162000213565b81146200023457600080fd5b50565b60008151905062000248816200021d565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200027b826200024e565b9050919050565b6200028d816200026e565b81146200029957600080fd5b50565b600081519050620002ad8162000282565b92915050565b60008060008060008060c08789031215620002d357620002d2620001d3565b5b6000620002e389828a01620001fc565b9650506020620002f689828a01620001fc565b95505060406200030989828a0162000237565b94505060606200031c89828a01620001fc565b93505060806200032f89828a01620001fc565b92505060a06200034289828a016200029c565b9150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006200038b82620001d8565b91506200039883620001d8565b925082620003ab57620003aa6200034f565b5b828206905092915050565b600082825260208201905092915050565b7f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560008201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000602082015250565b600062000425603783620003b6565b91506200043282620003c7565b604082019050919050565b60006020820190508181036000830152620004588162000416565b9050919050565b60805160a05160c05160e051611228620004c36000396000818161031a0152818161039e015261077e0152600081816103d201526108940152600081816102f4015261037d0152600081816107110152818161074b01526107a201526112286000f3fe6080604052600436106100c15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b14610236578063a25ae55714610261578063a4771aad1461029e578063f2fde38b146102c9576100c1565b806341840fa6146101c9578063529933df146101f4578063715018a61461021f576100c1565b80622134cc146100c657806302e51345146100f15780630c1952d31461012e57806325188104146101595780632b5d15d914610175578063357e951f1461019e575b600080fd5b3480156100d257600080fd5b506100db6102f2565b6040516100e89190610a93565b60405180910390f35b3480156100fd57600080fd5b5061011860048036038101906101139190610adf565b610316565b6040516101259190610a93565b60405180910390f35b34801561013a57600080fd5b506101436103fa565b6040516101509190610a93565b60405180910390f35b610173600480360381019061016e9190610b42565b610400565b005b34801561018157600080fd5b5061019c60048036038101906101979190610ba9565b6105ee565b005b3480156101aa57600080fd5b506101b3610747565b6040516101c09190610a93565b60405180910390f35b3480156101d557600080fd5b506101de61077c565b6040516101eb9190610a93565b60405180910390f35b34801561020057600080fd5b506102096107a0565b6040516102169190610a93565b60405180910390f35b34801561022b57600080fd5b506102346107c4565b005b34801561024257600080fd5b5061024b61084c565b6040516102589190610c17565b60405180910390f35b34801561026d57600080fd5b5061028860048036038101906102839190610adf565b610875565b6040516102959190610c41565b60405180910390f35b3480156102aa57600080fd5b506102b3610892565b6040516102c09190610a93565b60405180910390f35b3480156102d557600080fd5b506102f060048036038101906102eb9190610c88565b6108b6565b005b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f000000000000000000000000000000000000000000000000000000000000000082101561037b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161037290610d38565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008303816103cd576103cc610d58565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6104086109ae565b73ffffffffffffffffffffffffffffffffffffffff1661042661084c565b73ffffffffffffffffffffffffffffffffffffffff161461047c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047390610dd3565b60405180910390fd5b4283106104be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b590610e65565b60405180910390fd5b6104c6610747565b8314610507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104fe90610ef7565b60405180910390fd5b6000801b84141561054d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161054490610f63565b60405180910390fd5b6000801b821461059b578181401461059a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059190610ff5565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b6105f66109ae565b73ffffffffffffffffffffffffffffffffffffffff1661061461084c565b73ffffffffffffffffffffffffffffffffffffffff161461066a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161066190610dd3565b60405180910390fd5b60006002600060015481526020019081526020016000205490508082146106c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106bd90611087565b60405180910390fd5b600154817f36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f26660405160405180910390a3600260006001548152602001908152602001600020600090557f000000000000000000000000000000000000000000000000000000000000000060015461073d91906110d6565b6001819055505050565b60007f0000000000000000000000000000000000000000000000000000000000000000600154610777919061110a565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6107cc6109ae565b73ffffffffffffffffffffffffffffffffffffffff166107ea61084c565b73ffffffffffffffffffffffffffffffffffffffff1614610840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083790610dd3565b60405180910390fd5b61084a60006109b6565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6108be6109ae565b73ffffffffffffffffffffffffffffffffffffffff166108dc61084c565b73ffffffffffffffffffffffffffffffffffffffff1614610932576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161092990610dd3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156109a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610999906111d2565b60405180910390fd5b6109ab816109b6565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b610a8d81610a7a565b82525050565b6000602082019050610aa86000830184610a84565b92915050565b600080fd5b610abc81610a7a565b8114610ac757600080fd5b50565b600081359050610ad981610ab3565b92915050565b600060208284031215610af557610af4610aae565b5b6000610b0384828501610aca565b91505092915050565b6000819050919050565b610b1f81610b0c565b8114610b2a57600080fd5b50565b600081359050610b3c81610b16565b92915050565b60008060008060808587031215610b5c57610b5b610aae565b5b6000610b6a87828801610b2d565b9450506020610b7b87828801610aca565b9350506040610b8c87828801610b2d565b9250506060610b9d87828801610aca565b91505092959194509250565b600060208284031215610bbf57610bbe610aae565b5b6000610bcd84828501610b2d565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610c0182610bd6565b9050919050565b610c1181610bf6565b82525050565b6000602082019050610c2c6000830184610c08565b92915050565b610c3b81610b0c565b82525050565b6000602082019050610c566000830184610c32565b92915050565b610c6581610bf6565b8114610c7057600080fd5b50565b600081359050610c8281610c5c565b92915050565b600060208284031215610c9e57610c9d610aae565b5b6000610cac84828501610c73565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610d22602983610cb5565b9150610d2d82610cc6565b604082019050919050565b60006020820190508181036000830152610d5181610d15565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610dbd602083610cb5565b9150610dc882610d87565b602082019050919050565b60006020820190508181036000830152610dec81610db0565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610e4f602183610cb5565b9150610e5a82610df3565b604082019050919050565b60006020820190508181036000830152610e7e81610e42565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610ee1602e83610cb5565b9150610eec82610e85565b604082019050919050565b60006020820190508181036000830152610f1081610ed4565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610f4d601d83610cb5565b9150610f5882610f17565b602082019050919050565b60006020820190508181036000830152610f7c81610f40565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610fdf603983610cb5565b9150610fea82610f83565b604082019050919050565b6000602082019050818103600083015261100e81610fd2565b9050919050565b7f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060008201527f6f75747075742e00000000000000000000000000000000000000000000000000602082015250565b6000611071602783610cb5565b915061107c82611015565b604082019050919050565b600060208201905081810360008301526110a081611064565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006110e182610a7a565b91506110ec83610a7a565b9250828210156110ff576110fe6110a7565b5b828203905092915050565b600061111582610a7a565b915061112083610a7a565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115611155576111546110a7565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006111bc602683610cb5565b91506111c782611160565b604082019050919050565b600060208201905081810360008301526111eb816111af565b905091905056fea2646970667358221220c4ef1d00f7f2659b0bb4c745bd02e768e44edce52f60d1b4607f3f90d6b2b7d664736f6c634300080a0033", -} - -// L2OutputOracleABI is the input ABI used to generate the binding from. -// Deprecated: Use L2OutputOracleMetaData.ABI instead. -var L2OutputOracleABI = L2OutputOracleMetaData.ABI - -// L2OutputOracleBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use L2OutputOracleMetaData.Bin instead. -var L2OutputOracleBin = L2OutputOracleMetaData.Bin - -// DeployL2OutputOracle deploys a new Ethereum contract, binding an instance of L2OutputOracle to it. -func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionInterval *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int, _startingBlockTimestamp *big.Int, sequencer common.Address) (common.Address, *types.Transaction, *L2OutputOracle, error) { - parsed, err := L2OutputOracleMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L2OutputOracleBin), backend, _submissionInterval, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks, _startingBlockTimestamp, sequencer) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &L2OutputOracle{L2OutputOracleCaller: L2OutputOracleCaller{contract: contract}, L2OutputOracleTransactor: L2OutputOracleTransactor{contract: contract}, L2OutputOracleFilterer: L2OutputOracleFilterer{contract: contract}}, nil -} - -// L2OutputOracle is an auto generated Go binding around an Ethereum contract. -type L2OutputOracle struct { - L2OutputOracleCaller // Read-only binding to the contract - L2OutputOracleTransactor // Write-only binding to the contract - L2OutputOracleFilterer // Log filterer for contract events -} - -// L2OutputOracleCaller is an auto generated read-only Go binding around an Ethereum contract. -type L2OutputOracleCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// L2OutputOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. -type L2OutputOracleTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// L2OutputOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type L2OutputOracleFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// L2OutputOracleSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type L2OutputOracleSession struct { - Contract *L2OutputOracle // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// L2OutputOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type L2OutputOracleCallerSession struct { - Contract *L2OutputOracleCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// L2OutputOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type L2OutputOracleTransactorSession struct { - Contract *L2OutputOracleTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// L2OutputOracleRaw is an auto generated low-level Go binding around an Ethereum contract. -type L2OutputOracleRaw struct { - Contract *L2OutputOracle // Generic contract binding to access the raw methods on -} - -// L2OutputOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type L2OutputOracleCallerRaw struct { - Contract *L2OutputOracleCaller // Generic read-only contract binding to access the raw methods on -} - -// L2OutputOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type L2OutputOracleTransactorRaw struct { - Contract *L2OutputOracleTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewL2OutputOracle creates a new instance of L2OutputOracle, bound to a specific deployed contract. -func NewL2OutputOracle(address common.Address, backend bind.ContractBackend) (*L2OutputOracle, error) { - contract, err := bindL2OutputOracle(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &L2OutputOracle{L2OutputOracleCaller: L2OutputOracleCaller{contract: contract}, L2OutputOracleTransactor: L2OutputOracleTransactor{contract: contract}, L2OutputOracleFilterer: L2OutputOracleFilterer{contract: contract}}, nil -} - -// NewL2OutputOracleCaller creates a new read-only instance of L2OutputOracle, bound to a specific deployed contract. -func NewL2OutputOracleCaller(address common.Address, caller bind.ContractCaller) (*L2OutputOracleCaller, error) { - contract, err := bindL2OutputOracle(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &L2OutputOracleCaller{contract: contract}, nil -} - -// NewL2OutputOracleTransactor creates a new write-only instance of L2OutputOracle, bound to a specific deployed contract. -func NewL2OutputOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*L2OutputOracleTransactor, error) { - contract, err := bindL2OutputOracle(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &L2OutputOracleTransactor{contract: contract}, nil -} - -// NewL2OutputOracleFilterer creates a new log filterer instance of L2OutputOracle, bound to a specific deployed contract. -func NewL2OutputOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*L2OutputOracleFilterer, error) { - contract, err := bindL2OutputOracle(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &L2OutputOracleFilterer{contract: contract}, nil -} - -// bindL2OutputOracle binds a generic wrapper to an already deployed contract. -func bindL2OutputOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(L2OutputOracleABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_L2OutputOracle *L2OutputOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _L2OutputOracle.Contract.L2OutputOracleCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_L2OutputOracle *L2OutputOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _L2OutputOracle.Contract.L2OutputOracleTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_L2OutputOracle *L2OutputOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _L2OutputOracle.Contract.L2OutputOracleTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_L2OutputOracle *L2OutputOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _L2OutputOracle.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _L2OutputOracle.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _L2OutputOracle.Contract.contract.Transact(opts, method, params...) -} - -// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. -// -// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) HISTORICALTOTALBLOCKS(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "HISTORICAL_TOTAL_BLOCKS") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. -// -// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) HISTORICALTOTALBLOCKS() (*big.Int, error) { - return _L2OutputOracle.Contract.HISTORICALTOTALBLOCKS(&_L2OutputOracle.CallOpts) -} - -// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. -// -// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) HISTORICALTOTALBLOCKS() (*big.Int, error) { - return _L2OutputOracle.Contract.HISTORICALTOTALBLOCKS(&_L2OutputOracle.CallOpts) -} - -// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. -// -// Solidity: function L2_BLOCK_TIME() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) L2BLOCKTIME(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "L2_BLOCK_TIME") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. -// -// Solidity: function L2_BLOCK_TIME() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) L2BLOCKTIME() (*big.Int, error) { - return _L2OutputOracle.Contract.L2BLOCKTIME(&_L2OutputOracle.CallOpts) -} - -// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. -// -// Solidity: function L2_BLOCK_TIME() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) L2BLOCKTIME() (*big.Int, error) { - return _L2OutputOracle.Contract.L2BLOCKTIME(&_L2OutputOracle.CallOpts) -} - -// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. -// -// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) STARTINGBLOCKTIMESTAMP(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "STARTING_BLOCK_TIMESTAMP") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. -// -// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) { - return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts) -} - -// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. -// -// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) { - return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts) -} - -// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. -// -// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) SUBMISSIONINTERVAL(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "SUBMISSION_INTERVAL") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. -// -// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) SUBMISSIONINTERVAL() (*big.Int, error) { - return _L2OutputOracle.Contract.SUBMISSIONINTERVAL(&_L2OutputOracle.CallOpts) -} - -// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. -// -// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) SUBMISSIONINTERVAL() (*big.Int, error) { - return _L2OutputOracle.Contract.SUBMISSIONINTERVAL(&_L2OutputOracle.CallOpts) -} - -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. -// -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. -// -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { - return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) -} - -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. -// -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { - return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) -} - -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. -// -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. -// -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { - return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) -} - -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. -// -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { - return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) -} - -// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. -// -// Solidity: function latestBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) LatestBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "latestBlockTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. -// -// Solidity: function latestBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) LatestBlockTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts) -} - -// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. -// -// Solidity: function latestBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) LatestBlockTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts) -} - -// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. -// -// Solidity: function nextTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) NextTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "nextTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. -// -// Solidity: function nextTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) NextTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts) -} - -// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f. -// -// Solidity: function nextTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) NextTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_L2OutputOracle *L2OutputOracleCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_L2OutputOracle *L2OutputOracleSession) Owner() (common.Address, error) { - return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_L2OutputOracle *L2OutputOracleCallerSession) Owner() (common.Address, error) { - return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) -} - -// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. -// -// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() -func (_L2OutputOracle *L2OutputOracleTransactor) AppendL2Output(opts *bind.TransactOpts, _l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { - return _L2OutputOracle.contract.Transact(opts, "appendL2Output", _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) -} - -// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. -// -// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() -func (_L2OutputOracle *L2OutputOracleSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { - return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) -} - -// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. -// -// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() -func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) { - return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) -} - -// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. -// -// Solidity: function deleteL2Output(bytes32 _l2Output) returns() -func (_L2OutputOracle *L2OutputOracleTransactor) DeleteL2Output(opts *bind.TransactOpts, _l2Output [32]byte) (*types.Transaction, error) { - return _L2OutputOracle.contract.Transact(opts, "deleteL2Output", _l2Output) -} - -// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. -// -// Solidity: function deleteL2Output(bytes32 _l2Output) returns() -func (_L2OutputOracle *L2OutputOracleSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { - return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) -} - -// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. -// -// Solidity: function deleteL2Output(bytes32 _l2Output) returns() -func (_L2OutputOracle *L2OutputOracleTransactorSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { - return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_L2OutputOracle *L2OutputOracleTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _L2OutputOracle.contract.Transact(opts, "renounceOwnership") -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_L2OutputOracle *L2OutputOracleSession) RenounceOwnership() (*types.Transaction, error) { - return _L2OutputOracle.Contract.RenounceOwnership(&_L2OutputOracle.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_L2OutputOracle *L2OutputOracleTransactorSession) RenounceOwnership() (*types.Transaction, error) { - return _L2OutputOracle.Contract.RenounceOwnership(&_L2OutputOracle.TransactOpts) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_L2OutputOracle *L2OutputOracleTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { - return _L2OutputOracle.contract.Transact(opts, "transferOwnership", newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_L2OutputOracle *L2OutputOracleSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _L2OutputOracle.Contract.TransferOwnership(&_L2OutputOracle.TransactOpts, newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_L2OutputOracle *L2OutputOracleTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _L2OutputOracle.Contract.TransferOwnership(&_L2OutputOracle.TransactOpts, newOwner) -} - -// L2OutputOracleOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the L2OutputOracle contract. -type L2OutputOracleOwnershipTransferredIterator struct { - Event *L2OutputOracleOwnershipTransferred // 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 *L2OutputOracleOwnershipTransferredIterator) 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(L2OutputOracleOwnershipTransferred) - 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(L2OutputOracleOwnershipTransferred) - 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 *L2OutputOracleOwnershipTransferredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *L2OutputOracleOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// L2OutputOracleOwnershipTransferred represents a OwnershipTransferred event raised by the L2OutputOracle contract. -type L2OutputOracleOwnershipTransferred struct { - PreviousOwner common.Address - NewOwner common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_L2OutputOracle *L2OutputOracleFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*L2OutputOracleOwnershipTransferredIterator, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return &L2OutputOracleOwnershipTransferredIterator{contract: _L2OutputOracle.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_L2OutputOracle *L2OutputOracleFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *L2OutputOracleOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - 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(L2OutputOracleOwnershipTransferred) - if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", 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 -} - -// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_L2OutputOracle *L2OutputOracleFilterer) ParseOwnershipTransferred(log types.Log) (*L2OutputOracleOwnershipTransferred, error) { - event := new(L2OutputOracleOwnershipTransferred) - if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// L2OutputOracleL2OutputAppendedIterator is returned from FilterL2OutputAppended and is used to iterate over the raw logs and unpacked data for L2OutputAppended events raised by the L2OutputOracle contract. -type L2OutputOracleL2OutputAppendedIterator struct { - Event *L2OutputOracleL2OutputAppended // 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 *L2OutputOracleL2OutputAppendedIterator) 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(L2OutputOracleL2OutputAppended) - 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(L2OutputOracleL2OutputAppended) - 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 *L2OutputOracleL2OutputAppendedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *L2OutputOracleL2OutputAppendedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// L2OutputOracleL2OutputAppended represents a L2OutputAppended event raised by the L2OutputOracle contract. -type L2OutputOracleL2OutputAppended struct { - L2Output [32]byte - L2timestamp *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterL2OutputAppended is a free log retrieval operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. -// -// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputAppendedIterator, error) { - - var _l2OutputRule []interface{} - for _, _l2OutputItem := range _l2Output { - _l2OutputRule = append(_l2OutputRule, _l2OutputItem) - } - var _l2timestampRule []interface{} - for _, _l2timestampItem := range _l2timestamp { - _l2timestampRule = append(_l2timestampRule, _l2timestampItem) - } - - logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) - if err != nil { - return nil, err - } - return &L2OutputOracleL2OutputAppendedIterator{contract: _L2OutputOracle.contract, event: "l2OutputAppended", logs: logs, sub: sub}, nil -} - -// WatchL2OutputAppended is a free log subscription operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. -// -// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputAppended, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { - - var _l2OutputRule []interface{} - for _, _l2OutputItem := range _l2Output { - _l2OutputRule = append(_l2OutputRule, _l2OutputItem) - } - var _l2timestampRule []interface{} - for _, _l2timestampItem := range _l2timestamp { - _l2timestampRule = append(_l2timestampRule, _l2timestampItem) - } - - logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) - 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(L2OutputOracleL2OutputAppended) - if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", 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 -} - -// ParseL2OutputAppended is a log parse operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. -// -// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.Log) (*L2OutputOracleL2OutputAppended, error) { - event := new(L2OutputOracleL2OutputAppended) - if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// L2OutputOracleL2OutputDeletedIterator is returned from FilterL2OutputDeleted and is used to iterate over the raw logs and unpacked data for L2OutputDeleted events raised by the L2OutputOracle contract. -type L2OutputOracleL2OutputDeletedIterator struct { - Event *L2OutputOracleL2OutputDeleted // 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 *L2OutputOracleL2OutputDeletedIterator) 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(L2OutputOracleL2OutputDeleted) - 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(L2OutputOracleL2OutputDeleted) - 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 *L2OutputOracleL2OutputDeletedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *L2OutputOracleL2OutputDeletedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// L2OutputOracleL2OutputDeleted represents a L2OutputDeleted event raised by the L2OutputOracle contract. -type L2OutputOracleL2OutputDeleted struct { - L2Output [32]byte - L2timestamp *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterL2OutputDeleted is a free log retrieval operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. -// -// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputDeleted(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputDeletedIterator, error) { - - var _l2OutputRule []interface{} - for _, _l2OutputItem := range _l2Output { - _l2OutputRule = append(_l2OutputRule, _l2OutputItem) - } - var _l2timestampRule []interface{} - for _, _l2timestampItem := range _l2timestamp { - _l2timestampRule = append(_l2timestampRule, _l2timestampItem) - } - - logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) - if err != nil { - return nil, err - } - return &L2OutputOracleL2OutputDeletedIterator{contract: _L2OutputOracle.contract, event: "l2OutputDeleted", logs: logs, sub: sub}, nil -} - -// WatchL2OutputDeleted is a free log subscription operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. -// -// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputDeleted, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { - - var _l2OutputRule []interface{} - for _, _l2OutputItem := range _l2Output { - _l2OutputRule = append(_l2OutputRule, _l2OutputItem) - } - var _l2timestampRule []interface{} - for _, _l2timestampItem := range _l2timestamp { - _l2timestampRule = append(_l2timestampRule, _l2timestampItem) - } - - logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) - 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(L2OutputOracleL2OutputDeleted) - if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", 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 -} - -// ParseL2OutputDeleted is a log parse operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. -// -// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputDeleted(log types.Log) (*L2OutputOracleL2OutputDeleted, error) { - event := new(L2OutputOracleL2OutputDeleted) - if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// LibBytesUtilsMetaData contains all meta data concerning the LibBytesUtils contract. -var LibBytesUtilsMetaData = &bind.MetaData{ - ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e958e3c5fd0868451927cf89f50e248831442cc24af29e21bca4bc8a02ffeb9764736f6c634300080a0033", -} - -// LibBytesUtilsABI is the input ABI used to generate the binding from. -// Deprecated: Use LibBytesUtilsMetaData.ABI instead. -var LibBytesUtilsABI = LibBytesUtilsMetaData.ABI - -// LibBytesUtilsBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use LibBytesUtilsMetaData.Bin instead. -var LibBytesUtilsBin = LibBytesUtilsMetaData.Bin - -// DeployLibBytesUtils deploys a new Ethereum contract, binding an instance of LibBytesUtils to it. -func DeployLibBytesUtils(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibBytesUtils, error) { - parsed, err := LibBytesUtilsMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibBytesUtilsBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LibBytesUtils{LibBytesUtilsCaller: LibBytesUtilsCaller{contract: contract}, LibBytesUtilsTransactor: LibBytesUtilsTransactor{contract: contract}, LibBytesUtilsFilterer: LibBytesUtilsFilterer{contract: contract}}, nil -} - -// LibBytesUtils is an auto generated Go binding around an Ethereum contract. -type LibBytesUtils struct { - LibBytesUtilsCaller // Read-only binding to the contract - LibBytesUtilsTransactor // Write-only binding to the contract - LibBytesUtilsFilterer // Log filterer for contract events -} - -// LibBytesUtilsCaller is an auto generated read-only Go binding around an Ethereum contract. -type LibBytesUtilsCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibBytesUtilsTransactor is an auto generated write-only Go binding around an Ethereum contract. -type LibBytesUtilsTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibBytesUtilsFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type LibBytesUtilsFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibBytesUtilsSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type LibBytesUtilsSession struct { - Contract *LibBytesUtils // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibBytesUtilsCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type LibBytesUtilsCallerSession struct { - Contract *LibBytesUtilsCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// LibBytesUtilsTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type LibBytesUtilsTransactorSession struct { - Contract *LibBytesUtilsTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibBytesUtilsRaw is an auto generated low-level Go binding around an Ethereum contract. -type LibBytesUtilsRaw struct { - Contract *LibBytesUtils // Generic contract binding to access the raw methods on -} - -// LibBytesUtilsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type LibBytesUtilsCallerRaw struct { - Contract *LibBytesUtilsCaller // Generic read-only contract binding to access the raw methods on -} - -// LibBytesUtilsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type LibBytesUtilsTransactorRaw struct { - Contract *LibBytesUtilsTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewLibBytesUtils creates a new instance of LibBytesUtils, bound to a specific deployed contract. -func NewLibBytesUtils(address common.Address, backend bind.ContractBackend) (*LibBytesUtils, error) { - contract, err := bindLibBytesUtils(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LibBytesUtils{LibBytesUtilsCaller: LibBytesUtilsCaller{contract: contract}, LibBytesUtilsTransactor: LibBytesUtilsTransactor{contract: contract}, LibBytesUtilsFilterer: LibBytesUtilsFilterer{contract: contract}}, nil -} - -// NewLibBytesUtilsCaller creates a new read-only instance of LibBytesUtils, bound to a specific deployed contract. -func NewLibBytesUtilsCaller(address common.Address, caller bind.ContractCaller) (*LibBytesUtilsCaller, error) { - contract, err := bindLibBytesUtils(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LibBytesUtilsCaller{contract: contract}, nil -} - -// NewLibBytesUtilsTransactor creates a new write-only instance of LibBytesUtils, bound to a specific deployed contract. -func NewLibBytesUtilsTransactor(address common.Address, transactor bind.ContractTransactor) (*LibBytesUtilsTransactor, error) { - contract, err := bindLibBytesUtils(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LibBytesUtilsTransactor{contract: contract}, nil -} - -// NewLibBytesUtilsFilterer creates a new log filterer instance of LibBytesUtils, bound to a specific deployed contract. -func NewLibBytesUtilsFilterer(address common.Address, filterer bind.ContractFilterer) (*LibBytesUtilsFilterer, error) { - contract, err := bindLibBytesUtils(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LibBytesUtilsFilterer{contract: contract}, nil -} - -// bindLibBytesUtils binds a generic wrapper to an already deployed contract. -func bindLibBytesUtils(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(LibBytesUtilsABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibBytesUtils *LibBytesUtilsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibBytesUtils.Contract.LibBytesUtilsCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibBytesUtils *LibBytesUtilsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibBytesUtils.Contract.LibBytesUtilsTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibBytesUtils *LibBytesUtilsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibBytesUtils.Contract.LibBytesUtilsTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibBytesUtils *LibBytesUtilsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibBytesUtils.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibBytesUtils *LibBytesUtilsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibBytesUtils.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibBytesUtils *LibBytesUtilsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibBytesUtils.Contract.contract.Transact(opts, method, params...) -} - -// LibMerkleTrieMetaData contains all meta data concerning the LibMerkleTrie contract. -var LibMerkleTrieMetaData = &bind.MetaData{ - ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212204e5467228078a9262e6dfded9555ccabe760347ff5c34b33bdd846b1084e54b764736f6c634300080a0033", -} - -// LibMerkleTrieABI is the input ABI used to generate the binding from. -// Deprecated: Use LibMerkleTrieMetaData.ABI instead. -var LibMerkleTrieABI = LibMerkleTrieMetaData.ABI - -// LibMerkleTrieBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use LibMerkleTrieMetaData.Bin instead. -var LibMerkleTrieBin = LibMerkleTrieMetaData.Bin - -// DeployLibMerkleTrie deploys a new Ethereum contract, binding an instance of LibMerkleTrie to it. -func DeployLibMerkleTrie(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibMerkleTrie, error) { - parsed, err := LibMerkleTrieMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibMerkleTrieBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LibMerkleTrie{LibMerkleTrieCaller: LibMerkleTrieCaller{contract: contract}, LibMerkleTrieTransactor: LibMerkleTrieTransactor{contract: contract}, LibMerkleTrieFilterer: LibMerkleTrieFilterer{contract: contract}}, nil -} - -// LibMerkleTrie is an auto generated Go binding around an Ethereum contract. -type LibMerkleTrie struct { - LibMerkleTrieCaller // Read-only binding to the contract - LibMerkleTrieTransactor // Write-only binding to the contract - LibMerkleTrieFilterer // Log filterer for contract events -} - -// LibMerkleTrieCaller is an auto generated read-only Go binding around an Ethereum contract. -type LibMerkleTrieCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibMerkleTrieTransactor is an auto generated write-only Go binding around an Ethereum contract. -type LibMerkleTrieTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibMerkleTrieFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type LibMerkleTrieFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibMerkleTrieSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type LibMerkleTrieSession struct { - Contract *LibMerkleTrie // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibMerkleTrieCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type LibMerkleTrieCallerSession struct { - Contract *LibMerkleTrieCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// LibMerkleTrieTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type LibMerkleTrieTransactorSession struct { - Contract *LibMerkleTrieTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibMerkleTrieRaw is an auto generated low-level Go binding around an Ethereum contract. -type LibMerkleTrieRaw struct { - Contract *LibMerkleTrie // Generic contract binding to access the raw methods on -} - -// LibMerkleTrieCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type LibMerkleTrieCallerRaw struct { - Contract *LibMerkleTrieCaller // Generic read-only contract binding to access the raw methods on -} - -// LibMerkleTrieTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type LibMerkleTrieTransactorRaw struct { - Contract *LibMerkleTrieTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewLibMerkleTrie creates a new instance of LibMerkleTrie, bound to a specific deployed contract. -func NewLibMerkleTrie(address common.Address, backend bind.ContractBackend) (*LibMerkleTrie, error) { - contract, err := bindLibMerkleTrie(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LibMerkleTrie{LibMerkleTrieCaller: LibMerkleTrieCaller{contract: contract}, LibMerkleTrieTransactor: LibMerkleTrieTransactor{contract: contract}, LibMerkleTrieFilterer: LibMerkleTrieFilterer{contract: contract}}, nil -} - -// NewLibMerkleTrieCaller creates a new read-only instance of LibMerkleTrie, bound to a specific deployed contract. -func NewLibMerkleTrieCaller(address common.Address, caller bind.ContractCaller) (*LibMerkleTrieCaller, error) { - contract, err := bindLibMerkleTrie(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LibMerkleTrieCaller{contract: contract}, nil -} - -// NewLibMerkleTrieTransactor creates a new write-only instance of LibMerkleTrie, bound to a specific deployed contract. -func NewLibMerkleTrieTransactor(address common.Address, transactor bind.ContractTransactor) (*LibMerkleTrieTransactor, error) { - contract, err := bindLibMerkleTrie(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LibMerkleTrieTransactor{contract: contract}, nil -} - -// NewLibMerkleTrieFilterer creates a new log filterer instance of LibMerkleTrie, bound to a specific deployed contract. -func NewLibMerkleTrieFilterer(address common.Address, filterer bind.ContractFilterer) (*LibMerkleTrieFilterer, error) { - contract, err := bindLibMerkleTrie(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LibMerkleTrieFilterer{contract: contract}, nil -} - -// bindLibMerkleTrie binds a generic wrapper to an already deployed contract. -func bindLibMerkleTrie(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(LibMerkleTrieABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibMerkleTrie *LibMerkleTrieRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibMerkleTrie.Contract.LibMerkleTrieCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibMerkleTrie *LibMerkleTrieRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibMerkleTrie.Contract.LibMerkleTrieTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibMerkleTrie *LibMerkleTrieRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibMerkleTrie.Contract.LibMerkleTrieTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibMerkleTrie *LibMerkleTrieCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibMerkleTrie.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibMerkleTrie *LibMerkleTrieTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibMerkleTrie.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibMerkleTrie *LibMerkleTrieTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibMerkleTrie.Contract.contract.Transact(opts, method, params...) -} - -// LibRLPReaderMetaData contains all meta data concerning the LibRLPReader contract. -var LibRLPReaderMetaData = &bind.MetaData{ - ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e5de027b2466f0cb69615d578b02779f2ad9c727a9dd3b17b8e9279e3334f80864736f6c634300080a0033", -} - -// LibRLPReaderABI is the input ABI used to generate the binding from. -// Deprecated: Use LibRLPReaderMetaData.ABI instead. -var LibRLPReaderABI = LibRLPReaderMetaData.ABI - -// LibRLPReaderBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use LibRLPReaderMetaData.Bin instead. -var LibRLPReaderBin = LibRLPReaderMetaData.Bin - -// DeployLibRLPReader deploys a new Ethereum contract, binding an instance of LibRLPReader to it. -func DeployLibRLPReader(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibRLPReader, error) { - parsed, err := LibRLPReaderMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibRLPReaderBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LibRLPReader{LibRLPReaderCaller: LibRLPReaderCaller{contract: contract}, LibRLPReaderTransactor: LibRLPReaderTransactor{contract: contract}, LibRLPReaderFilterer: LibRLPReaderFilterer{contract: contract}}, nil -} - -// LibRLPReader is an auto generated Go binding around an Ethereum contract. -type LibRLPReader struct { - LibRLPReaderCaller // Read-only binding to the contract - LibRLPReaderTransactor // Write-only binding to the contract - LibRLPReaderFilterer // Log filterer for contract events -} - -// LibRLPReaderCaller is an auto generated read-only Go binding around an Ethereum contract. -type LibRLPReaderCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibRLPReaderTransactor is an auto generated write-only Go binding around an Ethereum contract. -type LibRLPReaderTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibRLPReaderFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type LibRLPReaderFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibRLPReaderSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type LibRLPReaderSession struct { - Contract *LibRLPReader // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibRLPReaderCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type LibRLPReaderCallerSession struct { - Contract *LibRLPReaderCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// LibRLPReaderTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type LibRLPReaderTransactorSession struct { - Contract *LibRLPReaderTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibRLPReaderRaw is an auto generated low-level Go binding around an Ethereum contract. -type LibRLPReaderRaw struct { - Contract *LibRLPReader // Generic contract binding to access the raw methods on -} - -// LibRLPReaderCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type LibRLPReaderCallerRaw struct { - Contract *LibRLPReaderCaller // Generic read-only contract binding to access the raw methods on -} - -// LibRLPReaderTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type LibRLPReaderTransactorRaw struct { - Contract *LibRLPReaderTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewLibRLPReader creates a new instance of LibRLPReader, bound to a specific deployed contract. -func NewLibRLPReader(address common.Address, backend bind.ContractBackend) (*LibRLPReader, error) { - contract, err := bindLibRLPReader(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LibRLPReader{LibRLPReaderCaller: LibRLPReaderCaller{contract: contract}, LibRLPReaderTransactor: LibRLPReaderTransactor{contract: contract}, LibRLPReaderFilterer: LibRLPReaderFilterer{contract: contract}}, nil -} - -// NewLibRLPReaderCaller creates a new read-only instance of LibRLPReader, bound to a specific deployed contract. -func NewLibRLPReaderCaller(address common.Address, caller bind.ContractCaller) (*LibRLPReaderCaller, error) { - contract, err := bindLibRLPReader(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LibRLPReaderCaller{contract: contract}, nil -} - -// NewLibRLPReaderTransactor creates a new write-only instance of LibRLPReader, bound to a specific deployed contract. -func NewLibRLPReaderTransactor(address common.Address, transactor bind.ContractTransactor) (*LibRLPReaderTransactor, error) { - contract, err := bindLibRLPReader(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LibRLPReaderTransactor{contract: contract}, nil -} - -// NewLibRLPReaderFilterer creates a new log filterer instance of LibRLPReader, bound to a specific deployed contract. -func NewLibRLPReaderFilterer(address common.Address, filterer bind.ContractFilterer) (*LibRLPReaderFilterer, error) { - contract, err := bindLibRLPReader(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LibRLPReaderFilterer{contract: contract}, nil -} - -// bindLibRLPReader binds a generic wrapper to an already deployed contract. -func bindLibRLPReader(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(LibRLPReaderABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibRLPReader *LibRLPReaderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibRLPReader.Contract.LibRLPReaderCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibRLPReader *LibRLPReaderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibRLPReader.Contract.LibRLPReaderTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibRLPReader *LibRLPReaderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibRLPReader.Contract.LibRLPReaderTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibRLPReader *LibRLPReaderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibRLPReader.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibRLPReader *LibRLPReaderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibRLPReader.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibRLPReader *LibRLPReaderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibRLPReader.Contract.contract.Transact(opts, method, params...) -} - -// LibRLPWriterMetaData contains all meta data concerning the LibRLPWriter contract. -var LibRLPWriterMetaData = &bind.MetaData{ - ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220bef8e644bef83a13fe830ce5a62f8dd508a8ed03087ab7d1f194c2164c3d8cfe64736f6c634300080a0033", -} - -// LibRLPWriterABI is the input ABI used to generate the binding from. -// Deprecated: Use LibRLPWriterMetaData.ABI instead. -var LibRLPWriterABI = LibRLPWriterMetaData.ABI - -// LibRLPWriterBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use LibRLPWriterMetaData.Bin instead. -var LibRLPWriterBin = LibRLPWriterMetaData.Bin - -// DeployLibRLPWriter deploys a new Ethereum contract, binding an instance of LibRLPWriter to it. -func DeployLibRLPWriter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibRLPWriter, error) { - parsed, err := LibRLPWriterMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibRLPWriterBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LibRLPWriter{LibRLPWriterCaller: LibRLPWriterCaller{contract: contract}, LibRLPWriterTransactor: LibRLPWriterTransactor{contract: contract}, LibRLPWriterFilterer: LibRLPWriterFilterer{contract: contract}}, nil -} - -// LibRLPWriter is an auto generated Go binding around an Ethereum contract. -type LibRLPWriter struct { - LibRLPWriterCaller // Read-only binding to the contract - LibRLPWriterTransactor // Write-only binding to the contract - LibRLPWriterFilterer // Log filterer for contract events -} - -// LibRLPWriterCaller is an auto generated read-only Go binding around an Ethereum contract. -type LibRLPWriterCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibRLPWriterTransactor is an auto generated write-only Go binding around an Ethereum contract. -type LibRLPWriterTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibRLPWriterFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type LibRLPWriterFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibRLPWriterSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type LibRLPWriterSession struct { - Contract *LibRLPWriter // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibRLPWriterCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type LibRLPWriterCallerSession struct { - Contract *LibRLPWriterCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// LibRLPWriterTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type LibRLPWriterTransactorSession struct { - Contract *LibRLPWriterTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibRLPWriterRaw is an auto generated low-level Go binding around an Ethereum contract. -type LibRLPWriterRaw struct { - Contract *LibRLPWriter // Generic contract binding to access the raw methods on -} - -// LibRLPWriterCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type LibRLPWriterCallerRaw struct { - Contract *LibRLPWriterCaller // Generic read-only contract binding to access the raw methods on -} - -// LibRLPWriterTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type LibRLPWriterTransactorRaw struct { - Contract *LibRLPWriterTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewLibRLPWriter creates a new instance of LibRLPWriter, bound to a specific deployed contract. -func NewLibRLPWriter(address common.Address, backend bind.ContractBackend) (*LibRLPWriter, error) { - contract, err := bindLibRLPWriter(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LibRLPWriter{LibRLPWriterCaller: LibRLPWriterCaller{contract: contract}, LibRLPWriterTransactor: LibRLPWriterTransactor{contract: contract}, LibRLPWriterFilterer: LibRLPWriterFilterer{contract: contract}}, nil -} - -// NewLibRLPWriterCaller creates a new read-only instance of LibRLPWriter, bound to a specific deployed contract. -func NewLibRLPWriterCaller(address common.Address, caller bind.ContractCaller) (*LibRLPWriterCaller, error) { - contract, err := bindLibRLPWriter(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LibRLPWriterCaller{contract: contract}, nil -} - -// NewLibRLPWriterTransactor creates a new write-only instance of LibRLPWriter, bound to a specific deployed contract. -func NewLibRLPWriterTransactor(address common.Address, transactor bind.ContractTransactor) (*LibRLPWriterTransactor, error) { - contract, err := bindLibRLPWriter(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LibRLPWriterTransactor{contract: contract}, nil -} - -// NewLibRLPWriterFilterer creates a new log filterer instance of LibRLPWriter, bound to a specific deployed contract. -func NewLibRLPWriterFilterer(address common.Address, filterer bind.ContractFilterer) (*LibRLPWriterFilterer, error) { - contract, err := bindLibRLPWriter(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LibRLPWriterFilterer{contract: contract}, nil -} - -// bindLibRLPWriter binds a generic wrapper to an already deployed contract. -func bindLibRLPWriter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(LibRLPWriterABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibRLPWriter *LibRLPWriterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibRLPWriter.Contract.LibRLPWriterCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibRLPWriter *LibRLPWriterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibRLPWriter.Contract.LibRLPWriterTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibRLPWriter *LibRLPWriterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibRLPWriter.Contract.LibRLPWriterTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibRLPWriter *LibRLPWriterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibRLPWriter.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibRLPWriter *LibRLPWriterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibRLPWriter.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibRLPWriter *LibRLPWriterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibRLPWriter.Contract.contract.Transact(opts, method, params...) -} - -// LibSecureMerkleTrieMetaData contains all meta data concerning the LibSecureMerkleTrie contract. -var LibSecureMerkleTrieMetaData = &bind.MetaData{ - ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202826b55c1fd499dcab01cf9cefa4f87b2c8d925e6014f9f077213f8dbc479ba964736f6c634300080a0033", -} - -// LibSecureMerkleTrieABI is the input ABI used to generate the binding from. -// Deprecated: Use LibSecureMerkleTrieMetaData.ABI instead. -var LibSecureMerkleTrieABI = LibSecureMerkleTrieMetaData.ABI - -// LibSecureMerkleTrieBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use LibSecureMerkleTrieMetaData.Bin instead. -var LibSecureMerkleTrieBin = LibSecureMerkleTrieMetaData.Bin - -// DeployLibSecureMerkleTrie deploys a new Ethereum contract, binding an instance of LibSecureMerkleTrie to it. -func DeployLibSecureMerkleTrie(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LibSecureMerkleTrie, error) { - parsed, err := LibSecureMerkleTrieMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LibSecureMerkleTrieBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LibSecureMerkleTrie{LibSecureMerkleTrieCaller: LibSecureMerkleTrieCaller{contract: contract}, LibSecureMerkleTrieTransactor: LibSecureMerkleTrieTransactor{contract: contract}, LibSecureMerkleTrieFilterer: LibSecureMerkleTrieFilterer{contract: contract}}, nil -} - -// LibSecureMerkleTrie is an auto generated Go binding around an Ethereum contract. -type LibSecureMerkleTrie struct { - LibSecureMerkleTrieCaller // Read-only binding to the contract - LibSecureMerkleTrieTransactor // Write-only binding to the contract - LibSecureMerkleTrieFilterer // Log filterer for contract events -} - -// LibSecureMerkleTrieCaller is an auto generated read-only Go binding around an Ethereum contract. -type LibSecureMerkleTrieCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibSecureMerkleTrieTransactor is an auto generated write-only Go binding around an Ethereum contract. -type LibSecureMerkleTrieTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibSecureMerkleTrieFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type LibSecureMerkleTrieFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LibSecureMerkleTrieSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type LibSecureMerkleTrieSession struct { - Contract *LibSecureMerkleTrie // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibSecureMerkleTrieCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type LibSecureMerkleTrieCallerSession struct { - Contract *LibSecureMerkleTrieCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// LibSecureMerkleTrieTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type LibSecureMerkleTrieTransactorSession struct { - Contract *LibSecureMerkleTrieTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LibSecureMerkleTrieRaw is an auto generated low-level Go binding around an Ethereum contract. -type LibSecureMerkleTrieRaw struct { - Contract *LibSecureMerkleTrie // Generic contract binding to access the raw methods on -} - -// LibSecureMerkleTrieCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type LibSecureMerkleTrieCallerRaw struct { - Contract *LibSecureMerkleTrieCaller // Generic read-only contract binding to access the raw methods on -} - -// LibSecureMerkleTrieTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type LibSecureMerkleTrieTransactorRaw struct { - Contract *LibSecureMerkleTrieTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewLibSecureMerkleTrie creates a new instance of LibSecureMerkleTrie, bound to a specific deployed contract. -func NewLibSecureMerkleTrie(address common.Address, backend bind.ContractBackend) (*LibSecureMerkleTrie, error) { - contract, err := bindLibSecureMerkleTrie(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LibSecureMerkleTrie{LibSecureMerkleTrieCaller: LibSecureMerkleTrieCaller{contract: contract}, LibSecureMerkleTrieTransactor: LibSecureMerkleTrieTransactor{contract: contract}, LibSecureMerkleTrieFilterer: LibSecureMerkleTrieFilterer{contract: contract}}, nil -} - -// NewLibSecureMerkleTrieCaller creates a new read-only instance of LibSecureMerkleTrie, bound to a specific deployed contract. -func NewLibSecureMerkleTrieCaller(address common.Address, caller bind.ContractCaller) (*LibSecureMerkleTrieCaller, error) { - contract, err := bindLibSecureMerkleTrie(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LibSecureMerkleTrieCaller{contract: contract}, nil -} - -// NewLibSecureMerkleTrieTransactor creates a new write-only instance of LibSecureMerkleTrie, bound to a specific deployed contract. -func NewLibSecureMerkleTrieTransactor(address common.Address, transactor bind.ContractTransactor) (*LibSecureMerkleTrieTransactor, error) { - contract, err := bindLibSecureMerkleTrie(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LibSecureMerkleTrieTransactor{contract: contract}, nil -} - -// NewLibSecureMerkleTrieFilterer creates a new log filterer instance of LibSecureMerkleTrie, bound to a specific deployed contract. -func NewLibSecureMerkleTrieFilterer(address common.Address, filterer bind.ContractFilterer) (*LibSecureMerkleTrieFilterer, error) { - contract, err := bindLibSecureMerkleTrie(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LibSecureMerkleTrieFilterer{contract: contract}, nil -} - -// bindLibSecureMerkleTrie binds a generic wrapper to an already deployed contract. -func bindLibSecureMerkleTrie(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(LibSecureMerkleTrieABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibSecureMerkleTrie *LibSecureMerkleTrieRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibSecureMerkleTrie.Contract.LibSecureMerkleTrieCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibSecureMerkleTrie *LibSecureMerkleTrieRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibSecureMerkleTrie.Contract.LibSecureMerkleTrieTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibSecureMerkleTrie *LibSecureMerkleTrieRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibSecureMerkleTrie.Contract.LibSecureMerkleTrieTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_LibSecureMerkleTrie *LibSecureMerkleTrieCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LibSecureMerkleTrie.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_LibSecureMerkleTrie *LibSecureMerkleTrieTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LibSecureMerkleTrie.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LibSecureMerkleTrie *LibSecureMerkleTrieTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LibSecureMerkleTrie.Contract.contract.Transact(opts, method, params...) -} - -// OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. -var OptimismPortalMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60c060405261dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200005357600080fd5b50604051620030ba380380620030ba83398181016040528101906200007991906200017a565b81818173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050806080818152505050505050620001c1565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000f382620000c6565b9050919050565b60006200010782620000e6565b9050919050565b6200011981620000fa565b81146200012557600080fd5b50565b60008151905062000139816200010e565b92915050565b6000819050919050565b62000154816200013f565b81146200016057600080fd5b50565b600081519050620001748162000149565b92915050565b60008060408385031215620001945762000193620000c1565b5b6000620001a48582860162000128565b9250506020620001b78582860162000163565b9150509250929050565b60805160a051612ec5620001f5600039600081816102b2015261037801526000818161031a01526106720152612ec56000f3fe6080604052600436106100585760003560e01c80621c2ff6146100835780639bf62d82146100ae578063a14238e7146100d9578063e9e05c4214610116578063eecf1c3614610132578063ff61cc931461015b5761007e565b3661007e5761007c3334617530600060405180602001604052806000815250610186565b005b600080fd5b34801561008f57600080fd5b506100986102b0565b6040516100a59190611bd9565b60405180910390f35b3480156100ba57600080fd5b506100c36102d4565b6040516100d09190611c15565b60405180910390f35b3480156100e557600080fd5b5061010060048036038101906100fb9190611c7a565b6102f8565b60405161010d9190611cc2565b60405180910390f35b610130600480360381019061012b9190611ef1565b610186565b005b34801561013e57600080fd5b506101596004803603810190610154919061200c565b610318565b005b34801561016757600080fd5b50610170610670565b60405161017d9190612127565b60405180910390f35b8180156101c05750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156101f7576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461023b5761023833610694565b90505b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102a09594939291906121d9565b60405180910390a3505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915054906101000a900460ff1681565b7f00000000000000000000000000000000000000000000000000000000000000008401421015610374576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a25ae557866040518263ffffffff1660e01b81526004016103cf9190612127565b602060405180830381865afa1580156103ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104109190612248565b905061041b846106b4565b8114610453576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104648d8d8d8d8d8d8d6106fa565b90506000151561047a828760400135878761073c565b151514156104b4576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600115156001600083815260200190815260200160002060009054906101000a900460ff1615151415610513576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b6040516105aa9291906122a5565b600060405180830381858888f193505050503d80600081146105e8576040519150601f19603f3d011682016040523d82523d6000602084013e6105ed565b606091505b5050905061dead6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550817f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f60405160405180910390a25050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600073111100000000000000000000000000000000111182019050919050565b600081600001358260200135836040013584606001356040516020016106dd94939291906122cd565b604051602081830303815290604052805190602001209050919050565b600087878787878787604051602001610719979695949392919061233f565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016107539291906123a9565b60405160208183030381529060405280519060200120905061080f8160405160200161077f91906123f3565b6040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508861081a565b915050949350505050565b6000806108268661083f565b90506108348186868661086f565b915050949350505050565b6060818051906020012060405160200161085991906123f3565b6040516020818303038152906040529050919050565b600080600061087f8786866108a2565b915091508180156108965750610895868261097b565b5b92505050949350505050565b6000606060006108b185610996565b905060008060006108c3848a89610a8b565b925092509250600080835114905080806108da5750815b610919576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109109061246b565b60405180910390fd5b6000816109355760405180602001604052806000815250610965565b6109648660018761094691906124ba565b81518110610957576109566124ee565b5b6020026020010151610efc565b5b9050818197509750505050505050935093915050565b60008180519060200120838051906020012014905092915050565b606060006109a383610f3d565b90506000815167ffffffffffffffff8111156109c2576109c1611dc6565b5b6040519080825280602002602001820160405280156109fb57816020015b6109e8611b26565b8152602001906001900390816109e05790505b50905060005b8251811015610a80576000610a2f848381518110610a2257610a216124ee565b5b6020026020010151610f57565b90506040518060400160405280828152602001610a4b83610f3d565b815250838381518110610a6157610a606124ee565b5b6020026020010181905250508080610a789061251d565b915050610a01565b508092505050919050565b60006060600080600090506000610aa187610fed565b90506000869050600080610ab3611b26565b60005b8c51811015610eac578c8181518110610ad257610ad16124ee565b5b602002602001015191508284610ae89190612566565b9350600187610af79190612566565b96506000841415610b54578482600001518051906020012014610b4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4690612608565b60405180910390fd5b610c03565b602082600001515110610bb3578482600001518051906020012014610bae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba590612674565b60405180910390fd5b610c02565b84610bc18360000151611192565b14610c01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf8906126e0565b60405180910390fd5b5b5b60016010610c119190612566565b8260200151511415610c8c578551841415610c2b57610eac565b6000868581518110610c4057610c3f6124ee565b5b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c6c57610c6b6124ee565b5b60200260200101519050610c7f816111cc565b9650600194505050610e99565b60028260200151511415610e5e576000610ca58361120a565b9050600081600081518110610cbd57610cbc6124ee565b5b602001015160f81c60f81b60f81c90506000600282610cdc919061273c565b6002610ce8919061276d565b90506000610cf9848360ff16611243565b90506000610d078b8a611243565b90506000610d158383611284565b9050600260ff168560ff161480610d325750600360ff168560ff16145b15610d8f57808351148015610d475750808251145b15610d5b57808a610d589190612566565b99505b608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b600060ff168560ff161480610daa5750600160ff168560ff16145b15610e235782518114610deb57608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169a50505050505050610eac565b610e138860200151600181518110610e0657610e056124ee565b5b60200260200101516111cc565b9a50809850505050505050610e99565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5590612813565b60405180910390fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e909061287f565b60405180910390fd5b8080610ea49061251d565b915050610ab6565b506000608060f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168514905086610ee58786611243565b829950995099505050505050505093509350939050565b6060610f3682602001516001846020015151610f1891906124ba565b81518110610f2957610f286124ee565b5b6020026020010151610f57565b9050919050565b6060610f50610f4b83611347565b611375565b9050919050565b60606000806000610f678561156c565b92509250925060006001811115610f8157610f8061289f565b5b816001811115610f9457610f9361289f565b5b14610fd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fcb9061291a565b60405180910390fd5b610fe385602001518484611885565b9350505050919050565b6060600060028351610fff919061293a565b67ffffffffffffffff81111561101857611017611dc6565b5b6040519080825280601f01601f19166020018201604052801561104a5781602001600182028036833780820191505090505b50905060005b835181101561118857600484828151811061106e5761106d6124ee565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c826002836110ab919061293a565b815181106110bc576110bb6124ee565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506010848281518110611100576110ff6124ee565b5b602001015160f81c60f81b60f81c611118919061273c565b60f81b82600160028461112b919061293a565b6111359190612566565b81518110611146576111456124ee565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806111809061251d565b915050611050565b5080915050919050565b60006020825110156111b057600060208301519050809150506111c7565b818060200190518101906111c49190612248565b90505b919050565b600060606020836000015110156111ed576111e68361198b565b90506111f9565b6111f683610f57565b90505b61120281611192565b915050919050565b606061123c611237836020015160008151811061122a576112296124ee565b5b6020026020010151610f57565b610fed565b9050919050565b6060825182106112645760405180602001604052806000815250905061127e565b61127b838384865161127691906124ba565b61199d565b90505b92915050565b600080600090505b80845111801561129c5750808351115b801561132557508281815181106112b6576112b56124ee565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112f6576112f56124ee565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b1561133d5780806113359061251d565b91505061128c565b8091505092915050565b61134f611b40565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606000806113838461156c565b925050915060018081111561139b5761139a61289f565b5b8160018111156113ae576113ad61289f565b5b146113ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e5906129e0565b60405180910390fd5b6000602067ffffffffffffffff81111561140b5761140a611dc6565b5b60405190808252806020026020018201604052801561144457816020015b611431611b40565b8152602001906001900390816114295790505b5090506000808490505b866000015181101561155c576020821061149d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149490612a72565b60405180910390fd5b6000806114db6040518060400160405280858c600001516114be91906124ba565b8152602001858c602001516114d39190612566565b81525061156c565b5091509150604051806040016040528083836114f79190612566565b8152602001848b6020015161150c9190612566565b815250858581518110611522576115216124ee565b5b602002602001018190525060018461153a9190612566565b935080826115489190612566565b836115539190612566565b9250505061144e565b8183528295505050505050919050565b6000806000808460000151116115b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ae90612ade565b60405180910390fd5b6000846020015190506000815160001a9050607f81116115e457600060016000945094509450505061187e565b60b781116116565760006080826115fb91906124ba565b905080876000015111611643576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163a90612b4a565b60405180910390fd5b600181600095509550955050505061187e565b60bf811161173757600060b78261166d91906124ba565b9050808760000151116116b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ac90612bb6565b60405180910390fd5b6000816020036101000a600185015104905080826116d39190612566565b886000015111611718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170f90612c22565b60405180910390fd5b8160016117259190612566565b8160009650965096505050505061187e565b60f781116117a957600060c08261174e91906124ba565b905080876000015111611796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178d90612c8e565b60405180910390fd5b600181600195509550955050505061187e565b600060f7826117b891906124ba565b905080876000015111611800576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f790612cfa565b60405180910390fd5b6000816020036101000a6001850151049050808261181e9190612566565b886000015111611863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185a90612d66565b60405180910390fd5b8160016118709190612566565b816001965096509650505050505b9193909250565b606060008267ffffffffffffffff8111156118a3576118a2611dc6565b5b6040519080825280601f01601f1916602001820160405280156118d55781602001600182028036833780820191505090505b5090506000815114156118eb5780915050611984565b600084866118f99190612566565b9050600060208301905060005b6020866119139190612d86565b81101561194f578251825260208361192b9190612566565b925060208261193a9190612566565b915080806119479061251d565b915050611906565b5060006001602087816119655761196461270d565b5b066020036101000a039050808251168119845116178252839450505050505b9392505050565b606061199682611b09565b9050919050565b606081601f836119ad9190612566565b10156119ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e590612e03565b60405180910390fd5b8282846119fb9190612566565b1015611a3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a3390612e03565b60405180910390fd5b8183611a489190612566565b84511015611a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8290612e6f565b60405180910390fd5b6060821560008114611aac5760405191506000825260208201604052611afd565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611aea5780518352602083019250602081019050611acd565b50868552601f19601f8301166040525050505b50809150509392505050565b6060611b1f826020015160008460000151611885565b9050919050565b604051806040016040528060608152602001606081525090565b604051806040016040528060008152602001600081525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611b9f611b9a611b9584611b5a565b611b7a565b611b5a565b9050919050565b6000611bb182611b84565b9050919050565b6000611bc382611ba6565b9050919050565b611bd381611bb8565b82525050565b6000602082019050611bee6000830184611bca565b92915050565b6000611bff82611b5a565b9050919050565b611c0f81611bf4565b82525050565b6000602082019050611c2a6000830184611c06565b92915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b611c5781611c44565b8114611c6257600080fd5b50565b600081359050611c7481611c4e565b92915050565b600060208284031215611c9057611c8f611c3a565b5b6000611c9e84828501611c65565b91505092915050565b60008115159050919050565b611cbc81611ca7565b82525050565b6000602082019050611cd76000830184611cb3565b92915050565b611ce681611bf4565b8114611cf157600080fd5b50565b600081359050611d0381611cdd565b92915050565b6000819050919050565b611d1c81611d09565b8114611d2757600080fd5b50565b600081359050611d3981611d13565b92915050565b600067ffffffffffffffff82169050919050565b611d5c81611d3f565b8114611d6757600080fd5b50565b600081359050611d7981611d53565b92915050565b611d8881611ca7565b8114611d9357600080fd5b50565b600081359050611da581611d7f565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611dfe82611db5565b810181811067ffffffffffffffff82111715611e1d57611e1c611dc6565b5b80604052505050565b6000611e30611c30565b9050611e3c8282611df5565b919050565b600067ffffffffffffffff821115611e5c57611e5b611dc6565b5b611e6582611db5565b9050602081019050919050565b82818337600083830152505050565b6000611e94611e8f84611e41565b611e26565b905082815260208101848484011115611eb057611eaf611db0565b5b611ebb848285611e72565b509392505050565b600082601f830112611ed857611ed7611dab565b5b8135611ee8848260208601611e81565b91505092915050565b600080600080600060a08688031215611f0d57611f0c611c3a565b5b6000611f1b88828901611cf4565b9550506020611f2c88828901611d2a565b9450506040611f3d88828901611d6a565b9350506060611f4e88828901611d96565b925050608086013567ffffffffffffffff811115611f6f57611f6e611c3f565b5b611f7b88828901611ec3565b9150509295509295909350565b600080fd5b600080fd5b60008083601f840112611fa857611fa7611dab565b5b8235905067ffffffffffffffff811115611fc557611fc4611f88565b5b602083019150836001820283011115611fe157611fe0611f8d565b5b9250929050565b600080fd5b60006080828403121561200357612002611fe8565b5b81905092915050565b60008060008060008060008060008060006101808c8e03121561203257612031611c3a565b5b60006120408e828f01611d2a565b9b505060206120518e828f01611cf4565b9a505060406120628e828f01611cf4565b99505060606120738e828f01611d2a565b98505060806120848e828f01611d2a565b97505060a08c013567ffffffffffffffff8111156120a5576120a4611c3f565b5b6120b18e828f01611f92565b965096505060c06120c48e828f01611d2a565b94505060e06120d58e828f01611fed565b9350506101608c013567ffffffffffffffff8111156120f7576120f6611c3f565b5b6121038e828f01611f92565b92509250509295989b509295989b9093969950565b61212181611d09565b82525050565b600060208201905061213c6000830184612118565b92915050565b61214b81611d3f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561218b578082015181840152602081019050612170565b8381111561219a576000848401525b50505050565b60006121ab82612151565b6121b5818561215c565b93506121c581856020860161216d565b6121ce81611db5565b840191505092915050565b600060a0820190506121ee6000830188612118565b6121fb6020830187612118565b6122086040830186612142565b6122156060830185611cb3565b818103608083015261222781846121a0565b90509695505050505050565b60008151905061224281611c4e565b92915050565b60006020828403121561225e5761225d611c3a565b5b600061226c84828501612233565b91505092915050565b600081905092915050565b600061228c8385612275565b9350612299838584611e72565b82840190509392505050565b60006122b2828486612280565b91508190509392505050565b6122c781611c44565b82525050565b60006080820190506122e260008301876122be565b6122ef60208301866122be565b6122fc60408301856122be565b61230960608301846122be565b95945050505050565b600061231e838561215c565b935061232b838584611e72565b61233483611db5565b840190509392505050565b600060c082019050612354600083018a612118565b6123616020830189611c06565b61236e6040830188611c06565b61237b6060830187612118565b6123886080830186612118565b81810360a083015261239b818486612312565b905098975050505050505050565b60006040820190506123be60008301856122be565b6123cb6020830184612118565b9392505050565b6000819050919050565b6123ed6123e882611c44565b6123d2565b82525050565b60006123ff82846123dc565b60208201915081905092915050565b600082825260208201905092915050565b7f50726f76696465642070726f6f6620697320696e76616c69642e000000000000600082015250565b6000612455601a8361240e565b91506124608261241f565b602082019050919050565b6000602082019050818103600083015261248481612448565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006124c582611d09565b91506124d083611d09565b9250828210156124e3576124e261248b565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061252882611d09565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561255b5761255a61248b565b5b600182019050919050565b600061257182611d09565b915061257c83611d09565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156125b1576125b061248b565b5b828201905092915050565b7f496e76616c696420726f6f742068617368000000000000000000000000000000600082015250565b60006125f260118361240e565b91506125fd826125bc565b602082019050919050565b60006020820190508181036000830152612621816125e5565b9050919050565b7f496e76616c6964206c6172676520696e7465726e616c20686173680000000000600082015250565b600061265e601b8361240e565b915061266982612628565b602082019050919050565b6000602082019050818103600083015261268d81612651565b9050919050565b7f496e76616c696420696e7465726e616c206e6f64652068617368000000000000600082015250565b60006126ca601a8361240e565b91506126d582612694565b602082019050919050565b600060208201905081810360008301526126f9816126bd565b9050919050565b600060ff82169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061274782612700565b915061275283612700565b9250826127625761276161270d565b5b828206905092915050565b600061277882612700565b915061278383612700565b9250828210156127965761279561248b565b5b828203905092915050565b7f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060008201527f7072656669780000000000000000000000000000000000000000000000000000602082015250565b60006127fd60268361240e565b9150612808826127a1565b604082019050919050565b6000602082019050818103600083015261282c816127f0565b9050919050565b7f526563656976656420616e20756e706172736561626c65206e6f64652e000000600082015250565b6000612869601d8361240e565b915061287482612833565b602082019050919050565b600060208201905081810360008301526128988161285c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f496e76616c696420524c502062797465732076616c75652e0000000000000000600082015250565b600061290460188361240e565b915061290f826128ce565b602082019050919050565b60006020820190508181036000830152612933816128f7565b9050919050565b600061294582611d09565b915061295083611d09565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156129895761298861248b565b5b828202905092915050565b7f496e76616c696420524c50206c6973742076616c75652e000000000000000000600082015250565b60006129ca60178361240e565b91506129d582612994565b602082019050919050565b600060208201905081810360008301526129f9816129bd565b9050919050565b7f50726f766964656420524c50206c6973742065786365656473206d6178206c6960008201527f7374206c656e6774682e00000000000000000000000000000000000000000000602082015250565b6000612a5c602a8361240e565b9150612a6782612a00565b604082019050919050565b60006020820190508181036000830152612a8b81612a4f565b9050919050565b7f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000600082015250565b6000612ac860188361240e565b9150612ad382612a92565b602082019050919050565b60006020820190508181036000830152612af781612abb565b9050919050565b7f496e76616c696420524c502073686f727420737472696e672e00000000000000600082015250565b6000612b3460198361240e565b9150612b3f82612afe565b602082019050919050565b60006020820190508181036000830152612b6381612b27565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00600082015250565b6000612ba0601f8361240e565b9150612bab82612b6a565b602082019050919050565b60006020820190508181036000830152612bcf81612b93565b9050919050565b7f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000600082015250565b6000612c0c60188361240e565b9150612c1782612bd6565b602082019050919050565b60006020820190508181036000830152612c3b81612bff565b9050919050565b7f496e76616c696420524c502073686f7274206c6973742e000000000000000000600082015250565b6000612c7860178361240e565b9150612c8382612c42565b602082019050919050565b60006020820190508181036000830152612ca781612c6b565b9050919050565b7f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000600082015250565b6000612ce4601d8361240e565b9150612cef82612cae565b602082019050919050565b60006020820190508181036000830152612d1381612cd7565b9050919050565b7f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000600082015250565b6000612d5060168361240e565b9150612d5b82612d1a565b602082019050919050565b60006020820190508181036000830152612d7f81612d43565b9050919050565b6000612d9182611d09565b9150612d9c83611d09565b925082612dac57612dab61270d565b5b828204905092915050565b7f736c6963655f6f766572666c6f77000000000000000000000000000000000000600082015250565b6000612ded600e8361240e565b9150612df882612db7565b602082019050919050565b60006020820190508181036000830152612e1c81612de0565b9050919050565b7f736c6963655f6f75744f66426f756e6473000000000000000000000000000000600082015250565b6000612e5960118361240e565b9150612e6482612e23565b602082019050919050565b60006020820190508181036000830152612e8881612e4c565b905091905056fea264697066735822122074dee632ac29194e1f1bccf1f4b1d8201f31bbc289f63a71425c41734905a8de64736f6c634300080a0033", -} - -// OptimismPortalABI is the input ABI used to generate the binding from. -// Deprecated: Use OptimismPortalMetaData.ABI instead. -var OptimismPortalABI = OptimismPortalMetaData.ABI - -// OptimismPortalBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use OptimismPortalMetaData.Bin instead. -var OptimismPortalBin = OptimismPortalMetaData.Bin - -// DeployOptimismPortal deploys a new Ethereum contract, binding an instance of OptimismPortal to it. -func DeployOptimismPortal(auth *bind.TransactOpts, backend bind.ContractBackend, _l2Oracle common.Address, _finalizationPeriod *big.Int) (common.Address, *types.Transaction, *OptimismPortal, error) { - parsed, err := OptimismPortalMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OptimismPortalBin), backend, _l2Oracle, _finalizationPeriod) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &OptimismPortal{OptimismPortalCaller: OptimismPortalCaller{contract: contract}, OptimismPortalTransactor: OptimismPortalTransactor{contract: contract}, OptimismPortalFilterer: OptimismPortalFilterer{contract: contract}}, nil -} - -// OptimismPortal is an auto generated Go binding around an Ethereum contract. -type OptimismPortal struct { - OptimismPortalCaller // Read-only binding to the contract - OptimismPortalTransactor // Write-only binding to the contract - OptimismPortalFilterer // Log filterer for contract events -} - -// OptimismPortalCaller is an auto generated read-only Go binding around an Ethereum contract. -type OptimismPortalCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OptimismPortalTransactor is an auto generated write-only Go binding around an Ethereum contract. -type OptimismPortalTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OptimismPortalFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type OptimismPortalFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OptimismPortalSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type OptimismPortalSession struct { - Contract *OptimismPortal // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OptimismPortalCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type OptimismPortalCallerSession struct { - Contract *OptimismPortalCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// OptimismPortalTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type OptimismPortalTransactorSession struct { - Contract *OptimismPortalTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OptimismPortalRaw is an auto generated low-level Go binding around an Ethereum contract. -type OptimismPortalRaw struct { - Contract *OptimismPortal // Generic contract binding to access the raw methods on -} - -// OptimismPortalCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type OptimismPortalCallerRaw struct { - Contract *OptimismPortalCaller // Generic read-only contract binding to access the raw methods on -} - -// OptimismPortalTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type OptimismPortalTransactorRaw struct { - Contract *OptimismPortalTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewOptimismPortal creates a new instance of OptimismPortal, bound to a specific deployed contract. -func NewOptimismPortal(address common.Address, backend bind.ContractBackend) (*OptimismPortal, error) { - contract, err := bindOptimismPortal(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &OptimismPortal{OptimismPortalCaller: OptimismPortalCaller{contract: contract}, OptimismPortalTransactor: OptimismPortalTransactor{contract: contract}, OptimismPortalFilterer: OptimismPortalFilterer{contract: contract}}, nil -} - -// NewOptimismPortalCaller creates a new read-only instance of OptimismPortal, bound to a specific deployed contract. -func NewOptimismPortalCaller(address common.Address, caller bind.ContractCaller) (*OptimismPortalCaller, error) { - contract, err := bindOptimismPortal(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &OptimismPortalCaller{contract: contract}, nil -} - -// NewOptimismPortalTransactor creates a new write-only instance of OptimismPortal, bound to a specific deployed contract. -func NewOptimismPortalTransactor(address common.Address, transactor bind.ContractTransactor) (*OptimismPortalTransactor, error) { - contract, err := bindOptimismPortal(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &OptimismPortalTransactor{contract: contract}, nil -} - -// NewOptimismPortalFilterer creates a new log filterer instance of OptimismPortal, bound to a specific deployed contract. -func NewOptimismPortalFilterer(address common.Address, filterer bind.ContractFilterer) (*OptimismPortalFilterer, error) { - contract, err := bindOptimismPortal(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &OptimismPortalFilterer{contract: contract}, nil -} - -// bindOptimismPortal binds a generic wrapper to an already deployed contract. -func bindOptimismPortal(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(OptimismPortalABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_OptimismPortal *OptimismPortalRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OptimismPortal.Contract.OptimismPortalCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_OptimismPortal *OptimismPortalRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OptimismPortal.Contract.OptimismPortalTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_OptimismPortal *OptimismPortalRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OptimismPortal.Contract.OptimismPortalTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_OptimismPortal *OptimismPortalCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OptimismPortal.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_OptimismPortal *OptimismPortalTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OptimismPortal.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_OptimismPortal *OptimismPortalTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OptimismPortal.Contract.contract.Transact(opts, method, params...) -} - -// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. -// -// Solidity: function FINALIZATION_PERIOD() view returns(uint256) -func (_OptimismPortal *OptimismPortalCaller) FINALIZATIONPERIOD(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _OptimismPortal.contract.Call(opts, &out, "FINALIZATION_PERIOD") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. -// -// Solidity: function FINALIZATION_PERIOD() view returns(uint256) -func (_OptimismPortal *OptimismPortalSession) FINALIZATIONPERIOD() (*big.Int, error) { - return _OptimismPortal.Contract.FINALIZATIONPERIOD(&_OptimismPortal.CallOpts) -} - -// FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. -// -// Solidity: function FINALIZATION_PERIOD() view returns(uint256) -func (_OptimismPortal *OptimismPortalCallerSession) FINALIZATIONPERIOD() (*big.Int, error) { - return _OptimismPortal.Contract.FINALIZATIONPERIOD(&_OptimismPortal.CallOpts) -} - -// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. -// -// Solidity: function L2_ORACLE() view returns(address) -func (_OptimismPortal *OptimismPortalCaller) L2ORACLE(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _OptimismPortal.contract.Call(opts, &out, "L2_ORACLE") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. -// -// Solidity: function L2_ORACLE() view returns(address) -func (_OptimismPortal *OptimismPortalSession) L2ORACLE() (common.Address, error) { - return _OptimismPortal.Contract.L2ORACLE(&_OptimismPortal.CallOpts) -} - -// L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. -// -// Solidity: function L2_ORACLE() view returns(address) -func (_OptimismPortal *OptimismPortalCallerSession) L2ORACLE() (common.Address, error) { - return _OptimismPortal.Contract.L2ORACLE(&_OptimismPortal.CallOpts) -} - -// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. -// -// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) -func (_OptimismPortal *OptimismPortalCaller) FinalizedWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { - var out []interface{} - err := _OptimismPortal.contract.Call(opts, &out, "finalizedWithdrawals", arg0) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. -// -// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) -func (_OptimismPortal *OptimismPortalSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { - return _OptimismPortal.Contract.FinalizedWithdrawals(&_OptimismPortal.CallOpts, arg0) -} - -// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. -// -// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) -func (_OptimismPortal *OptimismPortalCallerSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { - return _OptimismPortal.Contract.FinalizedWithdrawals(&_OptimismPortal.CallOpts, arg0) -} - -// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. -// -// Solidity: function l2Sender() view returns(address) -func (_OptimismPortal *OptimismPortalCaller) L2Sender(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _OptimismPortal.contract.Call(opts, &out, "l2Sender") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. -// -// Solidity: function l2Sender() view returns(address) -func (_OptimismPortal *OptimismPortalSession) L2Sender() (common.Address, error) { - return _OptimismPortal.Contract.L2Sender(&_OptimismPortal.CallOpts) -} - -// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. -// -// Solidity: function l2Sender() view returns(address) -func (_OptimismPortal *OptimismPortalCallerSession) L2Sender() (common.Address, error) { - return _OptimismPortal.Contract.L2Sender(&_OptimismPortal.CallOpts) -} - -// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. -// -// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_OptimismPortal *OptimismPortalTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _OptimismPortal.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) -} - -// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. -// -// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_OptimismPortal *OptimismPortalSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) -} - -// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. -// -// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() -func (_OptimismPortal *OptimismPortalTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) -} - -// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. -// -// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) -} - -// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. -// -// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) -} - -// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. -// -// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) -} - -// Receive is a paid mutator transaction binding the contract receive function. -// -// Solidity: receive() payable returns() -func (_OptimismPortal *OptimismPortalTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OptimismPortal.contract.RawTransact(opts, nil) // calldata is disallowed for receive function -} - -// Receive is a paid mutator transaction binding the contract receive function. -// -// Solidity: receive() payable returns() -func (_OptimismPortal *OptimismPortalSession) Receive() (*types.Transaction, error) { - return _OptimismPortal.Contract.Receive(&_OptimismPortal.TransactOpts) -} - -// Receive is a paid mutator transaction binding the contract receive function. -// -// Solidity: receive() payable returns() -func (_OptimismPortal *OptimismPortalTransactorSession) Receive() (*types.Transaction, error) { - return _OptimismPortal.Contract.Receive(&_OptimismPortal.TransactOpts) -} - -// OptimismPortalTransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the OptimismPortal contract. -type OptimismPortalTransactionDepositedIterator struct { - Event *OptimismPortalTransactionDeposited // 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 *OptimismPortalTransactionDepositedIterator) 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(OptimismPortalTransactionDeposited) - 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(OptimismPortalTransactionDeposited) - 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 *OptimismPortalTransactionDepositedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OptimismPortalTransactionDepositedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OptimismPortalTransactionDeposited represents a TransactionDeposited event raised by the OptimismPortal contract. -type OptimismPortalTransactionDeposited struct { - From common.Address - To common.Address - Mint *big.Int - Value *big.Int - GasLimit uint64 - IsCreation bool - Data []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. -// -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) -func (_OptimismPortal *OptimismPortalFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismPortalTransactionDepositedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _OptimismPortal.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule) - if err != nil { - return nil, err - } - return &OptimismPortalTransactionDepositedIterator{contract: _OptimismPortal.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil -} - -// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. -// -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) -func (_OptimismPortal *OptimismPortalFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *OptimismPortalTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _OptimismPortal.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule) - 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(OptimismPortalTransactionDeposited) - if err := _OptimismPortal.contract.UnpackLog(event, "TransactionDeposited", 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 -} - -// ParseTransactionDeposited is a log parse operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. -// -// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) -func (_OptimismPortal *OptimismPortalFilterer) ParseTransactionDeposited(log types.Log) (*OptimismPortalTransactionDeposited, error) { - event := new(OptimismPortalTransactionDeposited) - if err := _OptimismPortal.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// OptimismPortalWithdrawalFinalizedIterator is returned from FilterWithdrawalFinalized and is used to iterate over the raw logs and unpacked data for WithdrawalFinalized events raised by the OptimismPortal contract. -type OptimismPortalWithdrawalFinalizedIterator struct { - Event *OptimismPortalWithdrawalFinalized // 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 *OptimismPortalWithdrawalFinalizedIterator) 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(OptimismPortalWithdrawalFinalized) - 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(OptimismPortalWithdrawalFinalized) - 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 *OptimismPortalWithdrawalFinalizedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OptimismPortalWithdrawalFinalizedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OptimismPortalWithdrawalFinalized represents a WithdrawalFinalized event raised by the OptimismPortal contract. -type OptimismPortalWithdrawalFinalized struct { - Arg0 [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterWithdrawalFinalized is a free log retrieval operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. -// -// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) -func (_OptimismPortal *OptimismPortalFilterer) FilterWithdrawalFinalized(opts *bind.FilterOpts, arg0 [][32]byte) (*OptimismPortalWithdrawalFinalizedIterator, error) { - - var arg0Rule []interface{} - for _, arg0Item := range arg0 { - arg0Rule = append(arg0Rule, arg0Item) - } - - logs, sub, err := _OptimismPortal.contract.FilterLogs(opts, "WithdrawalFinalized", arg0Rule) - if err != nil { - return nil, err - } - return &OptimismPortalWithdrawalFinalizedIterator{contract: _OptimismPortal.contract, event: "WithdrawalFinalized", logs: logs, sub: sub}, nil -} - -// WatchWithdrawalFinalized is a free log subscription operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. -// -// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) -func (_OptimismPortal *OptimismPortalFilterer) WatchWithdrawalFinalized(opts *bind.WatchOpts, sink chan<- *OptimismPortalWithdrawalFinalized, arg0 [][32]byte) (event.Subscription, error) { - - var arg0Rule []interface{} - for _, arg0Item := range arg0 { - arg0Rule = append(arg0Rule, arg0Item) - } - - logs, sub, err := _OptimismPortal.contract.WatchLogs(opts, "WithdrawalFinalized", arg0Rule) - 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(OptimismPortalWithdrawalFinalized) - if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalFinalized", 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 -} - -// ParseWithdrawalFinalized is a log parse operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. -// -// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) -func (_OptimismPortal *OptimismPortalFilterer) ParseWithdrawalFinalized(log types.Log) (*OptimismPortalWithdrawalFinalized, error) { - event := new(OptimismPortalWithdrawalFinalized) - if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// OwnableMetaData contains all meta data concerning the Ownable contract. -var OwnableMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", -} - -// OwnableABI is the input ABI used to generate the binding from. -// Deprecated: Use OwnableMetaData.ABI instead. -var OwnableABI = OwnableMetaData.ABI - -// Ownable is an auto generated Go binding around an Ethereum contract. -type Ownable struct { - OwnableCaller // Read-only binding to the contract - OwnableTransactor // Write-only binding to the contract - OwnableFilterer // Log filterer for contract events -} - -// OwnableCaller is an auto generated read-only Go binding around an Ethereum contract. -type OwnableCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OwnableTransactor is an auto generated write-only Go binding around an Ethereum contract. -type OwnableTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OwnableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type OwnableFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OwnableSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type OwnableSession struct { - Contract *Ownable // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OwnableCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type OwnableCallerSession struct { - Contract *OwnableCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// OwnableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type OwnableTransactorSession struct { - Contract *OwnableTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OwnableRaw is an auto generated low-level Go binding around an Ethereum contract. -type OwnableRaw struct { - Contract *Ownable // Generic contract binding to access the raw methods on -} - -// OwnableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type OwnableCallerRaw struct { - Contract *OwnableCaller // Generic read-only contract binding to access the raw methods on -} - -// OwnableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type OwnableTransactorRaw struct { - Contract *OwnableTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewOwnable creates a new instance of Ownable, bound to a specific deployed contract. -func NewOwnable(address common.Address, backend bind.ContractBackend) (*Ownable, error) { - contract, err := bindOwnable(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Ownable{OwnableCaller: OwnableCaller{contract: contract}, OwnableTransactor: OwnableTransactor{contract: contract}, OwnableFilterer: OwnableFilterer{contract: contract}}, nil -} - -// NewOwnableCaller creates a new read-only instance of Ownable, bound to a specific deployed contract. -func NewOwnableCaller(address common.Address, caller bind.ContractCaller) (*OwnableCaller, error) { - contract, err := bindOwnable(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &OwnableCaller{contract: contract}, nil -} - -// NewOwnableTransactor creates a new write-only instance of Ownable, bound to a specific deployed contract. -func NewOwnableTransactor(address common.Address, transactor bind.ContractTransactor) (*OwnableTransactor, error) { - contract, err := bindOwnable(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &OwnableTransactor{contract: contract}, nil -} - -// NewOwnableFilterer creates a new log filterer instance of Ownable, bound to a specific deployed contract. -func NewOwnableFilterer(address common.Address, filterer bind.ContractFilterer) (*OwnableFilterer, error) { - contract, err := bindOwnable(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &OwnableFilterer{contract: contract}, nil -} - -// bindOwnable binds a generic wrapper to an already deployed contract. -func bindOwnable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(OwnableABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Ownable *OwnableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Ownable.Contract.OwnableCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Ownable *OwnableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Ownable.Contract.OwnableTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Ownable *OwnableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Ownable.Contract.OwnableTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Ownable *OwnableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Ownable.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Ownable *OwnableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Ownable.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Ownable *OwnableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Ownable.Contract.contract.Transact(opts, method, params...) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Ownable *OwnableCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Ownable.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Ownable *OwnableSession) Owner() (common.Address, error) { - return _Ownable.Contract.Owner(&_Ownable.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Ownable *OwnableCallerSession) Owner() (common.Address, error) { - return _Ownable.Contract.Owner(&_Ownable.CallOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Ownable *OwnableTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Ownable.contract.Transact(opts, "renounceOwnership") -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Ownable *OwnableSession) RenounceOwnership() (*types.Transaction, error) { - return _Ownable.Contract.RenounceOwnership(&_Ownable.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Ownable *OwnableTransactorSession) RenounceOwnership() (*types.Transaction, error) { - return _Ownable.Contract.RenounceOwnership(&_Ownable.TransactOpts) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Ownable *OwnableTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { - return _Ownable.contract.Transact(opts, "transferOwnership", newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Ownable *OwnableSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Ownable *OwnableTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) -} - -// OwnableOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Ownable contract. -type OwnableOwnershipTransferredIterator struct { - Event *OwnableOwnershipTransferred // 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 *OwnableOwnershipTransferredIterator) 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(OwnableOwnershipTransferred) - 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(OwnableOwnershipTransferred) - 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 *OwnableOwnershipTransferredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OwnableOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OwnableOwnershipTransferred represents a OwnershipTransferred event raised by the Ownable contract. -type OwnableOwnershipTransferred struct { - PreviousOwner common.Address - NewOwner common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Ownable *OwnableFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*OwnableOwnershipTransferredIterator, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _Ownable.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return &OwnableOwnershipTransferredIterator{contract: _Ownable.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Ownable *OwnableFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OwnableOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _Ownable.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - 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(OwnableOwnershipTransferred) - if err := _Ownable.contract.UnpackLog(event, "OwnershipTransferred", 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 -} - -// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Ownable *OwnableFilterer) ParseOwnershipTransferred(log types.Log) (*OwnableOwnershipTransferred, error) { - event := new(OwnableOwnershipTransferred) - if err := _Ownable.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// WithdrawalVerifierMetaData contains all meta data concerning the WithdrawalVerifier contract. -var WithdrawalVerifierMetaData = &bind.MetaData{ - ABI: "[]", - Bin: "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202eecfa4ab6f0ebc682ef9a192b83bda8737bbea39514d69c0924b2d73c4b1a7564736f6c634300080a0033", +// OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. +var OptimismPortalMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60c0604052600080546001600160a01b03191661dead17905534801561002457600080fd5b5060405162002322380380620023228339810160408190526100459161005b565b6001600160a01b0390911660a052608052610095565b6000806040838503121561006e57600080fd5b82516001600160a01b038116811461008557600080fd5b6020939093015192949293505050565b60805160a05161225a620000c86000396000818160a501526103500152600081816101a301526102c4015261225a6000f3fe6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015e578063eecf1c3614610171578063ff61cc931461019157600080fd5b80621c2ff6146100935780639bf62d82146100f1578063a14238e71461011e57600080fd5b3661008e5761008c33346175306000604051806020016040528060008152506101d3565b005b600080fd5b34801561009f57600080fd5b506100c77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fd57600080fd5b506000546100c79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012a57600080fd5b5061014e610139366004611c41565b60016020526000908152604090205460ff1681565b60405190151581526020016100e8565b61008c61016c366004611cb2565b6101d3565b34801561017d57600080fd5b5061008c61018c366004611e18565b6102c2565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e8565b8180156101f5575073ffffffffffffffffffffffffffffffffffffffff851615155b1561022c576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3332811461024d575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102b2959493929190611f18565b60405180910390a3505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000840142101561031e576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401602060405180830381865afa1580156103ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d09190611fb4565b9050610424846040805182356020828101919091528301358183015290820135606082810191909152820135608082015260009060a001604051602081830303815290604052805190602001209050919050565b811461045c576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046d8d8d8d8d8d8d8d610648565b905061047f818660400135868661068a565b6104b5576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff1615151415610504576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161059b929190611fcd565b600060405180830381858888f193505050503d80600081146105d9576040519150601f19603f3d011682016040523d82523d6000602084013e6105de565b606091505b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17815560405191925083917f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f9190a25050505050505050505050505050565b6000878787878787876040516020016106679796959493929190611fdd565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016106aa929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052925061077091016040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061077a915050565b9695505050505050565b60008061078686610794565b9050610770818686866107c6565b606081805190602001206040516020016107b091815260200190565b6040516020818303038152906040529050919050565b60008060006107d68786866107f7565b915091508180156107ec57506107ec86826108f1565b979650505050505050565b6000606060006108068561090d565b90506000806000610818848a89610a08565b8151929550909350915015808061082c5750815b610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064015b60405180910390fd5b6000816108b357604051806020016040528060008152506108df565b6108df866108c2600188612099565b815181106108d2576108d26120b0565b6020026020010151610f25565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b6060600061091a83610f4f565b90506000815167ffffffffffffffff81111561093857610938611c83565b60405190808252806020026020018201604052801561097d57816020015b60408051808201909152606080825260208201528152602001906001900390816109565790505b50905060005b8251811015610a005760006109b08483815181106109a3576109a36120b0565b6020026020010151610f82565b905060405180604001604052808281526020016109cc83610f4f565b8152508383815181106109e1576109e16120b0565b60200260200101819052505080806109f8906120df565b915050610983565b509392505050565b60006060818080610a188761102c565b90506000869050600080610a3f604051806040016040528060608152602001606081525090565b60005b8c51811015610ee1578c8181518110610a5d57610a5d6120b0565b602002602001015191508284610a739190612118565b9350610a80600188612118565b965083610afe57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f742068617368000000000000000000000000000000604482015260640161088e565b610bef565b815151602011610b7a57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161088e565b84610b8883600001516111af565b14610bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161088e565b610bfb60106001612118565b8260200151511415610c74578551841415610c1557610ee1565b6000868581518110610c2957610c296120b0565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c5457610c546120b0565b60200260200101519050610c67816111d7565b9650600194505050610ecf565b60028260200151511415610e6d576000610c8d83611214565b9050600081600081518110610ca457610ca46120b0565b016020015160f81c90506000610cbb60028361215f565b610cc6906002612181565b90506000610cd7848360ff16611238565b90506000610ce58b8a611238565b90506000610cf3838361126e565b905060ff851660021480610d0a575060ff85166003145b15610d6057808351148015610d1f5750808251145b15610d3157610d2e818b612118565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b60ff85161580610d73575060ff85166001145b15610de55782518114610daf57507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b610dd68860200151600181518110610dc957610dc96120b0565b60200260200101516111d7565b9a509750610ecf945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f7072656669780000000000000000000000000000000000000000000000000000606482015260840161088e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161088e565b80610ed9816120df565b915050610a42565b507f8000000000000000000000000000000000000000000000000000000000000000841486610f108786611238565b909e909d50909b509950505050505050505050565b6020810151805160609161090791610f3f90600190612099565b815181106109a3576109a36120b0565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906109079061131a565b60606000806000610f928561154d565b919450925090506000816001811115610fad57610fad6121a4565b14611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161088e565b61102385602001518484611954565b95945050505050565b606060008251600261103e91906121d3565b67ffffffffffffffff81111561105657611056611c83565b6040519080825280601f01601f191660200182016040528015611080576020820181803683370190505b50905060005b83518110156111a85760048482815181106110a3576110a36120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826110d88360026121d3565b815181106110e8576110e86120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061112b5761112b6120b0565b016020015161113d919060f81c61215f565b60f81b8261114c8360026121d3565b611157906001612118565b81518110611167576111676120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111a0816120df565b915050611086565b5092915050565b60006020825110156111c357506020015190565b818060200190518101906109079190611fb4565b600060606020836000015110156111f8576111f183611a33565b9050611204565b61120183610f82565b90505b61120d816111af565b9392505050565b606061090761123383602001516000815181106109a3576109a36120b0565b61102c565b6060825182106112575750604080516020810190915260008152610907565b61120d83838486516112699190612099565b611a3e565b6000805b8084511180156112825750808351115b8015611303575082818151811061129b5761129b6120b0565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112da576112da6120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561120d5780611312816120df565b915050611272565b60606000806113288461154d565b91935090915060019050816001811115611344576113446121a4565b146113ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161088e565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816113c45790505090506000835b8651811015611542576020821061148a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161088e565b6000806114c76040518060400160405280858c600001516114ab9190612099565b8152602001858c602001516114c09190612118565b905261154d565b5091509150604051806040016040528083836114e39190612118565b8152602001848b602001516114f89190612118565b81525085858151811061150d5761150d6120b0565b6020908102919091010152611523600185612118565b935061152f8183612118565b6115399084612118565b925050506113f1565b508152949350505050565b6000806000808460000151116115bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161088e565b6020840151805160001a607f81116115e457600060016000945094509450505061194d565b60b7811161167a5760006115f9608083612099565b905080876000015111611668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161088e565b6001955093506000925061194d915050565b60bf811161179d57600061168f60b783612099565b9050808760000151116116fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161088e565b600183015160208290036101000a90046117188183612118565b885111611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161088e565b61178c826001612118565b965094506000935061194d92505050565b60f781116118325760006117b260c083612099565b905080876000015111611821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161088e565b60019550935084925061194d915050565b600061183f60f783612099565b9050808760000151116118ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161088e565b600183015160208290036101000a90046118c88183612118565b885111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161088e565b61193c826001612118565b965094506001935061194d92505050565b9193909250565b606060008267ffffffffffffffff81111561197157611971611c83565b6040519080825280601f01601f19166020018201604052801561199b576020820181803683370190505b5090508051600014156119af57905061120d565b60006119bb8587612118565b90506020820160005b6119cf602087612210565b811015611a0657825182526119e5602084612118565b92506119f2602083612118565b9150806119fe816120df565b9150506119c4565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061090782611c2b565b606081611a4c81601f612118565b1015611ab4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b82611abf8382612118565b1015611b27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b611b318284612118565b84511015611b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161088e565b606082158015611bba5760405191506000825260208201604052611c22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bf3578051835260209283019201611bdb565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610907826020015160008460000151611954565b600060208284031215611c5357600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c7e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a08688031215611cca57600080fd5b611cd386611c5a565b945060208601359350604086013567ffffffffffffffff8082168214611cf857600080fd5b9093506060870135908115158214611d0f57600080fd5b90925060808701359080821115611d2557600080fd5b818801915088601f830112611d3957600080fd5b813581811115611d4b57611d4b611c83565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611d9157611d91611c83565b816040528281528b6020848701011115611daa57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b60008083601f840112611de157600080fd5b50813567ffffffffffffffff811115611df957600080fd5b602083019150836020828501011115611e1157600080fd5b9250929050565b60008060008060008060008060008060006101808c8e031215611e3a57600080fd5b8b359a50611e4a60208d01611c5a565b9950611e5860408d01611c5a565b985060608c0135975060808c0135965067ffffffffffffffff60a08d01351115611e8157600080fd5b611e918d60a08e01358e01611dcf565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215611ecf57600080fd5b60e08c01925067ffffffffffffffff6101608d01351115611eef57600080fd5b611f008d6101608e01358e01611dcf565b81935080925050509295989b509295989b9093969950565b85815260006020868184015267ffffffffffffffff86166040840152841515606084015260a0608084015283518060a085015260005b81811015611f6a5785810183015185820160c001528201611f4e565b81811115611f7c57600060c083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160c001979650505050505050565b600060208284031215611fc657600080fd5b5051919050565b8183823760009101908152919050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015284608083015260c060a08301528260c0830152828460e0840137600060e0848401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121115761211161206a565b5060010190565b6000821982111561212b5761212b61206a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061217257612172612130565b8060ff84160691505092915050565b600060ff821660ff84168082101561219b5761219b61206a565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561220b5761220b61206a565b500290565b60008261221f5761221f612130565b50049056fea26469706673582212208ef4bb38bdf36297a0a7fcd07a53d184d13074b51bfd01186b4075762eec487364736f6c634300080a0033", } -// WithdrawalVerifierABI is the input ABI used to generate the binding from. -// Deprecated: Use WithdrawalVerifierMetaData.ABI instead. -var WithdrawalVerifierABI = WithdrawalVerifierMetaData.ABI +// OptimismPortalABI is the input ABI used to generate the binding from. +// Deprecated: Use OptimismPortalMetaData.ABI instead. +var OptimismPortalABI = OptimismPortalMetaData.ABI -// WithdrawalVerifierBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use WithdrawalVerifierMetaData.Bin instead. -var WithdrawalVerifierBin = WithdrawalVerifierMetaData.Bin +// OptimismPortalBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use OptimismPortalMetaData.Bin instead. +var OptimismPortalBin = OptimismPortalMetaData.Bin -// DeployWithdrawalVerifier deploys a new Ethereum contract, binding an instance of WithdrawalVerifier to it. -func DeployWithdrawalVerifier(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *WithdrawalVerifier, error) { - parsed, err := WithdrawalVerifierMetaData.GetAbi() +// DeployOptimismPortal deploys a new Ethereum contract, binding an instance of OptimismPortal to it. +func DeployOptimismPortal(auth *bind.TransactOpts, backend bind.ContractBackend, _l2Oracle common.Address, _finalizationPeriod *big.Int) (common.Address, *types.Transaction, *OptimismPortal, error) { + parsed, err := OptimismPortalMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -3613,262 +60,111 @@ func DeployWithdrawalVerifier(auth *bind.TransactOpts, backend bind.ContractBack return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(WithdrawalVerifierBin), backend) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OptimismPortalBin), backend, _l2Oracle, _finalizationPeriod) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &WithdrawalVerifier{WithdrawalVerifierCaller: WithdrawalVerifierCaller{contract: contract}, WithdrawalVerifierTransactor: WithdrawalVerifierTransactor{contract: contract}, WithdrawalVerifierFilterer: WithdrawalVerifierFilterer{contract: contract}}, nil -} - -// WithdrawalVerifier is an auto generated Go binding around an Ethereum contract. -type WithdrawalVerifier struct { - WithdrawalVerifierCaller // Read-only binding to the contract - WithdrawalVerifierTransactor // Write-only binding to the contract - WithdrawalVerifierFilterer // Log filterer for contract events -} - -// WithdrawalVerifierCaller is an auto generated read-only Go binding around an Ethereum contract. -type WithdrawalVerifierCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// WithdrawalVerifierTransactor is an auto generated write-only Go binding around an Ethereum contract. -type WithdrawalVerifierTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// WithdrawalVerifierFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type WithdrawalVerifierFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// WithdrawalVerifierSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type WithdrawalVerifierSession struct { - Contract *WithdrawalVerifier // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// WithdrawalVerifierCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type WithdrawalVerifierCallerSession struct { - Contract *WithdrawalVerifierCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// WithdrawalVerifierTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type WithdrawalVerifierTransactorSession struct { - Contract *WithdrawalVerifierTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// WithdrawalVerifierRaw is an auto generated low-level Go binding around an Ethereum contract. -type WithdrawalVerifierRaw struct { - Contract *WithdrawalVerifier // Generic contract binding to access the raw methods on -} - -// WithdrawalVerifierCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type WithdrawalVerifierCallerRaw struct { - Contract *WithdrawalVerifierCaller // Generic read-only contract binding to access the raw methods on -} - -// WithdrawalVerifierTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type WithdrawalVerifierTransactorRaw struct { - Contract *WithdrawalVerifierTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewWithdrawalVerifier creates a new instance of WithdrawalVerifier, bound to a specific deployed contract. -func NewWithdrawalVerifier(address common.Address, backend bind.ContractBackend) (*WithdrawalVerifier, error) { - contract, err := bindWithdrawalVerifier(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &WithdrawalVerifier{WithdrawalVerifierCaller: WithdrawalVerifierCaller{contract: contract}, WithdrawalVerifierTransactor: WithdrawalVerifierTransactor{contract: contract}, WithdrawalVerifierFilterer: WithdrawalVerifierFilterer{contract: contract}}, nil -} - -// NewWithdrawalVerifierCaller creates a new read-only instance of WithdrawalVerifier, bound to a specific deployed contract. -func NewWithdrawalVerifierCaller(address common.Address, caller bind.ContractCaller) (*WithdrawalVerifierCaller, error) { - contract, err := bindWithdrawalVerifier(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &WithdrawalVerifierCaller{contract: contract}, nil -} - -// NewWithdrawalVerifierTransactor creates a new write-only instance of WithdrawalVerifier, bound to a specific deployed contract. -func NewWithdrawalVerifierTransactor(address common.Address, transactor bind.ContractTransactor) (*WithdrawalVerifierTransactor, error) { - contract, err := bindWithdrawalVerifier(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &WithdrawalVerifierTransactor{contract: contract}, nil -} - -// NewWithdrawalVerifierFilterer creates a new log filterer instance of WithdrawalVerifier, bound to a specific deployed contract. -func NewWithdrawalVerifierFilterer(address common.Address, filterer bind.ContractFilterer) (*WithdrawalVerifierFilterer, error) { - contract, err := bindWithdrawalVerifier(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &WithdrawalVerifierFilterer{contract: contract}, nil -} - -// bindWithdrawalVerifier binds a generic wrapper to an already deployed contract. -func bindWithdrawalVerifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(WithdrawalVerifierABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_WithdrawalVerifier *WithdrawalVerifierRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _WithdrawalVerifier.Contract.WithdrawalVerifierCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_WithdrawalVerifier *WithdrawalVerifierRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _WithdrawalVerifier.Contract.WithdrawalVerifierTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_WithdrawalVerifier *WithdrawalVerifierRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _WithdrawalVerifier.Contract.WithdrawalVerifierTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_WithdrawalVerifier *WithdrawalVerifierCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _WithdrawalVerifier.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_WithdrawalVerifier *WithdrawalVerifierTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _WithdrawalVerifier.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_WithdrawalVerifier *WithdrawalVerifierTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _WithdrawalVerifier.Contract.contract.Transact(opts, method, params...) -} - -// WithdrawalsRelayMetaData contains all meta data concerning the WithdrawalsRelay contract. -var WithdrawalsRelayMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + return address, tx, &OptimismPortal{OptimismPortalCaller: OptimismPortalCaller{contract: contract}, OptimismPortalTransactor: OptimismPortalTransactor{contract: contract}, OptimismPortalFilterer: OptimismPortalFilterer{contract: contract}}, nil } -// WithdrawalsRelayABI is the input ABI used to generate the binding from. -// Deprecated: Use WithdrawalsRelayMetaData.ABI instead. -var WithdrawalsRelayABI = WithdrawalsRelayMetaData.ABI - -// WithdrawalsRelay is an auto generated Go binding around an Ethereum contract. -type WithdrawalsRelay struct { - WithdrawalsRelayCaller // Read-only binding to the contract - WithdrawalsRelayTransactor // Write-only binding to the contract - WithdrawalsRelayFilterer // Log filterer for contract events +// OptimismPortal is an auto generated Go binding around an Ethereum contract. +type OptimismPortal struct { + OptimismPortalCaller // Read-only binding to the contract + OptimismPortalTransactor // Write-only binding to the contract + OptimismPortalFilterer // Log filterer for contract events } -// WithdrawalsRelayCaller is an auto generated read-only Go binding around an Ethereum contract. -type WithdrawalsRelayCaller struct { +// OptimismPortalCaller is an auto generated read-only Go binding around an Ethereum contract. +type OptimismPortalCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// WithdrawalsRelayTransactor is an auto generated write-only Go binding around an Ethereum contract. -type WithdrawalsRelayTransactor struct { +// OptimismPortalTransactor is an auto generated write-only Go binding around an Ethereum contract. +type OptimismPortalTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// WithdrawalsRelayFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type WithdrawalsRelayFilterer struct { +// OptimismPortalFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OptimismPortalFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// WithdrawalsRelaySession is an auto generated Go binding around an Ethereum contract, +// OptimismPortalSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. -type WithdrawalsRelaySession struct { - Contract *WithdrawalsRelay // Generic contract binding to set the session for +type OptimismPortalSession struct { + Contract *OptimismPortal // Generic contract binding to set the session for CallOpts bind.CallOpts // Call options to use throughout this session TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// WithdrawalsRelayCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// OptimismPortalCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. -type WithdrawalsRelayCallerSession struct { - Contract *WithdrawalsRelayCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session +type OptimismPortalCallerSession struct { + Contract *OptimismPortalCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session } -// WithdrawalsRelayTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// OptimismPortalTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. -type WithdrawalsRelayTransactorSession struct { - Contract *WithdrawalsRelayTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type OptimismPortalTransactorSession struct { + Contract *OptimismPortalTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// WithdrawalsRelayRaw is an auto generated low-level Go binding around an Ethereum contract. -type WithdrawalsRelayRaw struct { - Contract *WithdrawalsRelay // Generic contract binding to access the raw methods on +// OptimismPortalRaw is an auto generated low-level Go binding around an Ethereum contract. +type OptimismPortalRaw struct { + Contract *OptimismPortal // Generic contract binding to access the raw methods on } -// WithdrawalsRelayCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type WithdrawalsRelayCallerRaw struct { - Contract *WithdrawalsRelayCaller // Generic read-only contract binding to access the raw methods on +// OptimismPortalCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OptimismPortalCallerRaw struct { + Contract *OptimismPortalCaller // Generic read-only contract binding to access the raw methods on } -// WithdrawalsRelayTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type WithdrawalsRelayTransactorRaw struct { - Contract *WithdrawalsRelayTransactor // Generic write-only contract binding to access the raw methods on +// OptimismPortalTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OptimismPortalTransactorRaw struct { + Contract *OptimismPortalTransactor // Generic write-only contract binding to access the raw methods on } -// NewWithdrawalsRelay creates a new instance of WithdrawalsRelay, bound to a specific deployed contract. -func NewWithdrawalsRelay(address common.Address, backend bind.ContractBackend) (*WithdrawalsRelay, error) { - contract, err := bindWithdrawalsRelay(address, backend, backend, backend) +// NewOptimismPortal creates a new instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortal(address common.Address, backend bind.ContractBackend) (*OptimismPortal, error) { + contract, err := bindOptimismPortal(address, backend, backend, backend) if err != nil { return nil, err } - return &WithdrawalsRelay{WithdrawalsRelayCaller: WithdrawalsRelayCaller{contract: contract}, WithdrawalsRelayTransactor: WithdrawalsRelayTransactor{contract: contract}, WithdrawalsRelayFilterer: WithdrawalsRelayFilterer{contract: contract}}, nil + return &OptimismPortal{OptimismPortalCaller: OptimismPortalCaller{contract: contract}, OptimismPortalTransactor: OptimismPortalTransactor{contract: contract}, OptimismPortalFilterer: OptimismPortalFilterer{contract: contract}}, nil } -// NewWithdrawalsRelayCaller creates a new read-only instance of WithdrawalsRelay, bound to a specific deployed contract. -func NewWithdrawalsRelayCaller(address common.Address, caller bind.ContractCaller) (*WithdrawalsRelayCaller, error) { - contract, err := bindWithdrawalsRelay(address, caller, nil, nil) +// NewOptimismPortalCaller creates a new read-only instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortalCaller(address common.Address, caller bind.ContractCaller) (*OptimismPortalCaller, error) { + contract, err := bindOptimismPortal(address, caller, nil, nil) if err != nil { return nil, err } - return &WithdrawalsRelayCaller{contract: contract}, nil + return &OptimismPortalCaller{contract: contract}, nil } -// NewWithdrawalsRelayTransactor creates a new write-only instance of WithdrawalsRelay, bound to a specific deployed contract. -func NewWithdrawalsRelayTransactor(address common.Address, transactor bind.ContractTransactor) (*WithdrawalsRelayTransactor, error) { - contract, err := bindWithdrawalsRelay(address, nil, transactor, nil) +// NewOptimismPortalTransactor creates a new write-only instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortalTransactor(address common.Address, transactor bind.ContractTransactor) (*OptimismPortalTransactor, error) { + contract, err := bindOptimismPortal(address, nil, transactor, nil) if err != nil { return nil, err } - return &WithdrawalsRelayTransactor{contract: contract}, nil + return &OptimismPortalTransactor{contract: contract}, nil } -// NewWithdrawalsRelayFilterer creates a new log filterer instance of WithdrawalsRelay, bound to a specific deployed contract. -func NewWithdrawalsRelayFilterer(address common.Address, filterer bind.ContractFilterer) (*WithdrawalsRelayFilterer, error) { - contract, err := bindWithdrawalsRelay(address, nil, nil, filterer) +// NewOptimismPortalFilterer creates a new log filterer instance of OptimismPortal, bound to a specific deployed contract. +func NewOptimismPortalFilterer(address common.Address, filterer bind.ContractFilterer) (*OptimismPortalFilterer, error) { + contract, err := bindOptimismPortal(address, nil, nil, filterer) if err != nil { return nil, err } - return &WithdrawalsRelayFilterer{contract: contract}, nil + return &OptimismPortalFilterer{contract: contract}, nil } -// bindWithdrawalsRelay binds a generic wrapper to an already deployed contract. -func bindWithdrawalsRelay(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(WithdrawalsRelayABI)) +// bindOptimismPortal binds a generic wrapper to an already deployed contract. +func bindOptimismPortal(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(OptimismPortalABI)) if err != nil { return nil, err } @@ -3879,46 +175,46 @@ func bindWithdrawalsRelay(address common.Address, caller bind.ContractCaller, tr // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_WithdrawalsRelay *WithdrawalsRelayRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _WithdrawalsRelay.Contract.WithdrawalsRelayCaller.contract.Call(opts, result, method, params...) +func (_OptimismPortal *OptimismPortalRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismPortal.Contract.OptimismPortalCaller.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_WithdrawalsRelay *WithdrawalsRelayRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _WithdrawalsRelay.Contract.WithdrawalsRelayTransactor.contract.Transfer(opts) +func (_OptimismPortal *OptimismPortalRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal.Contract.OptimismPortalTransactor.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_WithdrawalsRelay *WithdrawalsRelayRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _WithdrawalsRelay.Contract.WithdrawalsRelayTransactor.contract.Transact(opts, method, params...) +func (_OptimismPortal *OptimismPortalRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismPortal.Contract.OptimismPortalTransactor.contract.Transact(opts, method, params...) } // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_WithdrawalsRelay *WithdrawalsRelayCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _WithdrawalsRelay.Contract.contract.Call(opts, result, method, params...) +func (_OptimismPortal *OptimismPortalCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismPortal.Contract.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_WithdrawalsRelay *WithdrawalsRelayTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _WithdrawalsRelay.Contract.contract.Transfer(opts) +func (_OptimismPortal *OptimismPortalTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal.Contract.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_WithdrawalsRelay *WithdrawalsRelayTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _WithdrawalsRelay.Contract.contract.Transact(opts, method, params...) +func (_OptimismPortal *OptimismPortalTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismPortal.Contract.contract.Transact(opts, method, params...) } // FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. // // Solidity: function FINALIZATION_PERIOD() view returns(uint256) -func (_WithdrawalsRelay *WithdrawalsRelayCaller) FINALIZATIONPERIOD(opts *bind.CallOpts) (*big.Int, error) { +func (_OptimismPortal *OptimismPortalCaller) FINALIZATIONPERIOD(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _WithdrawalsRelay.contract.Call(opts, &out, "FINALIZATION_PERIOD") + err := _OptimismPortal.contract.Call(opts, &out, "FINALIZATION_PERIOD") if err != nil { return *new(*big.Int), err @@ -3933,23 +229,23 @@ func (_WithdrawalsRelay *WithdrawalsRelayCaller) FINALIZATIONPERIOD(opts *bind.C // FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. // // Solidity: function FINALIZATION_PERIOD() view returns(uint256) -func (_WithdrawalsRelay *WithdrawalsRelaySession) FINALIZATIONPERIOD() (*big.Int, error) { - return _WithdrawalsRelay.Contract.FINALIZATIONPERIOD(&_WithdrawalsRelay.CallOpts) +func (_OptimismPortal *OptimismPortalSession) FINALIZATIONPERIOD() (*big.Int, error) { + return _OptimismPortal.Contract.FINALIZATIONPERIOD(&_OptimismPortal.CallOpts) } // FINALIZATIONPERIOD is a free data retrieval call binding the contract method 0xff61cc93. // // Solidity: function FINALIZATION_PERIOD() view returns(uint256) -func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) FINALIZATIONPERIOD() (*big.Int, error) { - return _WithdrawalsRelay.Contract.FINALIZATIONPERIOD(&_WithdrawalsRelay.CallOpts) +func (_OptimismPortal *OptimismPortalCallerSession) FINALIZATIONPERIOD() (*big.Int, error) { + return _OptimismPortal.Contract.FINALIZATIONPERIOD(&_OptimismPortal.CallOpts) } // L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. // // Solidity: function L2_ORACLE() view returns(address) -func (_WithdrawalsRelay *WithdrawalsRelayCaller) L2ORACLE(opts *bind.CallOpts) (common.Address, error) { +func (_OptimismPortal *OptimismPortalCaller) L2ORACLE(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _WithdrawalsRelay.contract.Call(opts, &out, "L2_ORACLE") + err := _OptimismPortal.contract.Call(opts, &out, "L2_ORACLE") if err != nil { return *new(common.Address), err @@ -3964,23 +260,23 @@ func (_WithdrawalsRelay *WithdrawalsRelayCaller) L2ORACLE(opts *bind.CallOpts) ( // L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. // // Solidity: function L2_ORACLE() view returns(address) -func (_WithdrawalsRelay *WithdrawalsRelaySession) L2ORACLE() (common.Address, error) { - return _WithdrawalsRelay.Contract.L2ORACLE(&_WithdrawalsRelay.CallOpts) +func (_OptimismPortal *OptimismPortalSession) L2ORACLE() (common.Address, error) { + return _OptimismPortal.Contract.L2ORACLE(&_OptimismPortal.CallOpts) } // L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. // // Solidity: function L2_ORACLE() view returns(address) -func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) L2ORACLE() (common.Address, error) { - return _WithdrawalsRelay.Contract.L2ORACLE(&_WithdrawalsRelay.CallOpts) +func (_OptimismPortal *OptimismPortalCallerSession) L2ORACLE() (common.Address, error) { + return _OptimismPortal.Contract.L2ORACLE(&_OptimismPortal.CallOpts) } // FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. // // Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) -func (_WithdrawalsRelay *WithdrawalsRelayCaller) FinalizedWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { +func (_OptimismPortal *OptimismPortalCaller) FinalizedWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { var out []interface{} - err := _WithdrawalsRelay.contract.Call(opts, &out, "finalizedWithdrawals", arg0) + err := _OptimismPortal.contract.Call(opts, &out, "finalizedWithdrawals", arg0) if err != nil { return *new(bool), err @@ -3995,23 +291,23 @@ func (_WithdrawalsRelay *WithdrawalsRelayCaller) FinalizedWithdrawals(opts *bind // FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. // // Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) -func (_WithdrawalsRelay *WithdrawalsRelaySession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { - return _WithdrawalsRelay.Contract.FinalizedWithdrawals(&_WithdrawalsRelay.CallOpts, arg0) +func (_OptimismPortal *OptimismPortalSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _OptimismPortal.Contract.FinalizedWithdrawals(&_OptimismPortal.CallOpts, arg0) } // FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. // // Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) -func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { - return _WithdrawalsRelay.Contract.FinalizedWithdrawals(&_WithdrawalsRelay.CallOpts, arg0) +func (_OptimismPortal *OptimismPortalCallerSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _OptimismPortal.Contract.FinalizedWithdrawals(&_OptimismPortal.CallOpts, arg0) } // L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. // // Solidity: function l2Sender() view returns(address) -func (_WithdrawalsRelay *WithdrawalsRelayCaller) L2Sender(opts *bind.CallOpts) (common.Address, error) { +func (_OptimismPortal *OptimismPortalCaller) L2Sender(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _WithdrawalsRelay.contract.Call(opts, &out, "l2Sender") + err := _OptimismPortal.contract.Call(opts, &out, "l2Sender") if err != nil { return *new(common.Address), err @@ -4026,41 +322,241 @@ func (_WithdrawalsRelay *WithdrawalsRelayCaller) L2Sender(opts *bind.CallOpts) ( // L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. // // Solidity: function l2Sender() view returns(address) -func (_WithdrawalsRelay *WithdrawalsRelaySession) L2Sender() (common.Address, error) { - return _WithdrawalsRelay.Contract.L2Sender(&_WithdrawalsRelay.CallOpts) +func (_OptimismPortal *OptimismPortalSession) L2Sender() (common.Address, error) { + return _OptimismPortal.Contract.L2Sender(&_OptimismPortal.CallOpts) } // L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. // // Solidity: function l2Sender() view returns(address) -func (_WithdrawalsRelay *WithdrawalsRelayCallerSession) L2Sender() (common.Address, error) { - return _WithdrawalsRelay.Contract.L2Sender(&_WithdrawalsRelay.CallOpts) +func (_OptimismPortal *OptimismPortalCallerSession) L2Sender() (common.Address, error) { + return _OptimismPortal.Contract.L2Sender(&_OptimismPortal.CallOpts) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalTransactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal *OptimismPortalTransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.DepositTransaction(&_OptimismPortal.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) } // FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. // // Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_WithdrawalsRelay *WithdrawalsRelayTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _WithdrawalsRelay.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) } // FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. // // Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_WithdrawalsRelay *WithdrawalsRelaySession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _WithdrawalsRelay.Contract.FinalizeWithdrawalTransaction(&_WithdrawalsRelay.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) } // FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. // // Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_WithdrawalsRelay *WithdrawalsRelayTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _WithdrawalsRelay.Contract.FinalizeWithdrawalTransaction(&_WithdrawalsRelay.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal *OptimismPortalTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal *OptimismPortalSession) Receive() (*types.Transaction, error) { + return _OptimismPortal.Contract.Receive(&_OptimismPortal.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal *OptimismPortalTransactorSession) Receive() (*types.Transaction, error) { + return _OptimismPortal.Contract.Receive(&_OptimismPortal.TransactOpts) +} + +// OptimismPortalTransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the OptimismPortal contract. +type OptimismPortalTransactionDepositedIterator struct { + Event *OptimismPortalTransactionDeposited // 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 *OptimismPortalTransactionDepositedIterator) 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(OptimismPortalTransactionDeposited) + 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(OptimismPortalTransactionDeposited) + 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 *OptimismPortalTransactionDepositedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortalTransactionDepositedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortalTransactionDeposited represents a TransactionDeposited event raised by the OptimismPortal contract. +type OptimismPortalTransactionDeposited struct { + From common.Address + To common.Address + Mint *big.Int + Value *big.Int + GasLimit uint64 + IsCreation bool + Data []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) +func (_OptimismPortal *OptimismPortalFilterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismPortalTransactionDepositedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule) + if err != nil { + return nil, err + } + return &OptimismPortalTransactionDepositedIterator{contract: _OptimismPortal.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil +} + +// WatchTransactionDeposited is a free log subscription operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) +func (_OptimismPortal *OptimismPortalFilterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *OptimismPortalTransactionDeposited, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule) + 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(OptimismPortalTransactionDeposited) + if err := _OptimismPortal.contract.UnpackLog(event, "TransactionDeposited", 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 } -// WithdrawalsRelayWithdrawalFinalizedIterator is returned from FilterWithdrawalFinalized and is used to iterate over the raw logs and unpacked data for WithdrawalFinalized events raised by the WithdrawalsRelay contract. -type WithdrawalsRelayWithdrawalFinalizedIterator struct { - Event *WithdrawalsRelayWithdrawalFinalized // Event containing the contract specifics and raw log +// ParseTransactionDeposited is a log parse operation binding the contract event 0x78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 mint, uint256 value, uint64 gasLimit, bool isCreation, bytes data) +func (_OptimismPortal *OptimismPortalFilterer) ParseTransactionDeposited(log types.Log) (*OptimismPortalTransactionDeposited, error) { + event := new(OptimismPortalTransactionDeposited) + if err := _OptimismPortal.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OptimismPortalWithdrawalFinalizedIterator is returned from FilterWithdrawalFinalized and is used to iterate over the raw logs and unpacked data for WithdrawalFinalized events raised by the OptimismPortal contract. +type OptimismPortalWithdrawalFinalizedIterator struct { + Event *OptimismPortalWithdrawalFinalized // 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 @@ -4074,7 +570,7 @@ type WithdrawalsRelayWithdrawalFinalizedIterator struct { // 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 *WithdrawalsRelayWithdrawalFinalizedIterator) Next() bool { +func (it *OptimismPortalWithdrawalFinalizedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -4083,7 +579,7 @@ func (it *WithdrawalsRelayWithdrawalFinalizedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(WithdrawalsRelayWithdrawalFinalized) + it.Event = new(OptimismPortalWithdrawalFinalized) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -4098,7 +594,7 @@ func (it *WithdrawalsRelayWithdrawalFinalizedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(WithdrawalsRelayWithdrawalFinalized) + it.Event = new(OptimismPortalWithdrawalFinalized) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -4114,19 +610,19 @@ func (it *WithdrawalsRelayWithdrawalFinalizedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *WithdrawalsRelayWithdrawalFinalizedIterator) Error() error { +func (it *OptimismPortalWithdrawalFinalizedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *WithdrawalsRelayWithdrawalFinalizedIterator) Close() error { +func (it *OptimismPortalWithdrawalFinalizedIterator) Close() error { it.sub.Unsubscribe() return nil } -// WithdrawalsRelayWithdrawalFinalized represents a WithdrawalFinalized event raised by the WithdrawalsRelay contract. -type WithdrawalsRelayWithdrawalFinalized struct { +// OptimismPortalWithdrawalFinalized represents a WithdrawalFinalized event raised by the OptimismPortal contract. +type OptimismPortalWithdrawalFinalized struct { Arg0 [32]byte Raw types.Log // Blockchain specific contextual infos } @@ -4134,31 +630,31 @@ type WithdrawalsRelayWithdrawalFinalized struct { // FilterWithdrawalFinalized is a free log retrieval operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. // // Solidity: event WithdrawalFinalized(bytes32 indexed arg0) -func (_WithdrawalsRelay *WithdrawalsRelayFilterer) FilterWithdrawalFinalized(opts *bind.FilterOpts, arg0 [][32]byte) (*WithdrawalsRelayWithdrawalFinalizedIterator, error) { +func (_OptimismPortal *OptimismPortalFilterer) FilterWithdrawalFinalized(opts *bind.FilterOpts, arg0 [][32]byte) (*OptimismPortalWithdrawalFinalizedIterator, error) { var arg0Rule []interface{} for _, arg0Item := range arg0 { arg0Rule = append(arg0Rule, arg0Item) } - logs, sub, err := _WithdrawalsRelay.contract.FilterLogs(opts, "WithdrawalFinalized", arg0Rule) + logs, sub, err := _OptimismPortal.contract.FilterLogs(opts, "WithdrawalFinalized", arg0Rule) if err != nil { return nil, err } - return &WithdrawalsRelayWithdrawalFinalizedIterator{contract: _WithdrawalsRelay.contract, event: "WithdrawalFinalized", logs: logs, sub: sub}, nil + return &OptimismPortalWithdrawalFinalizedIterator{contract: _OptimismPortal.contract, event: "WithdrawalFinalized", logs: logs, sub: sub}, nil } // WatchWithdrawalFinalized is a free log subscription operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. // // Solidity: event WithdrawalFinalized(bytes32 indexed arg0) -func (_WithdrawalsRelay *WithdrawalsRelayFilterer) WatchWithdrawalFinalized(opts *bind.WatchOpts, sink chan<- *WithdrawalsRelayWithdrawalFinalized, arg0 [][32]byte) (event.Subscription, error) { +func (_OptimismPortal *OptimismPortalFilterer) WatchWithdrawalFinalized(opts *bind.WatchOpts, sink chan<- *OptimismPortalWithdrawalFinalized, arg0 [][32]byte) (event.Subscription, error) { var arg0Rule []interface{} for _, arg0Item := range arg0 { arg0Rule = append(arg0Rule, arg0Item) } - logs, sub, err := _WithdrawalsRelay.contract.WatchLogs(opts, "WithdrawalFinalized", arg0Rule) + logs, sub, err := _OptimismPortal.contract.WatchLogs(opts, "WithdrawalFinalized", arg0Rule) if err != nil { return nil, err } @@ -4168,8 +664,8 @@ func (_WithdrawalsRelay *WithdrawalsRelayFilterer) WatchWithdrawalFinalized(opts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(WithdrawalsRelayWithdrawalFinalized) - if err := _WithdrawalsRelay.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { + event := new(OptimismPortalWithdrawalFinalized) + if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { return err } event.Raw = log @@ -4193,9 +689,9 @@ func (_WithdrawalsRelay *WithdrawalsRelayFilterer) WatchWithdrawalFinalized(opts // ParseWithdrawalFinalized is a log parse operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. // // Solidity: event WithdrawalFinalized(bytes32 indexed arg0) -func (_WithdrawalsRelay *WithdrawalsRelayFilterer) ParseWithdrawalFinalized(log types.Log) (*WithdrawalsRelayWithdrawalFinalized, error) { - event := new(WithdrawalsRelayWithdrawalFinalized) - if err := _WithdrawalsRelay.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { +func (_OptimismPortal *OptimismPortalFilterer) ParseWithdrawalFinalized(log types.Log) (*OptimismPortalWithdrawalFinalized, error) { + event := new(OptimismPortalWithdrawalFinalized) + if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { return nil, err } event.Raw = log diff --git a/opnode/contracts/l1block/l1_block_info_deployed.go b/opnode/contracts/l1block/l1_block_info_deployed.go index 9d5b0387dba4..2725a8109177 100644 --- a/opnode/contracts/l1block/l1_block_info_deployed.go +++ b/opnode/contracts/l1block/l1_block_info_deployed.go @@ -2,4 +2,4 @@ // This file is a generated binding and any manual changes will be lost. package l1block -var L1blockDeployedBin = "608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220223f4770a19b9fba63f4604d9ad8c075ca4f396c2d57476d208c9414ec7f831464736f6c634300080a0033" +var L1blockDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063b80777ea11610050578063b80777ea146100a5578063c03ba43e146100ae578063e591b282146100c357600080fd5b806309bd5a60146100775780635cf24969146100935780638381f58a1461009c575b600080fd5b61008060035481565b6040519081526020015b60405180910390f35b61008060025481565b61008060005481565b61008060015481565b6100c16100bc366004610164565b610103565b005b6100de73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008a565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610150576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600093909355600191909155600255600355565b6000806000806080858703121561017a57600080fd5b505082359460208401359450604084013593606001359250905056fea26469706673582212202030f0b19d5ff0b7a5d094d184635f40535b3dd5b50e391125e80dcd7c4dfb1564736f6c634300080a0033" diff --git a/opnode/contracts/l1block/l1_block_info_raw.go b/opnode/contracts/l1block/l1_block_info_raw.go index 2c2ad0e861dc..6073023f86de 100644 --- a/opnode/contracts/l1block/l1_block_info_raw.go +++ b/opnode/contracts/l1block/l1_block_info_raw.go @@ -31,7 +31,7 @@ var ( // L1BlockMetaData contains all meta data concerning the L1Block contract. var L1BlockMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506103a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806309bd5a60146100675780635cf24969146100855780638381f58a146100a3578063b80777ea146100c1578063c03ba43e146100df578063e591b282146100fb575b600080fd5b61006f610119565b60405161007c91906101fd565b60405180910390f35b61008d61011f565b60405161009a9190610231565b60405180910390f35b6100ab610125565b6040516100b89190610231565b60405180910390f35b6100c961012b565b6040516100d69190610231565b60405180910390f35b6100f960048036038101906100f491906102a9565b610131565b005b6101036101cc565b6040516101109190610351565b60405180910390f35b60035481565b60025481565b60005481565b60015481565b73deaddeaddeaddeaddeaddeaddeaddeaddead000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360008190555082600181905550816002819055508060038190555050505050565b73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b6000819050919050565b6101f7816101e4565b82525050565b600060208201905061021260008301846101ee565b92915050565b6000819050919050565b61022b81610218565b82525050565b60006020820190506102466000830184610222565b92915050565b600080fd5b61025a81610218565b811461026557600080fd5b50565b60008135905061027781610251565b92915050565b610286816101e4565b811461029157600080fd5b50565b6000813590506102a38161027d565b92915050565b600080600080608085870312156102c3576102c261024c565b5b60006102d187828801610268565b94505060206102e287828801610268565b93505060406102f387828801610268565b925050606061030487828801610294565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061033b82610310565b9050919050565b61034b81610330565b82525050565b60006020820190506103666000830184610342565b9291505056fea2646970667358221220223f4770a19b9fba63f4604d9ad8c075ca4f396c2d57476d208c9414ec7f831464736f6c634300080a0033", + Bin: "0x608060405234801561001057600080fd5b506101cc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063b80777ea11610050578063b80777ea146100a5578063c03ba43e146100ae578063e591b282146100c357600080fd5b806309bd5a60146100775780635cf24969146100935780638381f58a1461009c575b600080fd5b61008060035481565b6040519081526020015b60405180910390f35b61008060025481565b61008060005481565b61008060015481565b6100c16100bc366004610164565b610103565b005b6100de73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008a565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610150576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600093909355600191909155600255600355565b6000806000806080858703121561017a57600080fd5b505082359460208401359450604084013593606001359250905056fea26469706673582212202030f0b19d5ff0b7a5d094d184635f40535b3dd5b50e391125e80dcd7c4dfb1564736f6c634300080a0033", } // L1BlockABI is the input ABI used to generate the binding from. From a57eda05678fa97093b7374fcf276c0658b3f080 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Tue, 3 May 2022 14:17:36 -0700 Subject: [PATCH 514/585] l2os: update bindings --- l2os/bindings/l2oo/l2_output_oracle.go | 402 ++++++++++++++++++------- 1 file changed, 288 insertions(+), 114 deletions(-) diff --git a/l2os/bindings/l2oo/l2_output_oracle.go b/l2os/bindings/l2oo/l2_output_oracle.go index 719741610fc3..2dd74f953165 100644 --- a/l2os/bindings/l2oo/l2_output_oracle.go +++ b/l2os/bindings/l2oo/l2_output_oracle.go @@ -30,8 +30,8 @@ var ( // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"historicalTotalBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620012f2380380620012f2833981810160405281019062000038919062000260565b620000586200004c620000b460201b60201c565b620000bc60201b60201c565b85608081815250508460a081815250508360026000848152602001908152602001600020819055508260c08181525050816001819055508160e08181525050620000a881620000bc60201b60201c565b505050505050620002fc565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6200019a8162000185565b8114620001a657600080fd5b50565b600081519050620001ba816200018f565b92915050565b6000819050919050565b620001d581620001c0565b8114620001e157600080fd5b50565b600081519050620001f581620001ca565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022882620001fb565b9050919050565b6200023a816200021b565b81146200024657600080fd5b50565b6000815190506200025a816200022f565b92915050565b60008060008060008060c0878903121562000280576200027f62000180565b5b60006200029089828a01620001a9565b9650506020620002a389828a01620001a9565b9550506040620002b689828a01620001e4565b9450506060620002c989828a01620001a9565b9350506080620002dc89828a01620001a9565b92505060a0620002ef89828a0162000249565b9150509295509295509295565b60805160a05160c05160e051610f9962000359600039600081816102b30152818161033701526106b001526000818161036b01526106d4015260008181610316015261066f01526000818161058b01526106f80152610f996000f3fe6080604052600436106100a75760003560e01c806393991af31161006457806393991af31461019d578063a25ae557146101c8578063c5095d6814610205578063c90ec2da14610230578063e1a41bcf1461025b578063f2fde38b14610286576100a7565b806302e51345146100ac5780630c1952d3146100e95780632518810414610114578063357e951f14610130578063715018a61461015b5780638da5cb5b14610172575b600080fd5b3480156100b857600080fd5b506100d360048036038101906100ce9190610919565b6102af565b6040516100e09190610955565b60405180910390f35b3480156100f557600080fd5b506100fe610393565b60405161010b9190610955565b60405180910390f35b61012e600480360381019061012991906109a6565b610399565b005b34801561013c57600080fd5b50610145610587565b6040516101529190610955565b60405180910390f35b34801561016757600080fd5b506101706105bc565b005b34801561017e57600080fd5b50610187610644565b6040516101949190610a4e565b60405180910390f35b3480156101a957600080fd5b506101b261066d565b6040516101bf9190610955565b60405180910390f35b3480156101d457600080fd5b506101ef60048036038101906101ea9190610919565b610691565b6040516101fc9190610a78565b60405180910390f35b34801561021157600080fd5b5061021a6106ae565b6040516102279190610955565b60405180910390f35b34801561023c57600080fd5b506102456106d2565b6040516102529190610955565b60405180910390f35b34801561026757600080fd5b506102706106f6565b60405161027d9190610955565b60405180910390f35b34801561029257600080fd5b506102ad60048036038101906102a89190610abf565b61071a565b005b60007f0000000000000000000000000000000000000000000000000000000000000000821015610314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030b90610b6f565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161036657610365610b8f565b5b0460017f000000000000000000000000000000000000000000000000000000000000000001019050919050565b60015481565b6103a1610812565b73ffffffffffffffffffffffffffffffffffffffff166103bf610644565b73ffffffffffffffffffffffffffffffffffffffff1614610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040c90610c0a565b60405180910390fd5b428310610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e90610c9c565b60405180910390fd5b61045f610587565b83146104a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049790610d2e565b60405180910390fd5b6000801b8414156104e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104dd90610d9a565b60405180910390fd5b6000801b82146105345781814014610533576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052a90610e2c565b60405180910390fd5b5b8360026000858152602001908152602001600020819055508260018190555082847f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b60405160405180910390a350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546105b79190610e7b565b905090565b6105c4610812565b73ffffffffffffffffffffffffffffffffffffffff166105e2610644565b73ffffffffffffffffffffffffffffffffffffffff1614610638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062f90610c0a565b60405180910390fd5b610642600061081a565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060026000838152602001908152602001600020549050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610722610812565b73ffffffffffffffffffffffffffffffffffffffff16610740610644565b73ffffffffffffffffffffffffffffffffffffffff1614610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078d90610c0a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610806576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fd90610f43565b60405180910390fd5b61080f8161081a565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6108f6816108e3565b811461090157600080fd5b50565b600081359050610913816108ed565b92915050565b60006020828403121561092f5761092e6108de565b5b600061093d84828501610904565b91505092915050565b61094f816108e3565b82525050565b600060208201905061096a6000830184610946565b92915050565b6000819050919050565b61098381610970565b811461098e57600080fd5b50565b6000813590506109a08161097a565b92915050565b600080600080608085870312156109c0576109bf6108de565b5b60006109ce87828801610991565b94505060206109df87828801610904565b93505060406109f087828801610991565b9250506060610a0187828801610904565b91505092959194509250565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a3882610a0d565b9050919050565b610a4881610a2d565b82525050565b6000602082019050610a636000830184610a3f565b92915050565b610a7281610970565b82525050565b6000602082019050610a8d6000830184610a69565b92915050565b610a9c81610a2d565b8114610aa757600080fd5b50565b600081359050610ab981610a93565b92915050565b600060208284031215610ad557610ad46108de565b5b6000610ae384828501610aaa565b91505092915050565b600082825260208201905092915050565b7f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60008201527f54696d657374616d700000000000000000000000000000000000000000000000602082015250565b6000610b59602983610aec565b9150610b6482610afd565b604082019050919050565b60006020820190508181036000830152610b8881610b4c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610bf4602083610aec565b9150610bff82610bbe565b602082019050919050565b60006020820190508181036000830152610c2381610be7565b9050919050565b7f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000610c86602183610aec565b9150610c9182610c2a565b604082019050919050565b60006020820190508181036000830152610cb581610c79565b9050919050565b7f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560008201527f637465642074696d657374616d70000000000000000000000000000000000000602082015250565b6000610d18602e83610aec565b9150610d2382610cbc565b604082019050919050565b60006020820190508181036000830152610d4781610d0b565b9050919050565b7f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000600082015250565b6000610d84601d83610aec565b9150610d8f82610d4e565b602082019050919050565b60006020820190508181036000830152610db381610d77565b9050919050565b7f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360008201527f6820617420746865206578706563746564206865696768742e00000000000000602082015250565b6000610e16603983610aec565b9150610e2182610dba565b604082019050919050565b60006020820190508181036000830152610e4581610e09565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e86826108e3565b9150610e91836108e3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ec657610ec5610e4c565b5b828201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610f2d602683610aec565b9150610f3882610ed1565b604082019050919050565b60006020820190508181036000830152610f5c81610f20565b905091905056fea2646970667358221220980520f45819a707ff13a09b23bdace7cce468e4b8e92e7fd2f480d56c85cb7664736f6c634300080a0033", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x61010060405234801561001157600080fd5b50604051610e66380380610e6683398101604081905261003091610148565b610039336100f8565b61004385876101ac565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052600082815260026020526040902084905560c0839052600182905560e08290526100ed816100f8565b5050505050506101ce565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561016157600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b038116811461019e57600080fd5b809150509295509295509295565b6000826101c957634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610c36610230600039600081816101af015281816102d401526103aa01526000818161028e01526103db01526000818160e801526103890152600081816101e30152818161085801526108880152610c366000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad1461027c578063f2fde38b146102b057600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b806325188104116100b057806325188104146101535780632b5d15d914610168578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d5780630c1952d31461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610aeb565b6102d0565b34801561014957600080fd5b5061010a60015481565b610166610161366004610b04565b610405565b005b34801561017457600080fd5b50610166610183366004610aeb565b6106ee565b34801561019457600080fd5b5061010a610884565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b506101666108b9565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b5061010a61026a366004610aeb565b60009081526002602052604090205490565b34801561028857600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102bc57600080fd5b506101666102cb366004610b36565b610946565b60007f0000000000000000000000000000000000000000000000000000000000000000821015610387576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008303816103d8576103d8610b73565b047f0000000000000000000000000000000000000000000000000000000000000000600101019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b428310610515576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f6500000000000000000000000000000000000000000000000000000000000000606482015260840161037e565b61051d610884565b83146105ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d70000000000000000000000000000000000000606482015260840161037e565b83610612576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000604482015260640161037e565b81156106a857818140146106a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e00000000000000606482015260840161037e565b600083815260026020526040808220869055600185905551849186917f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b9190a350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b600154600090815260026020526040902054818114610810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e00000000000000000000000000000000000000000000000000606482015260840161037e565b60015460405182907f36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f26690600090a3600180546000908152600260205260408120555461087d907f000000000000000000000000000000000000000000000000000000000000000090610bd1565b6001555050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546108b49190610be8565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331461093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b6109446000610a76565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b73ffffffffffffffffffffffffffffffffffffffff8116610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161037e565b610a7381610a76565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610afd57600080fd5b5035919050565b60008060008060808587031215610b1a57600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610b4857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610b6c57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610be357610be3610ba2565b500390565b60008219821115610bfb57610bfb610ba2565b50019056fea26469706673582212202b75e7488f5da959d6f6a42e7994006e9678d900e97b36879b2d9afc9ee2659b64736f6c634300080a0033", } // L2OutputOracleABI is the input ABI used to generate the binding from. @@ -201,12 +201,12 @@ func (_L2OutputOracle *L2OutputOracleTransactorRaw) Transact(opts *bind.Transact return _L2OutputOracle.Contract.contract.Transact(opts, method, params...) } -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. // -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) { +// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) HISTORICALTOTALBLOCKS(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp) + err := _L2OutputOracle.contract.Call(opts, &out, "HISTORICAL_TOTAL_BLOCKS") if err != nil { return *new(*big.Int), err @@ -218,57 +218,88 @@ func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.Cal } -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. // -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { - return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) HISTORICALTOTALBLOCKS() (*big.Int, error) { + return _L2OutputOracle.Contract.HISTORICALTOTALBLOCKS(&_L2OutputOracle.CallOpts) } -// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// HISTORICALTOTALBLOCKS is a free data retrieval call binding the contract method 0xa4771aad. // -// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { - return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +// Solidity: function HISTORICAL_TOTAL_BLOCKS() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) HISTORICALTOTALBLOCKS() (*big.Int, error) { + return _L2OutputOracle.Contract.HISTORICALTOTALBLOCKS(&_L2OutputOracle.CallOpts) } -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { +// Solidity: function L2_BLOCK_TIME() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) L2BLOCKTIME(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) + err := _L2OutputOracle.contract.Call(opts, &out, "L2_BLOCK_TIME") if err != nil { - return *new([32]byte), err + return *new(*big.Int), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err } -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { - return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +// Solidity: function L2_BLOCK_TIME() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) L2BLOCKTIME() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BLOCKTIME(&_L2OutputOracle.CallOpts) } -// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// L2BLOCKTIME is a free data retrieval call binding the contract method 0x002134cc. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { - return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) +// Solidity: function L2_BLOCK_TIME() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) L2BLOCKTIME() (*big.Int, error) { + return _L2OutputOracle.Contract.L2BLOCKTIME(&_L2OutputOracle.CallOpts) +} + +// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. +// +// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) STARTINGBLOCKTIMESTAMP(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "STARTING_BLOCK_TIMESTAMP") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. // -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) { + return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts) +} + +// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6. +// +// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) { + return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts) +} + +// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. +// +// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) SUBMISSIONINTERVAL(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "historicalTotalBlocks") + err := _L2OutputOracle.contract.Call(opts, &out, "SUBMISSION_INTERVAL") if err != nil { return *new(*big.Int), err @@ -280,26 +311,26 @@ func (_L2OutputOracle *L2OutputOracleCaller) HistoricalTotalBlocks(opts *bind.Ca } -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. // -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) HistoricalTotalBlocks() (*big.Int, error) { - return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) SUBMISSIONINTERVAL() (*big.Int, error) { + return _L2OutputOracle.Contract.SUBMISSIONINTERVAL(&_L2OutputOracle.CallOpts) } -// HistoricalTotalBlocks is a free data retrieval call binding the contract method 0xc90ec2da. +// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df. // -// Solidity: function historicalTotalBlocks() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) HistoricalTotalBlocks() (*big.Int, error) { - return _L2OutputOracle.Contract.HistoricalTotalBlocks(&_L2OutputOracle.CallOpts) +// Solidity: function SUBMISSION_INTERVAL() view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) SUBMISSIONINTERVAL() (*big.Int, error) { + return _L2OutputOracle.Contract.SUBMISSIONINTERVAL(&_L2OutputOracle.CallOpts) } -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. // -// Solidity: function l2BlockTime() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) { var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "l2BlockTime") + err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp) if err != nil { return *new(*big.Int), err @@ -311,18 +342,49 @@ func (_L2OutputOracle *L2OutputOracleCaller) L2BlockTime(opts *bind.CallOpts) (* } -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345. +// +// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256) +func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) { + return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp) +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. +// +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { + var out []interface{} + err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. // -// Solidity: function l2BlockTime() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) L2BlockTime() (*big.Int, error) { - return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) } -// L2BlockTime is a free data retrieval call binding the contract method 0x93991af3. +// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. // -// Solidity: function l2BlockTime() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) L2BlockTime() (*big.Int, error) { - return _L2OutputOracle.Contract.L2BlockTime(&_L2OutputOracle.CallOpts) +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) +func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { + return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) } // LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3. @@ -418,68 +480,6 @@ func (_L2OutputOracle *L2OutputOracleCallerSession) Owner() (common.Address, err return _L2OutputOracle.Contract.Owner(&_L2OutputOracle.CallOpts) } -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) StartingBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "startingBlockTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) StartingBlockTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) -} - -// StartingBlockTimestamp is a free data retrieval call binding the contract method 0xc5095d68. -// -// Solidity: function startingBlockTimestamp() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) StartingBlockTimestamp() (*big.Int, error) { - return _L2OutputOracle.Contract.StartingBlockTimestamp(&_L2OutputOracle.CallOpts) -} - -// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. -// -// Solidity: function submissionInterval() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCaller) SubmissionInterval(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _L2OutputOracle.contract.Call(opts, &out, "submissionInterval") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. -// -// Solidity: function submissionInterval() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleSession) SubmissionInterval() (*big.Int, error) { - return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) -} - -// SubmissionInterval is a free data retrieval call binding the contract method 0xe1a41bcf. -// -// Solidity: function submissionInterval() view returns(uint256) -func (_L2OutputOracle *L2OutputOracleCallerSession) SubmissionInterval() (*big.Int, error) { - return _L2OutputOracle.Contract.SubmissionInterval(&_L2OutputOracle.CallOpts) -} - // AppendL2Output is a paid mutator transaction binding the contract method 0x25188104. // // Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns() @@ -501,6 +501,27 @@ func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) } +// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// +// Solidity: function deleteL2Output(bytes32 _l2Output) returns() +func (_L2OutputOracle *L2OutputOracleTransactor) DeleteL2Output(opts *bind.TransactOpts, _l2Output [32]byte) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "deleteL2Output", _l2Output) +} + +// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// +// Solidity: function deleteL2Output(bytes32 _l2Output) returns() +func (_L2OutputOracle *L2OutputOracleSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { + return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) +} + +// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// +// Solidity: function deleteL2Output(bytes32 _l2Output) returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { + return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) +} + // RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. // // Solidity: function renounceOwnership() returns() @@ -848,3 +869,156 @@ func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.L event.Raw = log return event, nil } + +// L2OutputOracleL2OutputDeletedIterator is returned from FilterL2OutputDeleted and is used to iterate over the raw logs and unpacked data for L2OutputDeleted events raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputDeletedIterator struct { + Event *L2OutputOracleL2OutputDeleted // 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 *L2OutputOracleL2OutputDeletedIterator) 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(L2OutputOracleL2OutputDeleted) + 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(L2OutputOracleL2OutputDeleted) + 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 *L2OutputOracleL2OutputDeletedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *L2OutputOracleL2OutputDeletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// L2OutputOracleL2OutputDeleted represents a L2OutputDeleted event raised by the L2OutputOracle contract. +type L2OutputOracleL2OutputDeleted struct { + L2Output [32]byte + L2timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterL2OutputDeleted is a free log retrieval operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputDeleted(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputDeletedIterator, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) + if err != nil { + return nil, err + } + return &L2OutputOracleL2OutputDeletedIterator{contract: _L2OutputOracle.contract, event: "l2OutputDeleted", logs: logs, sub: sub}, nil +} + +// WatchL2OutputDeleted is a free log subscription operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputDeleted, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { + + var _l2OutputRule []interface{} + for _, _l2OutputItem := range _l2Output { + _l2OutputRule = append(_l2OutputRule, _l2OutputItem) + } + var _l2timestampRule []interface{} + for _, _l2timestampItem := range _l2timestamp { + _l2timestampRule = append(_l2timestampRule, _l2timestampItem) + } + + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) + 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(L2OutputOracleL2OutputDeleted) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", 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 +} + +// ParseL2OutputDeleted is a log parse operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputDeleted(log types.Log) (*L2OutputOracleL2OutputDeleted, error) { + event := new(L2OutputOracleL2OutputDeleted) + if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} From 63e4bebf8f81c9078b0525ad8acd59ae53a41f8d Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 29 Apr 2022 01:43:17 +0200 Subject: [PATCH 515/585] opnode: add seq nr to l1-info to fix driver bug --- opnode/contracts/deposit/deposit_feed_raw.go | 2 +- .../l1block/l1_block_info_deployed.go | 2 +- opnode/contracts/l1block/l1_block_info_raw.go | 91 +++++++++++++------ opnode/eth/id.go | 11 ++- opnode/l2/source.go | 36 +++++--- opnode/rollup/derive/doc.go | 6 +- opnode/rollup/derive/invert.go | 58 ------------ opnode/rollup/derive/l1_block_info.go | 72 +++++++++++++++ .../{invert_test.go => l1_block_info_test.go} | 60 ++++++------ opnode/rollup/derive/payload_attributes.go | 38 ++++---- opnode/rollup/driver/state.go | 9 +- opnode/rollup/driver/step.go | 20 +++- opnode/rollup/sync/start.go | 2 +- opnode/test/system_test.go | 35 +++---- packages/contracts/.gas-snapshot | 9 +- packages/contracts/contracts/L2/L1Block.sol | 13 ++- .../contracts/contracts/test/L1Block.t.sol | 10 +- specs/deposits.md | 4 + 18 files changed, 282 insertions(+), 196 deletions(-) delete mode 100644 opnode/rollup/derive/invert.go create mode 100644 opnode/rollup/derive/l1_block_info.go rename opnode/rollup/derive/{invert_test.go => l1_block_info_test.go} (67%) diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/opnode/contracts/deposit/deposit_feed_raw.go index db95f79f9fe9..fa5b453b607c 100644 --- a/opnode/contracts/deposit/deposit_feed_raw.go +++ b/opnode/contracts/deposit/deposit_feed_raw.go @@ -39,7 +39,7 @@ type WithdrawalVerifierOutputRootProof struct { // OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. var OptimismPortalMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60c0604052600080546001600160a01b03191661dead17905534801561002457600080fd5b5060405162002322380380620023228339810160408190526100459161005b565b6001600160a01b0390911660a052608052610095565b6000806040838503121561006e57600080fd5b82516001600160a01b038116811461008557600080fd5b6020939093015192949293505050565b60805160a05161225a620000c86000396000818160a501526103500152600081816101a301526102c4015261225a6000f3fe6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015e578063eecf1c3614610171578063ff61cc931461019157600080fd5b80621c2ff6146100935780639bf62d82146100f1578063a14238e71461011e57600080fd5b3661008e5761008c33346175306000604051806020016040528060008152506101d3565b005b600080fd5b34801561009f57600080fd5b506100c77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fd57600080fd5b506000546100c79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012a57600080fd5b5061014e610139366004611c41565b60016020526000908152604090205460ff1681565b60405190151581526020016100e8565b61008c61016c366004611cb2565b6101d3565b34801561017d57600080fd5b5061008c61018c366004611e18565b6102c2565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e8565b8180156101f5575073ffffffffffffffffffffffffffffffffffffffff851615155b1561022c576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3332811461024d575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102b2959493929190611f18565b60405180910390a3505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000840142101561031e576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401602060405180830381865afa1580156103ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d09190611fb4565b9050610424846040805182356020828101919091528301358183015290820135606082810191909152820135608082015260009060a001604051602081830303815290604052805190602001209050919050565b811461045c576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046d8d8d8d8d8d8d8d610648565b905061047f818660400135868661068a565b6104b5576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff1615151415610504576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161059b929190611fcd565b600060405180830381858888f193505050503d80600081146105d9576040519150601f19603f3d011682016040523d82523d6000602084013e6105de565b606091505b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17815560405191925083917f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f9190a25050505050505050505050505050565b6000878787878787876040516020016106679796959493929190611fdd565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016106aa929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052925061077091016040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061077a915050565b9695505050505050565b60008061078686610794565b9050610770818686866107c6565b606081805190602001206040516020016107b091815260200190565b6040516020818303038152906040529050919050565b60008060006107d68786866107f7565b915091508180156107ec57506107ec86826108f1565b979650505050505050565b6000606060006108068561090d565b90506000806000610818848a89610a08565b8151929550909350915015808061082c5750815b610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064015b60405180910390fd5b6000816108b357604051806020016040528060008152506108df565b6108df866108c2600188612099565b815181106108d2576108d26120b0565b6020026020010151610f25565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b6060600061091a83610f4f565b90506000815167ffffffffffffffff81111561093857610938611c83565b60405190808252806020026020018201604052801561097d57816020015b60408051808201909152606080825260208201528152602001906001900390816109565790505b50905060005b8251811015610a005760006109b08483815181106109a3576109a36120b0565b6020026020010151610f82565b905060405180604001604052808281526020016109cc83610f4f565b8152508383815181106109e1576109e16120b0565b60200260200101819052505080806109f8906120df565b915050610983565b509392505050565b60006060818080610a188761102c565b90506000869050600080610a3f604051806040016040528060608152602001606081525090565b60005b8c51811015610ee1578c8181518110610a5d57610a5d6120b0565b602002602001015191508284610a739190612118565b9350610a80600188612118565b965083610afe57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f742068617368000000000000000000000000000000604482015260640161088e565b610bef565b815151602011610b7a57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161088e565b84610b8883600001516111af565b14610bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161088e565b610bfb60106001612118565b8260200151511415610c74578551841415610c1557610ee1565b6000868581518110610c2957610c296120b0565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c5457610c546120b0565b60200260200101519050610c67816111d7565b9650600194505050610ecf565b60028260200151511415610e6d576000610c8d83611214565b9050600081600081518110610ca457610ca46120b0565b016020015160f81c90506000610cbb60028361215f565b610cc6906002612181565b90506000610cd7848360ff16611238565b90506000610ce58b8a611238565b90506000610cf3838361126e565b905060ff851660021480610d0a575060ff85166003145b15610d6057808351148015610d1f5750808251145b15610d3157610d2e818b612118565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b60ff85161580610d73575060ff85166001145b15610de55782518114610daf57507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b610dd68860200151600181518110610dc957610dc96120b0565b60200260200101516111d7565b9a509750610ecf945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f7072656669780000000000000000000000000000000000000000000000000000606482015260840161088e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161088e565b80610ed9816120df565b915050610a42565b507f8000000000000000000000000000000000000000000000000000000000000000841486610f108786611238565b909e909d50909b509950505050505050505050565b6020810151805160609161090791610f3f90600190612099565b815181106109a3576109a36120b0565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906109079061131a565b60606000806000610f928561154d565b919450925090506000816001811115610fad57610fad6121a4565b14611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161088e565b61102385602001518484611954565b95945050505050565b606060008251600261103e91906121d3565b67ffffffffffffffff81111561105657611056611c83565b6040519080825280601f01601f191660200182016040528015611080576020820181803683370190505b50905060005b83518110156111a85760048482815181106110a3576110a36120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826110d88360026121d3565b815181106110e8576110e86120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061112b5761112b6120b0565b016020015161113d919060f81c61215f565b60f81b8261114c8360026121d3565b611157906001612118565b81518110611167576111676120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111a0816120df565b915050611086565b5092915050565b60006020825110156111c357506020015190565b818060200190518101906109079190611fb4565b600060606020836000015110156111f8576111f183611a33565b9050611204565b61120183610f82565b90505b61120d816111af565b9392505050565b606061090761123383602001516000815181106109a3576109a36120b0565b61102c565b6060825182106112575750604080516020810190915260008152610907565b61120d83838486516112699190612099565b611a3e565b6000805b8084511180156112825750808351115b8015611303575082818151811061129b5761129b6120b0565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112da576112da6120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561120d5780611312816120df565b915050611272565b60606000806113288461154d565b91935090915060019050816001811115611344576113446121a4565b146113ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161088e565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816113c45790505090506000835b8651811015611542576020821061148a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161088e565b6000806114c76040518060400160405280858c600001516114ab9190612099565b8152602001858c602001516114c09190612118565b905261154d565b5091509150604051806040016040528083836114e39190612118565b8152602001848b602001516114f89190612118565b81525085858151811061150d5761150d6120b0565b6020908102919091010152611523600185612118565b935061152f8183612118565b6115399084612118565b925050506113f1565b508152949350505050565b6000806000808460000151116115bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161088e565b6020840151805160001a607f81116115e457600060016000945094509450505061194d565b60b7811161167a5760006115f9608083612099565b905080876000015111611668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161088e565b6001955093506000925061194d915050565b60bf811161179d57600061168f60b783612099565b9050808760000151116116fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161088e565b600183015160208290036101000a90046117188183612118565b885111611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161088e565b61178c826001612118565b965094506000935061194d92505050565b60f781116118325760006117b260c083612099565b905080876000015111611821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161088e565b60019550935084925061194d915050565b600061183f60f783612099565b9050808760000151116118ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161088e565b600183015160208290036101000a90046118c88183612118565b885111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161088e565b61193c826001612118565b965094506001935061194d92505050565b9193909250565b606060008267ffffffffffffffff81111561197157611971611c83565b6040519080825280601f01601f19166020018201604052801561199b576020820181803683370190505b5090508051600014156119af57905061120d565b60006119bb8587612118565b90506020820160005b6119cf602087612210565b811015611a0657825182526119e5602084612118565b92506119f2602083612118565b9150806119fe816120df565b9150506119c4565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061090782611c2b565b606081611a4c81601f612118565b1015611ab4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b82611abf8382612118565b1015611b27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b611b318284612118565b84511015611b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161088e565b606082158015611bba5760405191506000825260208201604052611c22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bf3578051835260209283019201611bdb565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610907826020015160008460000151611954565b600060208284031215611c5357600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c7e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a08688031215611cca57600080fd5b611cd386611c5a565b945060208601359350604086013567ffffffffffffffff8082168214611cf857600080fd5b9093506060870135908115158214611d0f57600080fd5b90925060808701359080821115611d2557600080fd5b818801915088601f830112611d3957600080fd5b813581811115611d4b57611d4b611c83565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611d9157611d91611c83565b816040528281528b6020848701011115611daa57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b60008083601f840112611de157600080fd5b50813567ffffffffffffffff811115611df957600080fd5b602083019150836020828501011115611e1157600080fd5b9250929050565b60008060008060008060008060008060006101808c8e031215611e3a57600080fd5b8b359a50611e4a60208d01611c5a565b9950611e5860408d01611c5a565b985060608c0135975060808c0135965067ffffffffffffffff60a08d01351115611e8157600080fd5b611e918d60a08e01358e01611dcf565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215611ecf57600080fd5b60e08c01925067ffffffffffffffff6101608d01351115611eef57600080fd5b611f008d6101608e01358e01611dcf565b81935080925050509295989b509295989b9093969950565b85815260006020868184015267ffffffffffffffff86166040840152841515606084015260a0608084015283518060a085015260005b81811015611f6a5785810183015185820160c001528201611f4e565b81811115611f7c57600060c083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160c001979650505050505050565b600060208284031215611fc657600080fd5b5051919050565b8183823760009101908152919050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015284608083015260c060a08301528260c0830152828460e0840137600060e0848401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121115761211161206a565b5060010190565b6000821982111561212b5761212b61206a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061217257612172612130565b8060ff84160691505092915050565b600060ff821660ff84168082101561219b5761219b61206a565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561220b5761220b61206a565b500290565b60008261221f5761221f612130565b50049056fea26469706673582212208ef4bb38bdf36297a0a7fcd07a53d184d13074b51bfd01186b4075762eec487364736f6c634300080a0033", + Bin: "0x60c0604052600080546001600160a01b03191661dead17905534801561002457600080fd5b50604051620022f9380380620022f98339810160408190526100459161005b565b6001600160a01b0390911660a052608052610095565b6000806040838503121561006e57600080fd5b82516001600160a01b038116811461008557600080fd5b6020939093015192949293505050565b60805160a051612231620000c86000396000818160a501526103500152600081816101a301526102c401526122316000f3fe6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015e578063eecf1c3614610171578063ff61cc931461019157600080fd5b80621c2ff6146100935780639bf62d82146100f1578063a14238e71461011e57600080fd5b3661008e5761008c33346175306000604051806020016040528060008152506101d3565b005b600080fd5b34801561009f57600080fd5b506100c77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fd57600080fd5b506000546100c79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012a57600080fd5b5061014e610139366004611c41565b60016020526000908152604090205460ff1681565b60405190151581526020016100e8565b61008c61016c366004611cb2565b6101d3565b34801561017d57600080fd5b5061008c61018c366004611e18565b6102c2565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e8565b8180156101f5575073ffffffffffffffffffffffffffffffffffffffff851615155b1561022c576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3332811461024d575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102b2959493929190611f18565b60405180910390a3505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000840142101561031e576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401602060405180830381865afa1580156103ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d09190611fb4565b9050610424846040805182356020828101919091528301358183015290820135606082810191909152820135608082015260009060a001604051602081830303815290604052805190602001209050919050565b811461045c576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046d8d8d8d8d8d8d8d610648565b905061047f818660400135868661068a565b6104b5576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff1615151415610504576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161059b929190611fcd565b600060405180830381858888f193505050503d80600081146105d9576040519150601f19603f3d011682016040523d82523d6000602084013e6105de565b606091505b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17815560405191925083917f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f9190a25050505050505050505050505050565b6000878787878787876040516020016106679796959493929190611fdd565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016106aa929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052925061077091016040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061077a915050565b9695505050505050565b60008061078686610794565b9050610770818686866107c6565b606081805190602001206040516020016107b091815260200190565b6040516020818303038152906040529050919050565b60008060006107d68786866107f7565b915091508180156107ec57506107ec86826108f1565b979650505050505050565b6000606060006108068561090d565b90506000806000610818848a89610a08565b8151929550909350915015808061082c5750815b610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064015b60405180910390fd5b6000816108b357604051806020016040528060008152506108df565b6108df866108c2600188612099565b815181106108d2576108d26120b0565b6020026020010151610f25565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b6060600061091a83610f4f565b90506000815167ffffffffffffffff81111561093857610938611c83565b60405190808252806020026020018201604052801561097d57816020015b60408051808201909152606080825260208201528152602001906001900390816109565790505b50905060005b8251811015610a005760006109b08483815181106109a3576109a36120b0565b6020026020010151610f82565b905060405180604001604052808281526020016109cc83610f4f565b8152508383815181106109e1576109e16120b0565b60200260200101819052505080806109f8906120df565b915050610983565b509392505050565b60006060818080610a188761102c565b90506000869050600080610a3f604051806040016040528060608152602001606081525090565b60005b8c51811015610ee1578c8181518110610a5d57610a5d6120b0565b602002602001015191508284610a739190612118565b9350610a80600188612118565b965083610afe57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f742068617368000000000000000000000000000000604482015260640161088e565b610bef565b815151602011610b7a57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161088e565b84610b8883600001516111af565b14610bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161088e565b610bfb60106001612118565b8260200151511415610c74578551841415610c1557610ee1565b6000868581518110610c2957610c296120b0565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c5457610c546120b0565b60200260200101519050610c67816111d7565b9650600194505050610ecf565b60028260200151511415610e6d576000610c8d83611214565b9050600081600081518110610ca457610ca46120b0565b016020015160f81c90506000610cbb60028361215f565b610cc6906002612181565b90506000610cd7848360ff16611238565b90506000610ce58b8a611238565b90506000610cf3838361126e565b905060ff851660021480610d0a575060ff85166003145b15610d6057808351148015610d1f5750808251145b15610d3157610d2e818b612118565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b60ff85161580610d73575060ff85166001145b15610de55782518114610daf57507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b610dd68860200151600181518110610dc957610dc96120b0565b60200260200101516111d7565b9a509750610ecf945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f7072656669780000000000000000000000000000000000000000000000000000606482015260840161088e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161088e565b80610ed9816120df565b915050610a42565b507f8000000000000000000000000000000000000000000000000000000000000000841486610f108786611238565b909e909d50909b509950505050505050505050565b6020810151805160609161090791610f3f90600190612099565b815181106109a3576109a36120b0565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906109079061131a565b60606000806000610f928561154d565b919450925090506000816001811115610fad57610fad6121a4565b14611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161088e565b61102385602001518484611954565b95945050505050565b606060008251600261103e91906121d3565b67ffffffffffffffff81111561105657611056611c83565b6040519080825280601f01601f191660200182016040528015611080576020820181803683370190505b50905060005b83518110156111a85760048482815181106110a3576110a36120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826110d88360026121d3565b815181106110e8576110e86120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061112b5761112b6120b0565b016020015161113d919060f81c61215f565b60f81b8261114c8360026121d3565b611157906001612118565b81518110611167576111676120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111a0816120df565b915050611086565b5092915050565b60006020825110156111c357506020015190565b818060200190518101906109079190611fb4565b600060606020836000015110156111f8576111f183611a33565b9050611204565b61120183610f82565b90505b61120d816111af565b9392505050565b606061090761123383602001516000815181106109a3576109a36120b0565b61102c565b6060825182106112575750604080516020810190915260008152610907565b61120d83838486516112699190612099565b611a3e565b6000805b8084511180156112825750808351115b8015611303575082818151811061129b5761129b6120b0565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112da576112da6120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561120d5780611312816120df565b915050611272565b60606000806113288461154d565b91935090915060019050816001811115611344576113446121a4565b146113ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161088e565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816113c45790505090506000835b8651811015611542576020821061148a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161088e565b6000806114c76040518060400160405280858c600001516114ab9190612099565b8152602001858c602001516114c09190612118565b905261154d565b5091509150604051806040016040528083836114e39190612118565b8152602001848b602001516114f89190612118565b81525085858151811061150d5761150d6120b0565b6020908102919091010152611523600185612118565b935061152f8183612118565b6115399084612118565b925050506113f1565b508152949350505050565b6000806000808460000151116115bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161088e565b6020840151805160001a607f81116115e457600060016000945094509450505061194d565b60b7811161167a5760006115f9608083612099565b905080876000015111611668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161088e565b6001955093506000925061194d915050565b60bf811161179d57600061168f60b783612099565b9050808760000151116116fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161088e565b600183015160208290036101000a90046117188183612118565b885111611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161088e565b61178c826001612118565b965094506000935061194d92505050565b60f781116118325760006117b260c083612099565b905080876000015111611821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161088e565b60019550935084925061194d915050565b600061183f60f783612099565b9050808760000151116118ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161088e565b600183015160208290036101000a90046118c88183612118565b885111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161088e565b61193c826001612118565b965094506001935061194d92505050565b9193909250565b606060008267ffffffffffffffff81111561197157611971611c83565b6040519080825280601f01601f19166020018201604052801561199b576020820181803683370190505b5090508051600014156119af57905061120d565b60006119bb8587612118565b90506020820160005b6119cf602087612210565b811015611a0657825182526119e5602084612118565b92506119f2602083612118565b9150806119fe816120df565b9150506119c4565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061090782611c2b565b606081611a4c81601f612118565b1015611ab4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b82611abf8382612118565b1015611b27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b611b318284612118565b84511015611b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161088e565b606082158015611bba5760405191506000825260208201604052611c22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bf3578051835260209283019201611bdb565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610907826020015160008460000151611954565b600060208284031215611c5357600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c7e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a08688031215611cca57600080fd5b611cd386611c5a565b945060208601359350604086013567ffffffffffffffff8082168214611cf857600080fd5b9093506060870135908115158214611d0f57600080fd5b90925060808701359080821115611d2557600080fd5b818801915088601f830112611d3957600080fd5b813581811115611d4b57611d4b611c83565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611d9157611d91611c83565b816040528281528b6020848701011115611daa57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b60008083601f840112611de157600080fd5b50813567ffffffffffffffff811115611df957600080fd5b602083019150836020828501011115611e1157600080fd5b9250929050565b60008060008060008060008060008060006101808c8e031215611e3a57600080fd5b8b359a50611e4a60208d01611c5a565b9950611e5860408d01611c5a565b985060608c0135975060808c0135965067ffffffffffffffff60a08d01351115611e8157600080fd5b611e918d60a08e01358e01611dcf565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215611ecf57600080fd5b60e08c01925067ffffffffffffffff6101608d01351115611eef57600080fd5b611f008d6101608e01358e01611dcf565b81935080925050509295989b509295989b9093969950565b85815260006020868184015267ffffffffffffffff86166040840152841515606084015260a0608084015283518060a085015260005b81811015611f6a5785810183015185820160c001528201611f4e565b81811115611f7c57600060c083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160c001979650505050505050565b600060208284031215611fc657600080fd5b5051919050565b8183823760009101908152919050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015284608083015260c060a08301528260c0830152828460e0840137600060e0848401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121115761211161206a565b5060010190565b6000821982111561212b5761212b61206a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061217257612172612130565b8060ff84160691505092915050565b600060ff821660ff84168082101561219b5761219b61206a565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561220b5761220b61206a565b500290565b60008261221f5761221f612130565b50049056fea164736f6c634300080a000a", } // OptimismPortalABI is the input ABI used to generate the binding from. diff --git a/opnode/contracts/l1block/l1_block_info_deployed.go b/opnode/contracts/l1block/l1_block_info_deployed.go index 2725a8109177..59522deb3ea6 100644 --- a/opnode/contracts/l1block/l1_block_info_deployed.go +++ b/opnode/contracts/l1block/l1_block_info_deployed.go @@ -2,4 +2,4 @@ // This file is a generated binding and any manual changes will be lost. package l1block -var L1blockDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063b80777ea11610050578063b80777ea146100a5578063c03ba43e146100ae578063e591b282146100c357600080fd5b806309bd5a60146100775780635cf24969146100935780638381f58a1461009c575b600080fd5b61008060035481565b6040519081526020015b60405180910390f35b61008060025481565b61008060005481565b61008060015481565b6100c16100bc366004610164565b610103565b005b6100de73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008a565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610150576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600093909355600191909155600255600355565b6000806000806080858703121561017a57600080fd5b505082359460208401359450604084013593606001359250905056fea26469706673582212202030f0b19d5ff0b7a5d094d184635f40535b3dd5b50e391125e80dcd7c4dfb1564736f6c634300080a0033" +var L1blockDeployedBin = "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c806364ca23ef1161005b57806364ca23ef146100bc5780638381f58a146100e9578063b80777ea146100fd578063e591b2821461011d57600080fd5b8063042c2f571461008257806309bd5a60146100975780635cf24969146100b3575b600080fd5b61009561009036600461024c565b61015d565b005b6100a060025481565b6040519081526020015b60405180910390f35b6100a060015481565b6003546100d09067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100aa565b6000546100d09067ffffffffffffffff1681565b6000546100d09068010000000000000000900467ffffffffffffffff1681565b61013873deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100aa565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805467ffffffffffffffff9687167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090911617680100000000000000009587169590950294909417909355600191909155600255600380547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909216179055565b803567ffffffffffffffff8116811461024757600080fd5b919050565b600080600080600060a0868803121561026457600080fd5b61026d8661022f565b945061027b6020870161022f565b935060408601359250606086013591506102976080870161022f565b9050929550929590935056fea164736f6c634300080a000a" diff --git a/opnode/contracts/l1block/l1_block_info_raw.go b/opnode/contracts/l1block/l1_block_info_raw.go index 6073023f86de..964b3c428ad5 100644 --- a/opnode/contracts/l1block/l1_block_info_raw.go +++ b/opnode/contracts/l1block/l1_block_info_raw.go @@ -30,8 +30,8 @@ var ( // L1BlockMetaData contains all meta data concerning the L1Block contract. var L1BlockMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506101cc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063b80777ea11610050578063b80777ea146100a5578063c03ba43e146100ae578063e591b282146100c357600080fd5b806309bd5a60146100775780635cf24969146100935780638381f58a1461009c575b600080fd5b61008060035481565b6040519081526020015b60405180910390f35b61008060025481565b61008060005481565b61008060015481565b6100c16100bc366004610164565b610103565b005b6100de73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008a565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610150576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600093909355600191909155600255600355565b6000806000806080858703121561017a57600080fd5b505082359460208401359450604084013593606001359250905056fea26469706673582212202030f0b19d5ff0b7a5d094d184635f40535b3dd5b50e391125e80dcd7c4dfb1564736f6c634300080a0033", + ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"_timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506102b0806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806364ca23ef1161005b57806364ca23ef146100bc5780638381f58a146100e9578063b80777ea146100fd578063e591b2821461011d57600080fd5b8063042c2f571461008257806309bd5a60146100975780635cf24969146100b3575b600080fd5b61009561009036600461024c565b61015d565b005b6100a060025481565b6040519081526020015b60405180910390f35b6100a060015481565b6003546100d09067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100aa565b6000546100d09067ffffffffffffffff1681565b6000546100d09068010000000000000000900467ffffffffffffffff1681565b61013873deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100aa565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146101aa576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805467ffffffffffffffff9687167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090911617680100000000000000009587169590950294909417909355600191909155600255600380547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909216179055565b803567ffffffffffffffff8116811461024757600080fd5b919050565b600080600080600060a0868803121561026457600080fd5b61026d8661022f565b945061027b6020870161022f565b935060408601359250606086013591506102976080870161022f565b9050929550929590935056fea164736f6c634300080a000a", } // L1BlockABI is the input ABI used to generate the binding from. @@ -296,16 +296,16 @@ func (_L1Block *L1BlockCallerSession) Hash() ([32]byte, error) { // Number is a free data retrieval call binding the contract method 0x8381f58a. // -// Solidity: function number() view returns(uint256) -func (_L1Block *L1BlockCaller) Number(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function number() view returns(uint64) +func (_L1Block *L1BlockCaller) Number(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L1Block.contract.Call(opts, &out, "number") if err != nil { - return *new(*big.Int), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -313,30 +313,61 @@ func (_L1Block *L1BlockCaller) Number(opts *bind.CallOpts) (*big.Int, error) { // Number is a free data retrieval call binding the contract method 0x8381f58a. // -// Solidity: function number() view returns(uint256) -func (_L1Block *L1BlockSession) Number() (*big.Int, error) { +// Solidity: function number() view returns(uint64) +func (_L1Block *L1BlockSession) Number() (uint64, error) { return _L1Block.Contract.Number(&_L1Block.CallOpts) } // Number is a free data retrieval call binding the contract method 0x8381f58a. // -// Solidity: function number() view returns(uint256) -func (_L1Block *L1BlockCallerSession) Number() (*big.Int, error) { +// Solidity: function number() view returns(uint64) +func (_L1Block *L1BlockCallerSession) Number() (uint64, error) { return _L1Block.Contract.Number(&_L1Block.CallOpts) } +// SequenceNumber is a free data retrieval call binding the contract method 0x64ca23ef. +// +// Solidity: function sequenceNumber() view returns(uint64) +func (_L1Block *L1BlockCaller) SequenceNumber(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _L1Block.contract.Call(opts, &out, "sequenceNumber") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// SequenceNumber is a free data retrieval call binding the contract method 0x64ca23ef. +// +// Solidity: function sequenceNumber() view returns(uint64) +func (_L1Block *L1BlockSession) SequenceNumber() (uint64, error) { + return _L1Block.Contract.SequenceNumber(&_L1Block.CallOpts) +} + +// SequenceNumber is a free data retrieval call binding the contract method 0x64ca23ef. +// +// Solidity: function sequenceNumber() view returns(uint64) +func (_L1Block *L1BlockCallerSession) SequenceNumber() (uint64, error) { + return _L1Block.Contract.SequenceNumber(&_L1Block.CallOpts) +} + // Timestamp is a free data retrieval call binding the contract method 0xb80777ea. // -// Solidity: function timestamp() view returns(uint256) -func (_L1Block *L1BlockCaller) Timestamp(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function timestamp() view returns(uint64) +func (_L1Block *L1BlockCaller) Timestamp(opts *bind.CallOpts) (uint64, error) { var out []interface{} err := _L1Block.contract.Call(opts, &out, "timestamp") if err != nil { - return *new(*big.Int), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err @@ -344,35 +375,35 @@ func (_L1Block *L1BlockCaller) Timestamp(opts *bind.CallOpts) (*big.Int, error) // Timestamp is a free data retrieval call binding the contract method 0xb80777ea. // -// Solidity: function timestamp() view returns(uint256) -func (_L1Block *L1BlockSession) Timestamp() (*big.Int, error) { +// Solidity: function timestamp() view returns(uint64) +func (_L1Block *L1BlockSession) Timestamp() (uint64, error) { return _L1Block.Contract.Timestamp(&_L1Block.CallOpts) } // Timestamp is a free data retrieval call binding the contract method 0xb80777ea. // -// Solidity: function timestamp() view returns(uint256) -func (_L1Block *L1BlockCallerSession) Timestamp() (*big.Int, error) { +// Solidity: function timestamp() view returns(uint64) +func (_L1Block *L1BlockCallerSession) Timestamp() (uint64, error) { return _L1Block.Contract.Timestamp(&_L1Block.CallOpts) } -// SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. +// SetL1BlockValues is a paid mutator transaction binding the contract method 0x042c2f57. // -// Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() -func (_L1Block *L1BlockTransactor) SetL1BlockValues(opts *bind.TransactOpts, _number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { - return _L1Block.contract.Transact(opts, "setL1BlockValues", _number, _timestamp, _basefee, _hash) +// Solidity: function setL1BlockValues(uint64 _number, uint64 _timestamp, uint256 _basefee, bytes32 _hash, uint64 _sequenceNumber) returns() +func (_L1Block *L1BlockTransactor) SetL1BlockValues(opts *bind.TransactOpts, _number uint64, _timestamp uint64, _basefee *big.Int, _hash [32]byte, _sequenceNumber uint64) (*types.Transaction, error) { + return _L1Block.contract.Transact(opts, "setL1BlockValues", _number, _timestamp, _basefee, _hash, _sequenceNumber) } -// SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. +// SetL1BlockValues is a paid mutator transaction binding the contract method 0x042c2f57. // -// Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() -func (_L1Block *L1BlockSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { - return _L1Block.Contract.SetL1BlockValues(&_L1Block.TransactOpts, _number, _timestamp, _basefee, _hash) +// Solidity: function setL1BlockValues(uint64 _number, uint64 _timestamp, uint256 _basefee, bytes32 _hash, uint64 _sequenceNumber) returns() +func (_L1Block *L1BlockSession) SetL1BlockValues(_number uint64, _timestamp uint64, _basefee *big.Int, _hash [32]byte, _sequenceNumber uint64) (*types.Transaction, error) { + return _L1Block.Contract.SetL1BlockValues(&_L1Block.TransactOpts, _number, _timestamp, _basefee, _hash, _sequenceNumber) } -// SetL1BlockValues is a paid mutator transaction binding the contract method 0xc03ba43e. +// SetL1BlockValues is a paid mutator transaction binding the contract method 0x042c2f57. // -// Solidity: function setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) returns() -func (_L1Block *L1BlockTransactorSession) SetL1BlockValues(_number *big.Int, _timestamp *big.Int, _basefee *big.Int, _hash [32]byte) (*types.Transaction, error) { - return _L1Block.Contract.SetL1BlockValues(&_L1Block.TransactOpts, _number, _timestamp, _basefee, _hash) +// Solidity: function setL1BlockValues(uint64 _number, uint64 _timestamp, uint256 _basefee, bytes32 _hash, uint64 _sequenceNumber) returns() +func (_L1Block *L1BlockTransactorSession) SetL1BlockValues(_number uint64, _timestamp uint64, _basefee *big.Int, _hash [32]byte, _sequenceNumber uint64) (*types.Transaction, error) { + return _L1Block.Contract.SetL1BlockValues(&_L1Block.TransactOpts, _number, _timestamp, _basefee, _hash, _sequenceNumber) } diff --git a/opnode/eth/id.go b/opnode/eth/id.go index eb1707f585ce..6a159edf1280 100644 --- a/opnode/eth/id.go +++ b/opnode/eth/id.go @@ -22,11 +22,12 @@ func (id BlockID) TerminalString() string { } type L2BlockRef struct { - Hash common.Hash `json:"hash"` - Number uint64 `json:"number"` - ParentHash common.Hash `json:"parentHash"` - Time uint64 `json:"timestamp"` - L1Origin BlockID `json:"l1origin"` + Hash common.Hash `json:"hash"` + Number uint64 `json:"number"` + ParentHash common.Hash `json:"parentHash"` + Time uint64 `json:"timestamp"` + L1Origin BlockID `json:"l1origin"` + SequenceNumber uint64 `json:"sequenceNumber"` // distance to first block of epoch } func (id L2BlockRef) String() string { diff --git a/opnode/l2/source.go b/opnode/l2/source.go index 96fc4a0fa199..39147ce55437 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -182,11 +182,13 @@ func (s *Source) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth. // falling back to genesis information if necessary. func blockToBlockRef(block *types.Block, genesis *rollup.Genesis) (eth.L2BlockRef, error) { var l1Origin eth.BlockID + var sequenceNumber uint64 if block.NumberU64() == genesis.L2.Number { if block.Hash() != genesis.L2.Hash { return eth.L2BlockRef{}, fmt.Errorf("expected L2 genesis hash to match L2 block at genesis block number %d: %s <> %s", genesis.L2.Number, block.Hash(), genesis.L2.Hash) } l1Origin = genesis.L1 + sequenceNumber = 0 } else { txs := block.Transactions() if len(txs) == 0 { @@ -196,18 +198,20 @@ func blockToBlockRef(block *types.Block, genesis *rollup.Genesis) (eth.L2BlockRe if tx.Type() != types.DepositTxType { return eth.L2BlockRef{}, fmt.Errorf("first block tx has unexpected tx type: %d", tx.Type()) } - l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) + info, err := derive.L1InfoDepositTxData(tx.Data()) if err != nil { return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) } - l1Origin = eth.BlockID{Hash: l1Hash, Number: l1Number} + l1Origin = eth.BlockID{Hash: info.BlockHash, Number: info.Number} + sequenceNumber = info.SequenceNumber } return eth.L2BlockRef{ - Hash: block.Hash(), - Number: block.NumberU64(), - ParentHash: block.ParentHash(), - Time: block.Time(), - L1Origin: l1Origin, + Hash: block.Hash(), + Number: block.NumberU64(), + ParentHash: block.ParentHash(), + Time: block.Time(), + L1Origin: l1Origin, + SequenceNumber: sequenceNumber, }, nil } @@ -215,11 +219,13 @@ func blockToBlockRef(block *types.Block, genesis *rollup.Genesis) (eth.L2BlockRe // falling back to genesis information if necessary. func PayloadToBlockRef(payload *ExecutionPayload, genesis *rollup.Genesis) (eth.L2BlockRef, error) { var l1Origin eth.BlockID + var sequenceNumber uint64 if uint64(payload.BlockNumber) == genesis.L2.Number { if payload.BlockHash != genesis.L2.Hash { return eth.L2BlockRef{}, fmt.Errorf("expected L2 genesis hash to match L2 block at genesis block number %d: %s <> %s", genesis.L2.Number, payload.BlockHash, genesis.L2.Hash) } l1Origin = genesis.L1 + sequenceNumber = 0 } else { if len(payload.Transactions) == 0 { return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", payload.BlockHash) @@ -231,18 +237,20 @@ func PayloadToBlockRef(payload *ExecutionPayload, genesis *rollup.Genesis) (eth. if tx.Type() != types.DepositTxType { return eth.L2BlockRef{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type()) } - l1Number, _, _, l1Hash, err := derive.L1InfoDepositTxData(tx.Data()) + info, err := derive.L1InfoDepositTxData(tx.Data()) if err != nil { return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %v", err) } - l1Origin = eth.BlockID{Hash: l1Hash, Number: l1Number} + l1Origin = eth.BlockID{Hash: info.BlockHash, Number: info.Number} + sequenceNumber = info.SequenceNumber } return eth.L2BlockRef{ - Hash: payload.BlockHash, - Number: uint64(payload.BlockNumber), - ParentHash: payload.ParentHash, - Time: uint64(payload.Timestamp), - L1Origin: l1Origin, + Hash: payload.BlockHash, + Number: uint64(payload.BlockNumber), + ParentHash: payload.ParentHash, + Time: uint64(payload.Timestamp), + L1Origin: l1Origin, + SequenceNumber: sequenceNumber, }, nil } diff --git a/opnode/rollup/derive/doc.go b/opnode/rollup/derive/doc.go index e8bdb6999700..4c03584371fe 100644 --- a/opnode/rollup/derive/doc.go +++ b/opnode/rollup/derive/doc.go @@ -3,11 +3,11 @@ // turned back into L1 data. // // The flow is data is as follows -// receipts -> l2.PayloadAttributes with `payload_attributes.go` +// receipts, batches -> l2.PayloadAttributes with `payload_attributes.go` // l2.PayloadAttributes -> l2.ExecutionPayload with `execution_payload.go` -// L2 block -> Corresponding L1 block with `invert.go` +// L2 block -> Corresponding L1 block info with `l1_block_info.go` // -// The Payload Atrribute derivation stage is a pure function. +// The Payload Attributes derivation stage is a pure function. // The Execution Payload derivation stage relies on the L2 execution engine to perform the // state update. // The inversion step is a pure function. diff --git a/opnode/rollup/derive/invert.go b/opnode/rollup/derive/invert.go deleted file mode 100644 index 1b69bcfdc8d0..000000000000 --- a/opnode/rollup/derive/invert.go +++ /dev/null @@ -1,58 +0,0 @@ -package derive - -import ( - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" -) - -// setL1BlockValues(uint256 _number, uint256 _timestamp, uint256 _basefee, bytes32 _hash) -type L1BlockInfo struct { - Number uint64 - Time uint64 - BaseFee *big.Int - BlockHash common.Hash -} - -// L1InfoDepositTxData is the inverse of L1InfoDeposit, to see where the L2 chain is derived from -func L1InfoDepositTxData(data []byte) (nr uint64, time uint64, baseFee *big.Int, blockHash common.Hash, err error) { - info, err := L1InfoDepositTxDataToStruct(data) - return info.Number, info.Time, info.BaseFee, info.BlockHash, err -} - -// L1InfoDepositTxDataToStruct is the inverse of L1InfoDeposit, to see where the L2 chain is derived from -func L1InfoDepositTxDataToStruct(data []byte) (L1BlockInfo, error) { - out := L1BlockInfo{} - if len(data) != 4+32+32+32+32 { - return out, fmt.Errorf("data is unexpected length: %d", len(data)) - } - - // Number - offset := 4 // Selector hash. Should check - number := new(big.Int) - number.SetBytes(data[offset : offset+32]) - if !number.IsUint64() { - return L1BlockInfo{}, errors.New("number does not fit in uint64") - } - out.Number = number.Uint64() - - // Timestamp - offset += 32 - timestamp := new(big.Int) - timestamp.SetBytes(data[offset : offset+32]) - if !timestamp.IsUint64() { - return L1BlockInfo{}, errors.New("timestamp does not fit in uint64") - } - out.Time = timestamp.Uint64() - - // BaseFee - offset += 32 - out.BaseFee = new(big.Int).SetBytes(data[offset : offset+32]) - - // Hash - offset += 32 - out.BlockHash.SetBytes(data[offset : offset+32]) - return out, nil -} diff --git a/opnode/rollup/derive/l1_block_info.go b/opnode/rollup/derive/l1_block_info.go new file mode 100644 index 000000000000..ae0de6e03ff9 --- /dev/null +++ b/opnode/rollup/derive/l1_block_info.go @@ -0,0 +1,72 @@ +package derive + +import ( + "bytes" + "encoding/binary" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +// L1BlockInfo presents the information stored in a L1Block.setL1BlockValues call +type L1BlockInfo struct { + Number uint64 + Time uint64 + BaseFee *big.Int + BlockHash common.Hash + // Not strictly a piece of L1 information. Represents the number of L2 blocks since the start of the epoch, + // i.e. when the actual L1 info was first introduced. + SequenceNumber uint64 +} + +func (info *L1BlockInfo) MarshalBinary() ([]byte, error) { + data := make([]byte, 4+32+32+32+32+32) + offset := 0 + copy(data[offset:4], L1InfoFuncBytes4) + offset += 4 + binary.BigEndian.PutUint64(data[offset+24:offset+32], info.Number) + offset += 32 + binary.BigEndian.PutUint64(data[offset+24:offset+32], info.Time) + offset += 32 + info.BaseFee.FillBytes(data[offset : offset+32]) + offset += 32 + copy(data[offset:offset+32], info.BlockHash.Bytes()) + offset += 32 + binary.BigEndian.PutUint64(data[offset+24:offset+32], info.SequenceNumber) + return data, nil +} + +func (info *L1BlockInfo) UnmarshalBinary(data []byte) error { + if len(data) != 4+32+32+32+32+32 { + return fmt.Errorf("data is unexpected length: %d", len(data)) + } + var padding [24]byte + offset := 4 + info.Number = binary.BigEndian.Uint64(data[offset+24 : offset+32]) + if !bytes.Equal(data[offset:offset+24], padding[:]) { + return fmt.Errorf("l1 info number exceeds uint64 bounds: %x", data[offset:offset+32]) + } + offset += 32 + info.Time = binary.BigEndian.Uint64(data[offset+24 : offset+32]) + if !bytes.Equal(data[offset:offset+24], padding[:]) { + return fmt.Errorf("l1 info time exceeds uint64 bounds: %x", data[offset:offset+32]) + } + offset += 32 + info.BaseFee = new(big.Int).SetBytes(data[offset : offset+32]) + offset += 32 + info.BlockHash.SetBytes(data[offset : offset+32]) + offset += 32 + info.SequenceNumber = binary.BigEndian.Uint64(data[offset+24 : offset+32]) + if !bytes.Equal(data[offset:offset+24], padding[:]) { + return fmt.Errorf("l1 info sequence number exceeds uint64 bounds: %x", data[offset:offset+32]) + } + return nil +} + +// L1InfoDepositTxData is the inverse of L1InfoDeposit, to see where the L2 chain is derived from +func L1InfoDepositTxData(data []byte) (L1BlockInfo, error) { + var info L1BlockInfo + err := info.UnmarshalBinary(data) + return info, err +} diff --git a/opnode/rollup/derive/invert_test.go b/opnode/rollup/derive/l1_block_info_test.go similarity index 67% rename from opnode/rollup/derive/invert_test.go rename to opnode/rollup/derive/l1_block_info_test.go index 9913da99c8d2..983ab31402f1 100644 --- a/opnode/rollup/derive/invert_test.go +++ b/opnode/rollup/derive/l1_block_info_test.go @@ -5,6 +5,8 @@ import ( "math/rand" "testing" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -14,14 +16,15 @@ import ( ) type l1MockInfo struct { - hash common.Hash - parentHash common.Hash - root common.Hash - num uint64 - time uint64 - mixDigest [32]byte - baseFee *big.Int - receiptRoot common.Hash + hash common.Hash + parentHash common.Hash + root common.Hash + num uint64 + time uint64 + mixDigest [32]byte + baseFee *big.Int + receiptRoot common.Hash + sequenceNumber uint64 } func (l *l1MockInfo) Hash() common.Hash { @@ -76,13 +79,14 @@ func randomHash(rng *rand.Rand) (out common.Hash) { func randomL1Info(rng *rand.Rand) *l1MockInfo { return &l1MockInfo{ - parentHash: randomHash(rng), - num: rng.Uint64(), - time: rng.Uint64(), - hash: randomHash(rng), - baseFee: big.NewInt(rng.Int63n(1000_000 * 1e9)), // a million GWEI - receiptRoot: types.EmptyRootHash, - root: randomHash(rng), + parentHash: randomHash(rng), + num: rng.Uint64(), + time: rng.Uint64(), + hash: randomHash(rng), + baseFee: big.NewInt(rng.Int63n(1000_000 * 1e9)), // a million GWEI + receiptRoot: types.EmptyRootHash, + root: randomHash(rng), + sequenceNumber: rng.Uint64(), } } @@ -118,6 +122,9 @@ func TestParseL1InfoDepositTxData(t *testing.T) { {"zero num", makeInfo(func(l *l1MockInfo) { l.num = 0 })}, + {"zero seq", makeInfo(func(l *l1MockInfo) { + l.sequenceNumber = 0 + })}, {"all zero", func(rng *rand.Rand) *l1MockInfo { return &l1MockInfo{baseFee: new(big.Int)} }}, @@ -125,26 +132,27 @@ func TestParseL1InfoDepositTxData(t *testing.T) { for i, testCase := range cases { t.Run(testCase.name, func(t *testing.T) { info := testCase.mkInfo(rand.New(rand.NewSource(int64(1234 + i)))) - depTx := L1InfoDeposit(123, info) - nr, time, baseFee, h, err := L1InfoDepositTxData(depTx.Data) - assert.NoError(t, err, "expected valid deposit info") - assert.Equal(t, nr, info.num) - assert.Equal(t, time, info.time) - assert.True(t, baseFee.Sign() >= 0) - assert.Equal(t, baseFee.Bytes(), info.baseFee.Bytes()) - assert.Equal(t, h, info.hash) + depTx, err := L1InfoDeposit(123, info) + require.NoError(t, err) + res, err := L1InfoDepositTxData(depTx.Data) + require.NoError(t, err, "expected valid deposit info") + assert.Equal(t, res.Number, info.num) + assert.Equal(t, res.Time, info.time) + assert.True(t, res.BaseFee.Sign() >= 0) + assert.Equal(t, res.BaseFee.Bytes(), info.baseFee.Bytes()) + assert.Equal(t, res.BlockHash, info.hash) }) } t.Run("no data", func(t *testing.T) { - _, _, _, _, err := L1InfoDepositTxData(nil) + _, err := L1InfoDepositTxData(nil) assert.Error(t, err) }) t.Run("not enough data", func(t *testing.T) { - _, _, _, _, err := L1InfoDepositTxData([]byte{1, 2, 3, 4}) + _, err := L1InfoDepositTxData([]byte{1, 2, 3, 4}) assert.Error(t, err) }) t.Run("too much data", func(t *testing.T) { - _, _, _, _, err := L1InfoDepositTxData(make([]byte, 4+8+8+32+32+1)) + _, err := L1InfoDepositTxData(make([]byte, 4+32+32+32+32+32+1)) assert.Error(t, err) }) } diff --git a/opnode/rollup/derive/payload_attributes.go b/opnode/rollup/derive/payload_attributes.go index 391dced298f0..e590cfab687e 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/opnode/rollup/derive/payload_attributes.go @@ -19,7 +19,7 @@ import ( var ( DepositEventABI = "TransactionDeposited(address,address,uint256,uint256,uint64,bool,bytes)" DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) - L1InfoFuncSignature = "setL1BlockValues(uint256,uint256,uint256,bytes32)" + L1InfoFuncSignature = "setL1BlockValues(uint64,uint64,uint256,bytes32,uint64)" L1InfoFuncBytes4 = crypto.Keccak256([]byte(L1InfoFuncSignature))[:4] L1InfoPredeployAddr = common.HexToAddress("0x4200000000000000000000000000000000000015") L1InfoDepositerAddress = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") @@ -170,20 +170,20 @@ type L1Info interface { ReceiptHash() common.Hash } -// L1InfoDeposit creats a L1 Info deposit transaction based on the L1 block, +// L1InfoDeposit creates a L1 Info deposit transaction based on the L1 block, // and the L2 block-height difference with the start of the epoch. -func L1InfoDeposit(seqNumber uint64, block L1Info) *types.DepositTx { - data := make([]byte, 4+32+32+32+32) - offset := 0 - copy(data[offset:4], L1InfoFuncBytes4) - offset += 4 - binary.BigEndian.PutUint64(data[offset+24:offset+32], block.NumberU64()) - offset += 32 - binary.BigEndian.PutUint64(data[offset+24:offset+32], block.Time()) - offset += 32 - block.BaseFee().FillBytes(data[offset : offset+32]) - offset += 32 - copy(data[offset:offset+32], block.Hash().Bytes()) +func L1InfoDeposit(seqNumber uint64, block L1Info) (*types.DepositTx, error) { + infoDat := L1BlockInfo{ + Number: block.NumberU64(), + Time: block.Time(), + BaseFee: block.BaseFee(), + BlockHash: block.Hash(), + SequenceNumber: seqNumber, + } + data, err := infoDat.MarshalBinary() + if err != nil { + return nil, err + } source := L1InfoDepositSource{ L1BlockHash: block.Hash(), @@ -198,7 +198,7 @@ func L1InfoDeposit(seqNumber uint64, block L1Info) *types.DepositTx { Value: big.NewInt(0), Gas: 99_999_999, Data: data, - } + }, nil } // UserDeposits transforms the L2 block-height and L1 receipts into the transaction inputs for a full L2 block @@ -336,10 +336,14 @@ func FillMissingBatches(batches []*BatchData, epoch, blockTime, minL2Time, nextL // L1InfoDepositBytes returns a serialized L1-info attributes transaction. func L1InfoDepositBytes(seqNumber uint64, l1Info L1Info) (hexutil.Bytes, error) { - l1Tx := types.NewTx(L1InfoDeposit(seqNumber, l1Info)) + dep, err := L1InfoDeposit(seqNumber, l1Info) + if err != nil { + return nil, fmt.Errorf("failed to create L1 info tx: %v", err) + } + l1Tx := types.NewTx(dep) opaqueL1Tx, err := l1Tx.MarshalBinary() if err != nil { - return nil, fmt.Errorf("failed to encode L1 info tx") + return nil, fmt.Errorf("failed to encode L1 info tx: %v", err) } return opaqueL1Tx, nil } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 474a278a90ee..8af5b2f6854f 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -84,10 +84,11 @@ func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error // TODO: Test this codepath. That requires setting up L1, letting it run, and then creating the L2 genesis from there. // Note: This will not work for setting the the genesis normally, but if the L1 node is not yet synced we could get this case. l2genesis := eth.L2BlockRef{ - Hash: s.Config.Genesis.L2.Hash, - Number: s.Config.Genesis.L2.Number, - Time: s.Config.Genesis.L2Time, - L1Origin: s.Config.Genesis.L1, + Hash: s.Config.Genesis.L2.Hash, + Number: s.Config.Genesis.L2.Number, + Time: s.Config.Genesis.L2Time, + L1Origin: s.Config.Genesis.L1, + SequenceNumber: 0, } s.l2Head = l2genesis s.l2SafeHead = l2genesis diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 85c153448a56..d81bb2627610 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -55,7 +55,7 @@ func lastDeposit(txns []l2.Data) (int, error) { } func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) { - d.log.Info("creating new block", "l2Head", l2Head) + d.log.Info("creating new block", "parent", l2Head, "l1Origin", l1Origin) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() @@ -64,11 +64,14 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, var receipts types.Receipts var err error + seqNumber := l2Head.SequenceNumber + 1 + // If the L1 origin changed this block, then we are in the first block of the epoch. In this // case we need to fetch all transaction receipts from the L1 origin block so we can scan for // user deposits. if l2Head.L1Origin.Number != l1Origin.Number { l1Info, _, receipts, err = d.dl.Fetch(fetchCtx, l1Origin.Hash) + seqNumber = 0 // reset sequence number at the start of the epoch } else { l1Info, err = d.dl.InfoByHash(fetchCtx, l1Origin.Hash) } @@ -80,7 +83,6 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, var txns []l2.Data // First transaction in every block is always the L1 info transaction. - seqNumber := l2Head.Number + 1 - l2SafeHead.Number l1InfoTx, err := derive.L1InfoDepositBytes(seqNumber, l1Info) if err != nil { return l2Head, nil, err @@ -154,8 +156,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S return l2Head, l2SafeHead, false, errors.New("invalid sequencing window size") } - logger := d.log.New("input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], "input_l2_parent", l2SafeHead, "finalized_l2", l2Finalized) - logger.Trace("Running update step on the L2 node") + d.log.Debug("inserting epoch", "input_l1_first", l1Input[0], "input_l1_last", l1Input[len(l1Input)-1], "input_l2_parent", l2SafeHead, "finalized_l2", l2Finalized) // Get inputs from L1 and L2 epoch := rollup.Epoch(l1Input[0].Number) @@ -231,11 +232,17 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S NoTxPool: true, } + d.log.Debug("inserting epoch batch", "safeHeadL1Origin", lastSafeHead.L1Origin, "l1Info", l1Info.ID(), "seqnr", i) + // We are either verifying blocks (with a potential for a reorg) or inserting a safe head to the chain if lastHead.Hash != lastSafeHead.Hash { + d.log.Debug("verifying derived attributes matches L2 block", + "lastHead", lastHead, "lastSafeHead", lastSafeHead, "epoch", epoch, + "lastSafeHead_l1origin", lastSafeHead.L1Origin, "lastHead_l1origin", lastHead.L1Origin) payload, reorg, err = d.verifySafeBlock(ctx, fc, attrs, lastSafeHead.ID()) } else { + d.log.Debug("inserting new batch after lastHead", "lastHead", lastHead.ID()) payload, _, err = d.insertHeadBlock(ctx, fc, attrs, true) } if err != nil { @@ -292,6 +299,11 @@ func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, if err != nil { return nil, false, fmt.Errorf("failed to get L2 block: %w", err) } + ref, err := l2.PayloadToBlockRef(payload, &d.Config.Genesis) + if err != nil { + return nil, false, fmt.Errorf("failed to parse block ref: %w", err) + } + d.log.Debug("verifySafeBlock", "parentl2", parent, "payload", payload.ID(), "payloadOrigin", ref.L1Origin, "payloadSeq", ref.SequenceNumber) err = attributesMatchBlock(attrs, parent.Hash, payload) if err != nil { // Have reorg diff --git a/opnode/rollup/sync/start.go b/opnode/rollup/sync/start.go index 7391c59070fc..636f9326848d 100644 --- a/opnode/rollup/sync/start.go +++ b/opnode/rollup/sync/start.go @@ -184,7 +184,7 @@ func FindL2Heads(ctx context.Context, start eth.L2BlockRef, seqWindowSize uint64 // Genesis is always safe. if n.Hash == genesis.L2.Hash || n.Number == genesis.L2.Number { safe = eth.L2BlockRef{Hash: genesis.L2.Hash, Number: genesis.L2.Number, - Time: genesis.L2Time, L1Origin: genesis.L1} + Time: genesis.L2Time, L1Origin: genesis.L1, SequenceNumber: 0} return highestPlausibleCanonicalOrigin, safe, nil } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 3811eb2b36bf..4071513a750a 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -2,7 +2,6 @@ package test import ( "context" - "errors" "flag" "fmt" "math/big" @@ -447,25 +446,15 @@ func L1InfoFromState(ctx context.Context, contract *l1block.L1Block, l2Number *b Context: ctx, } - number, err := contract.Number(&opts) + out.Number, err = contract.Number(&opts) if err != nil { return derive.L1BlockInfo{}, fmt.Errorf("failed to get number: %w", err) } - if !number.IsUint64() { - return derive.L1BlockInfo{}, errors.New("number does not fit in a uint64") - } - out.Number = number.Uint64() - - time, err := contract.Timestamp(&opts) + out.Time, err = contract.Timestamp(&opts) if err != nil { return derive.L1BlockInfo{}, fmt.Errorf("failed to get timestamp: %w", err) } - if !time.IsUint64() { - return derive.L1BlockInfo{}, errors.New("time does not fit in a uint64") - - } - out.Time = time.Uint64() out.BaseFee, err = contract.Basefee(&opts) if err != nil { @@ -478,6 +467,11 @@ func L1InfoFromState(ctx context.Context, contract *l1block.L1Block, l2Number *b } out.BlockHash = common.BytesToHash(blockHashBytes[:]) + out.SequenceNumber, err = contract.SequenceNumber(&opts) + if err != nil { + return derive.L1BlockInfo{}, fmt.Errorf("failed to get sequence number: %w", err) + } + return out, nil } @@ -539,8 +533,8 @@ func TestL1InfoContract(t *testing.T) { fillInfoLists := func(start *types.Block, contract *l1block.L1Block, client *ethclient.Client) ([]derive.L1BlockInfo, []derive.L1BlockInfo) { var txList, stateList []derive.L1BlockInfo for b := start; ; { - infoFromTx, err := derive.L1InfoDepositTxDataToStruct(b.Transactions()[0].Data()) - require.Nil(t, err) + var infoFromTx derive.L1BlockInfo + require.NoError(t, infoFromTx.UnmarshalBinary(b.Transactions()[0].Data())) txList = append(txList, infoFromTx) infoFromState, err := L1InfoFromState(ctx, contract, b.Number()) @@ -566,10 +560,11 @@ func TestL1InfoContract(t *testing.T) { require.Nil(t, err) l1blocks[h] = derive.L1BlockInfo{ - Number: b.NumberU64(), - Time: b.Time(), - BaseFee: b.BaseFee(), - BlockHash: h, + Number: b.NumberU64(), + Time: b.Time(), + BaseFee: b.BaseFee(), + BlockHash: h, + SequenceNumber: 0, // ignored, will be overwritten } h = b.ParentHash() @@ -581,9 +576,9 @@ func TestL1InfoContract(t *testing.T) { checkInfoList := func(name string, list []derive.L1BlockInfo) { for _, info := range list { if expected, ok := l1blocks[info.BlockHash]; ok { + expected.SequenceNumber = info.SequenceNumber // the seq nr is not part of the L1 info we know in advance, so we ignore it. require.Equal(t, expected, info) } else { - t.Fatalf("Did not find block hash for L1 Info: %v in test %s", info, name) } } diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index eb6cd674abda..8a288b6ac693 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -7,10 +7,11 @@ DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation( DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 22859) DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 31098) DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 31713) -L1BLockTest:test_basefee() (gas: 7509) -L1BLockTest:test_hash() (gas: 7508) -L1BLockTest:test_number() (gas: 7509) -L1BLockTest:test_timestamp() (gas: 7463) +L1BLockTest:test_basefee() (gas: 7531) +L1BLockTest:test_hash() (gas: 7530) +L1BLockTest:test_number() (gas: 7555) +L1BLockTest:test_sequenceNumber() (gas: 7577) +L1BLockTest:test_timestamp() (gas: 7587) L1CrossDomainMessenger_Test:testCannot_pause() (gas: 10843) L1CrossDomainMessenger_Test:test_blockAndUnblockSuccessfulMessage() (gas: 105412) L1CrossDomainMessenger_Test:test_pause() (gas: 31793) diff --git a/packages/contracts/contracts/L2/L1Block.sol b/packages/contracts/contracts/L2/L1Block.sol index 0b593463af30..a25011dcdbc5 100644 --- a/packages/contracts/contracts/L2/L1Block.sol +++ b/packages/contracts/contracts/L2/L1Block.sol @@ -12,16 +12,18 @@ contract L1Block { address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; - uint256 public number; - uint256 public timestamp; + uint64 public number; + uint64 public timestamp; uint256 public basefee; bytes32 public hash; + uint64 public sequenceNumber; function setL1BlockValues( - uint256 _number, - uint256 _timestamp, + uint64 _number, + uint64 _timestamp, uint256 _basefee, - bytes32 _hash + bytes32 _hash, + uint64 _sequenceNumber ) external { if (msg.sender != DEPOSITOR_ACCOUNT) { revert OnlyDepositor(); @@ -31,5 +33,6 @@ contract L1Block { timestamp = _timestamp; basefee = _basefee; hash = _hash; + sequenceNumber = _sequenceNumber; } } diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts/contracts/test/L1Block.t.sol index c051cbeef99b..2707a18c0f51 100644 --- a/packages/contracts/contracts/test/L1Block.t.sol +++ b/packages/contracts/contracts/test/L1Block.t.sol @@ -15,15 +15,15 @@ contract L1BLockTest is DSTest { lb = new L1Block(); depositor = lb.DEPOSITOR_ACCOUNT(); vm.prank(depositor); - lb.setL1BlockValues(1, 2, 3, NON_ZERO_HASH); + lb.setL1BlockValues(uint64(1), uint64(2), 3, NON_ZERO_HASH, uint64(4)); } function test_number() external { - assertEq(lb.number(), 1); + assertEq(lb.number(), uint64(1)); } function test_timestamp() external { - assertEq(lb.timestamp(), 2); + assertEq(lb.timestamp(), uint64(2)); } function test_basefee() external { @@ -33,4 +33,8 @@ contract L1BLockTest is DSTest { function test_hash() external { assertEq(lb.hash(), NON_ZERO_HASH); } + + function test_sequenceNumber() external { + assertEq(lb.sequenceNumber(), uint64(4)); + } } diff --git a/specs/deposits.md b/specs/deposits.md index 1b51e4f17e10..e57d1196c8b8 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -193,6 +193,10 @@ A predeployed contract on L2 at address `0x4200000000000000000000000000000000000 certain block variables from the corresponding L1 block in storage, so that they may be accessed during the execution of the subsequent deposited transactions. +Apart from the regular L1 attributes, a `sequenceNumber` attribute is stored. +This equals the L2 block number relative to the start of the epoch, i.e. the L2 block distance to the +L2 block height that the L1 attributes last changed, and reset to 0 at the start of a new epoch. + The contract implements an authorization scheme, such that it only accepts state-changing calls from the [depositor account][depositor-account]. From ddf5cb4f517bcdb7c2a9e9d4269f3f7d850428a3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 15 Apr 2022 07:45:42 -0400 Subject: [PATCH 516/585] feat: create opnode/predeploy package This resolves an import cycle when trying to use WithdrawalContractAddress in opnode/node. Otherwise the compiler complains that opnode imports opnode/node which imports opnode. --- opnode/{predeploys.go => predeploy/predeploy.go} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename opnode/{predeploys.go => predeploy/predeploy.go} (89%) diff --git a/opnode/predeploys.go b/opnode/predeploy/predeploy.go similarity index 89% rename from opnode/predeploys.go rename to opnode/predeploy/predeploy.go index 4ff1a985f44c..fc87090ba0f7 100644 --- a/opnode/predeploys.go +++ b/opnode/predeploy/predeploy.go @@ -1,4 +1,4 @@ -package opnode +package predeploy import "github.com/ethereum/go-ethereum/common" From 0684a9f5bae60c996fdf132b6f954ea63af90256 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 29 Mar 2022 04:02:11 +0400 Subject: [PATCH 517/585] opnode: refactor RPC server / config, prototype batch serving --- opnode/flags/flags.go | 7 -- opnode/l2/source.go | 66 ++++++++++++++++- opnode/{node => l2}/util.go | 52 ++++++++++++-- opnode/node/api.go | 138 +++++++++++++++++++++++++++++++++--- opnode/node/config.go | 10 +-- opnode/node/node.go | 7 +- opnode/node/server.go | 32 ++------- opnode/node/server_test.go | 46 +++++++++--- opnode/service.go | 27 +++---- opnode/test/setup.go | 2 + opnode/test/system_test.go | 11 +-- 11 files changed, 313 insertions(+), 85 deletions(-) rename opnode/{node => l2}/util.go (57%) diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go index 6c3886a8c547..47b044f562b4 100644 --- a/opnode/flags/flags.go +++ b/opnode/flags/flags.go @@ -70,12 +70,6 @@ var ( EnvVar: prefixEnvVar("BATCHSUBMITTER_KEY"), } - WithdrawalContractAddr = cli.StringFlag{ - Name: "rpc.withdrawalcontractaddress", - Usage: "Address of the Withdrawal contract. By default, this is set to the withdrawal contract predeploy", - EnvVar: prefixEnvVar("WITHDRAWAL_CONTRACT_ADDR"), - } - LogLevelFlag = cli.StringFlag{ Name: "log.level", Usage: "The lowest log level that will be output", @@ -108,7 +102,6 @@ var optionalFlags = append([]cli.Flag{ L1TrustRPC, SequencingEnabledFlag, BatchSubmitterKeyFlag, - WithdrawalContractAddr, LogLevelFlag, LogFormatFlag, LogColorFlag, diff --git a/opnode/l2/source.go b/opnode/l2/source.go index 39147ce55437..de1d0429dab5 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -6,6 +6,8 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" @@ -23,10 +25,10 @@ type Source struct { log log.Logger } -func NewSource(ll2Node *rpc.Client, genesis *rollup.Genesis, log log.Logger) (*Source, error) { +func NewSource(l2Node *rpc.Client, genesis *rollup.Genesis, log log.Logger) (*Source, error) { return &Source{ - rpc: ll2Node, - client: ethclient.NewClient(ll2Node), + rpc: l2Node, + client: ethclient.NewClient(l2Node), genesis: genesis, log: log, }, nil @@ -254,3 +256,61 @@ func PayloadToBlockRef(payload *ExecutionPayload, genesis *rollup.Genesis) (eth. SequenceNumber: sequenceNumber, }, nil } + +type ReadOnlySource struct { + rpc *rpc.Client // raw RPC client. Used for methods that do not already have bindings + client *ethclient.Client // go-ethereum's wrapper around the rpc client for the eth namespace + genesis *rollup.Genesis + log log.Logger +} + +func NewReadOnlySource(l2Node *rpc.Client, genesis *rollup.Genesis, log log.Logger) (*ReadOnlySource, error) { + return &ReadOnlySource{ + rpc: l2Node, + client: ethclient.NewClient(l2Node), + genesis: genesis, + log: log, + }, nil +} + +// TODO: de-duplicate Source and ReadOnlySource. +// We should really have a L1-downloader like binding that is more configurable and has caching. + +// L2BlockRefByNumber returns the canonical block and parent ids. +func (s *ReadOnlySource) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { + block, err := s.client.BlockByNumber(ctx, l2Num) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Num, err) + } + return blockToBlockRef(block, s.genesis) +} + +// L2BlockRefByHash returns the block & parent ids based on the supplied hash. The returned BlockRef may not be in the canonical chain +func (s *ReadOnlySource) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { + block, err := s.client.BlockByHash(ctx, l2Hash) + if err != nil { + // w%: wrap the error, we still need to detect if a canonical block is not found, a.k.a. end of chain. + return eth.L2BlockRef{}, fmt.Errorf("failed to determine block-hash of height %v, could not get header: %w", l2Hash, err) + } + return blockToBlockRef(block, s.genesis) +} + +func (s *ReadOnlySource) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return s.client.BlockByNumber(ctx, number) +} + +func (s *ReadOnlySource) GetBlockHeader(ctx context.Context, blockTag string) (*types.Header, error) { + var head *types.Header + err := s.rpc.CallContext(ctx, &head, "eth_getBlockByNumber", blockTag, false) + return head, err +} + +func (s *ReadOnlySource) GetProof(ctx context.Context, address common.Address, blockTag string) (*AccountResult, error) { + var getProofResponse *AccountResult + err := s.rpc.CallContext(ctx, &getProofResponse, "eth_getProof", address, []common.Hash{}, blockTag) + if err == nil && getProofResponse == nil { + err = ethereum.NotFound + } + return getProofResponse, err +} diff --git a/opnode/node/util.go b/opnode/l2/util.go similarity index 57% rename from opnode/node/util.go rename to opnode/l2/util.go index b50bfcfcadee..3d7531bb9414 100644 --- a/opnode/node/util.go +++ b/opnode/l2/util.go @@ -1,28 +1,32 @@ -package node +package l2 import ( "bytes" + "errors" "fmt" "math/big" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/trie" ) -func ComputeL2OutputRoot(l2OutputRootVersion l2.Bytes32, blockHash common.Hash, blockRoot common.Hash, storageRoot common.Hash) l2.Bytes32 { +func ComputeL2OutputRoot(l2OutputRootVersion Bytes32, blockHash common.Hash, blockRoot common.Hash, storageRoot common.Hash) Bytes32 { var buf bytes.Buffer buf.Write(l2OutputRootVersion[:]) buf.Write(blockRoot.Bytes()) buf.Write(storageRoot[:]) buf.Write(blockHash.Bytes()) - return l2.Bytes32(crypto.Keccak256Hash(buf.Bytes())) + return Bytes32(crypto.Keccak256Hash(buf.Bytes())) } type AccountResult struct { @@ -76,3 +80,43 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error { } return err } + +// BlockToBatch converts a L2 block to batch-data. +// Empty L2 blocks (i.e. only a L1 info deposit tx) return a nil batch with nil error. +// Invalid L2 blocks may return an error. +func BlockToBatch(config *rollup.Config, block *types.Block) (*derive.BatchData, error) { + txs := block.Transactions() + if len(txs) == 0 { + return nil, errors.New("expected at least 1 transaction but found none") + } + if typ := txs[0].Type(); typ != types.DepositTxType { + return nil, fmt.Errorf("expected first tx to be a deposit of L1 info, but got type: %d", typ) + } + if len(txs) == 1 { // the L1 info deposit tx, but empty otherwise, no batch data to submit + return nil, nil + } + + // encode non-deposit transactions + var opaqueTxs []hexutil.Bytes + for i, tx := range block.Transactions() { + if tx.Type() == types.DepositTxType { + continue + } + otx, err := tx.MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to encode tx %d in block: %v", i, err) + } + opaqueTxs = append(opaqueTxs, otx) + } + + // figure out which L1 epoch this L2 block was derived from + l1Info, err := derive.L1InfoDepositTxData(txs[0].Data()) + if err != nil { + return nil, fmt.Errorf("invalid L1 info deposit tx in block: %v", err) + } + return &derive.BatchData{BatchV1: derive.BatchV1{ + Epoch: rollup.Epoch(l1Info.Number), // the L1 block number equals the L2 epoch. + Timestamp: block.Time(), + Transactions: opaqueTxs, + }}, nil +} diff --git a/opnode/node/api.go b/opnode/node/api.go index 12d799e054c6..3afcf5f7fc87 100644 --- a/opnode/node/api.go +++ b/opnode/node/api.go @@ -1,8 +1,16 @@ package node import ( + "bytes" "context" + "errors" "fmt" + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum" @@ -13,23 +21,31 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +// TODO: decide on sanity limit to not keep adding more blocks when the data size is huge. +// I.e. don't batch together the whole L2 chain +const MaxL2BlocksPerBatchResponse = 100 + type l2EthClient interface { GetBlockHeader(ctx context.Context, blockTag string) (*types.Header, error) // GetProof returns a proof of the account, it may return a nil result without error if the address was not found. - GetProof(ctx context.Context, address common.Address, blockTag string) (*AccountResult, error) + GetProof(ctx context.Context, address common.Address, blockTag string) (*l2.AccountResult, error) + + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) + L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) } type nodeAPI struct { - client l2EthClient - withdrawalContractAddr common.Address - log log.Logger + config *rollup.Config + client l2EthClient + log log.Logger } -func newNodeAPI(l2Client l2EthClient, withdrawalContractAddr common.Address, log log.Logger) *nodeAPI { +func newNodeAPI(config *rollup.Config, l2Client l2EthClient, log log.Logger) *nodeAPI { return &nodeAPI{ - client: l2Client, - withdrawalContractAddr: withdrawalContractAddr, - log: log, + config: config, + client: l2Client, + log: log, } } @@ -45,7 +61,7 @@ func (n *nodeAPI) OutputAtBlock(ctx context.Context, number rpc.BlockNumber) ([] return nil, ethereum.NotFound } - proof, err := n.client.GetProof(ctx, n.withdrawalContractAddr, toBlockNumArg(number)) + proof, err := n.client.GetProof(ctx, predeploy.WithdrawalContractAddress, toBlockNumArg(number)) if err != nil { n.log.Error("failed to get contract proof", "err", err) return nil, err @@ -60,7 +76,7 @@ func (n *nodeAPI) OutputAtBlock(ctx context.Context, number rpc.BlockNumber) ([] } var l2OutputRootVersion l2.Bytes32 // it's zero for now - l2OutputRoot := ComputeL2OutputRoot(l2OutputRootVersion, head.Hash(), head.Root, proof.StorageHash) + l2OutputRoot := l2.ComputeL2OutputRoot(l2OutputRootVersion, head.Hash(), head.Root, proof.StorageHash) return []l2.Bytes32{l2OutputRootVersion, l2OutputRoot}, nil } @@ -74,3 +90,105 @@ func toBlockNumArg(number rpc.BlockNumber) string { } return hexutil.EncodeUint64(uint64(number.Int64())) } + +type BatchBundleRequest struct { + // L2History is a list of L2 blocks that are already in-flight or confirmed. + // The rollup-node then finds the common point, and responds with that point as PrevL2BlockHash and PrevL2BlockNum. + // The L2 history is read in order of the provided hashes, which may contain arbitrary gaps and skips. + // The first common hash will be the continuation point. + // A batch-submitter may search the history using gaps to find a common point even with deep reorgs. + L2History []common.Hash + + MaxSize hexutil.Uint64 +} + +type BatchBundleResponse struct { + PrevL2BlockHash common.Hash + PrevL2BlockNum hexutil.Uint64 + + // LastL2BlockHash is the L2 block hash of the last block in the bundle. + // This is the ideal continuation point for the next batch submission. + // It will equal PrevL2BlockHash if there are no batches to submit. + LastL2BlockHash common.Hash + LastL2BlockNum hexutil.Uint64 + + // Bundle represents the encoded bundle of batches. + // Each batch represents the inputs of a L2 block, i.e. a batch of L2 transactions (excl. deposits and such). + // The bundle encoding supports versioning and compression. + // The rollup-node determines the version to use based on configuration. + // Bundle is empty if there is nothing to submit. + Bundle hexutil.Bytes +} + +func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) (*BatchBundleResponse, error) { + var found eth.BlockID + // First find the common point with L2 history so far + for i, h := range req.L2History { + l2Ref, err := n.client.L2BlockRefByHash(ctx, h) + if err != nil { + if errors.Is(err, ethereum.NotFound) { // on reorgs and such we expect that blocks may be missing + continue + } + return nil, fmt.Errorf("failed to check L2 history for block hash %d in request %s: %v", i, h, err) + } + // found a block that exists! Now make sure it's really a canonical block of L2 + canonBlock, err := n.client.L2BlockRefByNumber(ctx, big.NewInt(int64(l2Ref.Number))) + if err != nil { + if errors.Is(err, ethereum.NotFound) { + continue + } + return nil, fmt.Errorf("failed to check L2 history for block number %d, expecting block %s: %v", l2Ref.Number, h, err) + } + if canonBlock.Hash == h { + // found a common canonical block! + found = eth.BlockID{Hash: canonBlock.Hash, Number: canonBlock.Number} + break + } + } + if found == (eth.BlockID{}) { // none of the L2 history could be found. + return nil, ethereum.NotFound + } + + lastL2Hash := found.Hash + lastL2BlockNum := found.Number + var batches []*derive.BatchData + // Now continue fetching the next blocks, and build batches, until we either run out of space, or run out of blocks. + for i := found.Number + 1; i < found.Number+MaxL2BlocksPerBatchResponse+1; i++ { + l2Block, err := n.client.BlockByNumber(ctx, big.NewInt(int64(i))) + if err != nil { + if errors.Is(err, ethereum.NotFound) { // block number too high + break + } + return nil, fmt.Errorf("failed to retrieve L2 block by number %d: %v", i, err) + } + batch, err := l2.BlockToBatch(n.config, l2Block) + if err != nil { + return nil, fmt.Errorf("failed to convert L2 block %d (%s) to batch: %v", i, l2Block.Hash(), err) + } + lastL2Hash = l2Block.Hash() + lastL2BlockNum = l2Block.Number().Uint64() + if batch == nil { // empty block, nothing to submit as batch + continue + } + batches = append(batches, batch) + // TODO: estimate size of all batches so far (including compressing them together, if we reached max size yet) + } + + var buf bytes.Buffer + if err := derive.EncodeBatches(n.config, batches, &buf); err != nil { + return nil, fmt.Errorf("failed to encode selected batches as bundle: %v", err) + } + + // sanity check the size is within desired limit as planned + if size := uint64(len(buf.Bytes())); size > uint64(req.MaxSize) { + return nil, fmt.Errorf("batch size is wrong, ended up with bundle that is too large: %d > %d", size, req.MaxSize) + } + + return &BatchBundleResponse{ + PrevL2BlockHash: found.Hash, + PrevL2BlockNum: hexutil.Uint64(found.Number), + LastL2BlockHash: lastL2Hash, + LastL2BlockNum: hexutil.Uint64(lastL2BlockNum), + Bundle: hexutil.Bytes(buf.Bytes()), + }, nil +} diff --git a/opnode/node/config.go b/opnode/node/config.go index 59b77f3cc746..b586e6d7795b 100644 --- a/opnode/node/config.go +++ b/opnode/node/config.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum/common" ) type Config struct { @@ -29,13 +28,16 @@ type Config struct { // SubmitterPrivKey, temporary config var while the batch-submitter is part of the rollup node SubmitterPrivKey *ecdsa.PrivateKey - RPCListenAddr string - RPCListenPort int - WithdrawalContractAddr common.Address + RPC RPCConfig P2P p2p.SetupP2P } +type RPCConfig struct { + ListenAddr string + ListenPort int +} + // Check verifies that the given configuration makes sense func (cfg *Config) Check() error { if err := cfg.Rollup.Check(); err != nil { diff --git a/opnode/node/node.go b/opnode/node/node.go index e4dbccac8332..76b50da9c07c 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -121,7 +121,12 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* if err != nil { return nil, fmt.Errorf("failed to dial l2 address (%s): %w", cfg.L2NodeAddr, err) } - server, err := newRPCServer(ctx, cfg.RPCListenAddr, cfg.RPCListenPort, &l2EthClientImpl{l2Node}, cfg.WithdrawalContractAddr, log, appVersion) + + client, err := l2.NewReadOnlySource(l2Node, &genesis, log) + if err != nil { + return nil, err + } + server, err := newRPCServer(ctx, &cfg.RPC, &cfg.Rollup, client, log, appVersion) if err != nil { return nil, err } diff --git a/opnode/node/server.go b/opnode/node/server.go index 49624778c911..9109df7425ee 100644 --- a/opnode/node/server.go +++ b/opnode/node/server.go @@ -7,10 +7,9 @@ import ( "net" "net/http" - "github.com/ethereum/go-ethereum" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" @@ -25,11 +24,13 @@ type rpcServer struct { appVersion string listenAddr net.Addr log log.Logger + l2.Source } -func newRPCServer(ctx context.Context, addr string, port int, l2Client l2EthClient, withdrawalContractAddress common.Address, log log.Logger, appVersion string) (*rpcServer, error) { - api := newNodeAPI(l2Client, withdrawalContractAddress, log.New("rpc", "node")) - endpoint := fmt.Sprintf("%s:%d", addr, port) +func newRPCServer(ctx context.Context, rpcCfg *RPCConfig, rollupCfg *rollup.Config, l2Client l2EthClient, log log.Logger, appVersion string) (*rpcServer, error) { + api := newNodeAPI(rollupCfg, l2Client, log.New("rpc", "node")) + // TODO: extend RPC config with options for WS, IPC and HTTP RPC connections + endpoint := fmt.Sprintf("%s:%d", rpcCfg.ListenAddr, rpcCfg.ListenPort) r := &rpcServer{ endpoint: endpoint, api: api, @@ -89,22 +90,3 @@ func healthzHandler(appVersion string) http.HandlerFunc { _, _ = w.Write([]byte(appVersion)) } } - -type l2EthClientImpl struct { - l2RPCClient *rpc.Client -} - -func (c *l2EthClientImpl) GetBlockHeader(ctx context.Context, blockTag string) (*types.Header, error) { - var head *types.Header - err := c.l2RPCClient.CallContext(ctx, &head, "eth_getBlockByNumber", blockTag, false) - return head, err -} - -func (c *l2EthClientImpl) GetProof(ctx context.Context, address common.Address, blockTag string) (*AccountResult, error) { - var getProofResponse *AccountResult - err := c.l2RPCClient.CallContext(ctx, &getProofResponse, "eth_getProof", address, []common.Hash{}, blockTag) - if err == nil && getProofResponse == nil { - err = ethereum.NotFound - } - return getProofResponse, err -} diff --git a/opnode/node/server_test.go b/opnode/node/server_test.go index 4f43a4063541..57e75c6544d3 100644 --- a/opnode/node/server_test.go +++ b/opnode/node/server_test.go @@ -3,8 +3,14 @@ package node import ( "context" "encoding/json" + "math/big" "testing" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/stretchr/testify/mock" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum/common" @@ -59,17 +65,23 @@ func TestOutputAtBlock(t *testing.T) { "nonce": "0x1", "storageHash": "0xc1917a80cb25ccc50d0d1921525a44fb619b4601194ca726ae32312f08a799f8" }` - var result AccountResult + var result l2.AccountResult err = json.Unmarshal([]byte(resultTestData), &result) assert.NoError(t, err) - l2Client := &mockL2Client{ - head: &header, - result: &result, + rpcCfg := &RPCConfig{ + ListenAddr: "localhost", + ListenPort: 0, + } + rollupCfg := &rollup.Config{ + // ignore other rollup config info in this test } - addr := common.HexToAddress("0x00000000219ab540356cBB839Cbe05303d7705Fa") - server, err := newRPCServer(context.Background(), "localhost", 0, l2Client, addr, log, "0.0") + l2Client := &mockL2Client{} + l2Client.mock.On("GetBlockHeader", "latest").Return(&header) + l2Client.mock.On("GetProof", predeploy.WithdrawalContractAddress, "latest").Return(&result) + + server, err := newRPCServer(context.Background(), rpcCfg, rollupCfg, l2Client, log, "0.0") assert.NoError(t, err) assert.NoError(t, server.Start()) defer server.Stop() @@ -81,17 +93,29 @@ func TestOutputAtBlock(t *testing.T) { err = client.CallContext(context.Background(), &out, "optimism_outputAtBlock", "latest") assert.NoError(t, err) assert.Len(t, out, 2) + l2Client.mock.AssertExpectations(t) } type mockL2Client struct { - head *types.Header - result *AccountResult + mock mock.Mock +} + +func (c *mockL2Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return c.mock.MethodCalled("BlockByNumber", number).Get(0).(*types.Block), nil +} + +func (c *mockL2Client) L2BlockRefByNumber(ctx context.Context, l2Num *big.Int) (eth.L2BlockRef, error) { + return c.mock.MethodCalled("L2BlockRefByNumber", l2Num).Get(0).(eth.L2BlockRef), nil +} + +func (c *mockL2Client) L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) { + return c.mock.MethodCalled("L2BlockRefByHash", l2Hash).Get(0).(eth.L2BlockRef), nil } func (c *mockL2Client) GetBlockHeader(ctx context.Context, blockTag string) (*types.Header, error) { - return c.head, nil + return c.mock.MethodCalled("GetBlockHeader", blockTag).Get(0).(*types.Header), nil } -func (c *mockL2Client) GetProof(ctx context.Context, address common.Address, blockTag string) (*AccountResult, error) { - return c.result, nil +func (c *mockL2Client) GetProof(ctx context.Context, address common.Address, blockTag string) (*l2.AccountResult, error) { + return c.mock.MethodCalled("GetProof", address, blockTag).Get(0).(*l2.AccountResult), nil } diff --git a/opnode/service.go b/opnode/service.go index 4125dd403cb3..08cfd552194d 100644 --- a/opnode/service.go +++ b/opnode/service.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/flags" "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/urfave/cli" ) @@ -39,22 +38,18 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) { } } - withdrawalContractAddress := WithdrawalContractAddress - if value := ctx.GlobalString(flags.WithdrawalContractAddr.Name); value != "" { - withdrawalContractAddress = common.HexToAddress(value) - } - cfg := &node.Config{ - L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), - L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), - L2NodeAddr: ctx.GlobalString(flags.L2EthNodeAddr.Name), - L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name), - Rollup: *rollupConfig, - Sequencer: enableSequencing, - SubmitterPrivKey: batchSubmitterKey, - RPCListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name), - RPCListenPort: ctx.GlobalInt(flags.RPCListenPort.Name), - WithdrawalContractAddr: withdrawalContractAddress, + L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), + L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), + L2NodeAddr: ctx.GlobalString(flags.L2EthNodeAddr.Name), + L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name), + Rollup: *rollupConfig, + Sequencer: enableSequencing, + SubmitterPrivKey: batchSubmitterKey, + RPC: node.RPCConfig{ + ListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name), + ListenPort: ctx.GlobalInt(flags.RPCListenPort.Name), + }, } if err := cfg.Check(); err != nil { return nil, err diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 275c8cf9b4df..ae23f15cf237 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -205,6 +206,7 @@ func (cfg SystemConfig) start() (*System, error) { } l2Alloc[cfg.L1InfoPredeployAddress] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} + l2Alloc[predeploy.WithdrawalContractAddress] = core.GenesisAccount{Code: []byte{}, Balance: common.Big0} genesisTimestamp := uint64(time.Now().Unix()) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 4071513a750a..61651abf14a2 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" @@ -95,8 +96,10 @@ func defaultSystemConfig(t *testing.T) SystemConfig { L1TrustRPC: false, Sequencer: true, // Submitter PrivKey is set in system start for rollup nodes where sequencer = true - RPCListenAddr: "127.0.0.1", - RPCListenPort: 9093, + RPC: node.RPCConfig{ + ListenAddr: "127.0.0.1", + ListenPort: 9093, + }, }, }, Loggers: map[string]log.Logger{ @@ -131,7 +134,7 @@ func TestL2OutputSubmitter(t *testing.T) { l1Client := sys.Clients["l1"] - rollupRPCClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPCListenAddr, cfg.Nodes["sequencer"].RPCListenPort)) + rollupRPCClient, err := rpc.DialContext(context.Background(), fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPC.ListenAddr, cfg.Nodes["sequencer"].RPC.ListenPort)) require.Nil(t, err) rollupClient := rollupclient.NewRollupClient(rollupRPCClient) @@ -146,7 +149,7 @@ func TestL2OutputSubmitter(t *testing.T) { l2OutputSubmitter, err := l2os.NewL2OutputSubmitter(l2os.Config{ L1EthRpc: "ws://127.0.0.1:9090", L2EthRpc: cfg.Nodes["sequencer"].L2NodeAddr, - RollupRpc: fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPCListenAddr, cfg.Nodes["sequencer"].RPCListenPort), + RollupRpc: fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPC.ListenAddr, cfg.Nodes["sequencer"].RPC.ListenPort), L2OOAddress: sys.L2OOContractAddr.String(), PollInterval: 2 * time.Second, NumConfirmations: 1, From 523682d9893a0e5125fe868120f79e0e9571f801 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 21 Apr 2022 22:45:03 -0400 Subject: [PATCH 518/585] feat: enforce size contraints on batch bundles This algorithm is modeled mostly off the one used in the existing batch submitter. The additional complexity enables us to configure a min and max value such that max - min < max_l2_tx_size. Applied strictly, submitting a large L2 tx would cause the batch construct to halt, since the batch constructed without including batch `i` can be under the min, while including batch `i` resulting in exceeding the maximum. The additional complexity in the pruning algorithm is used to identify this case and submit an undersized batch when it cannot be avoided. In the general case, however, this strategy increases our expected profitibability since the average batch size is closer to the desired maximum. --- opnode/node/api.go | 101 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/opnode/node/api.go b/opnode/node/api.go index 3afcf5f7fc87..66ab2b4f9fb0 100644 --- a/opnode/node/api.go +++ b/opnode/node/api.go @@ -99,6 +99,7 @@ type BatchBundleRequest struct { // A batch-submitter may search the history using gaps to find a common point even with deep reorgs. L2History []common.Hash + MinSize hexutil.Uint64 MaxSize hexutil.Uint64 } @@ -152,6 +153,8 @@ func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) ( lastL2Hash := found.Hash lastL2BlockNum := found.Number var batches []*derive.BatchData + var totalBatchSizeBytes uint64 + var hasLargeNextBatch bool // Now continue fetching the next blocks, and build batches, until we either run out of space, or run out of blocks. for i := found.Number + 1; i < found.Number+MaxL2BlocksPerBatchResponse+1; i++ { l2Block, err := n.client.BlockByNumber(ctx, big.NewInt(int64(i))) @@ -165,30 +168,92 @@ func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) ( if err != nil { return nil, fmt.Errorf("failed to convert L2 block %d (%s) to batch: %v", i, l2Block.Hash(), err) } - lastL2Hash = l2Block.Hash() - lastL2BlockNum = l2Block.Number().Uint64() if batch == nil { // empty block, nothing to submit as batch + lastL2Hash = l2Block.Hash() + lastL2BlockNum = l2Block.Number().Uint64() continue } + + // Encode the single as a batch to get a size estimate. This should + // slightly overestimate the size of the final batch, since each + // serialization will contribute the bundle version byte that is + // typically amortized over the entire bundle. + // + // TODO(conner): use iterative encoder when switching to calldata + // compression. + var buf bytes.Buffer + err = derive.EncodeBatches(n.config, []*derive.BatchData{batch}, &buf) + if err != nil { + return nil, fmt.Errorf("failed to encode batch for size estimate: %v", err) + } + + nextBatchSizeBytes := uint64(len(buf.Bytes())) + if totalBatchSizeBytes+nextBatchSizeBytes > uint64(req.MaxSize) { + // Adding this batch causes the bundle to be too large. Record + // whether the bundle size without the batch fails to meet the + // minimum size constraint. This is used below to determine whether + // or not to ignore the minimum size check, since in this scnario it + // can't be avoided, and the batch submitter must submit the + // undersized batch to avoid live locking. + hasLargeNextBatch = totalBatchSizeBytes < uint64(req.MinSize) + break + } + + totalBatchSizeBytes += nextBatchSizeBytes batches = append(batches, batch) - // TODO: estimate size of all batches so far (including compressing them together, if we reached max size yet) + lastL2Hash = l2Block.Hash() + lastL2BlockNum = l2Block.Number().Uint64() } - var buf bytes.Buffer - if err := derive.EncodeBatches(n.config, batches, &buf); err != nil { - return nil, fmt.Errorf("failed to encode selected batches as bundle: %v", err) - } + var pruneCount int + for { - // sanity check the size is within desired limit as planned - if size := uint64(len(buf.Bytes())); size > uint64(req.MaxSize) { - return nil, fmt.Errorf("batch size is wrong, ended up with bundle that is too large: %d > %d", size, req.MaxSize) - } + var buf bytes.Buffer + if err := derive.EncodeBatches(n.config, batches, &buf); err != nil { + return nil, fmt.Errorf("failed to encode selected batches as bundle: %v", err) + } + + bundleSize := uint64(len(buf.Bytes())) + + // Sanity check the bundle size respects the desired maximum. If we have + // exceeded the max size, prune the last block. This is very unlikely to + // occur since our initial greedy estimate has a very small, bounded + // error tolerance, so simply remove the last block and try again. + if bundleSize > uint64(req.MaxSize) { + batches = batches[:len(batches)-1] + pruneCount++ + continue + } - return &BatchBundleResponse{ - PrevL2BlockHash: found.Hash, - PrevL2BlockNum: hexutil.Uint64(found.Number), - LastL2BlockHash: lastL2Hash, - LastL2BlockNum: hexutil.Uint64(lastL2BlockNum), - Bundle: hexutil.Bytes(buf.Bytes()), - }, nil + // There are two specific cases in which we choose to ignore the minimum + // L1 tx size. These cases are permitted since they arise from + // situations where the difference between the configured MinTxSize and + // MaxTxSize is less than the maximum L2 tx size permitted by the + // mempool. + // + // This configuration is useful when trying to ensure the profitability + // is sufficient, and we permit batches to be submitted with less than + // our desired configuration only if it is not possible to construct a + // batch within the given parameters. + // + // The two cases are: + // 1. When the next batch is larger than the difference between the + // min and the max, causing the batch to be too small without the + // element, and too large with it. + // 2. When pruning a batch that initially exceeds the max size, and then + // becomes too small as a result. This is avoided by only applying + // the min size check when the pruneCount is zero. + ignoreMinSize := pruneCount > 0 || hasLargeNextBatch + if !ignoreMinSize && bundleSize < uint64(req.MinSize) { + return nil, nil + } + + return &BatchBundleResponse{ + PrevL2BlockHash: found.Hash, + PrevL2BlockNum: hexutil.Uint64(found.Number), + LastL2BlockHash: lastL2Hash, + LastL2BlockNum: hexutil.Uint64(lastL2BlockNum), + Bundle: hexutil.Bytes(buf.Bytes()), + }, nil + } } From 3bdca2a2d58238f44ee70b3df1e63a8fd1f10da3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 29 Apr 2022 07:14:33 -0700 Subject: [PATCH 519/585] feat: add BundleBuilder helper class --- opnode/node/api.go | 39 ++--- opnode/node/bundle_builder.go | 101 +++++++++++++ opnode/node/bundle_builder_test.go | 228 +++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+), 17 deletions(-) create mode 100644 opnode/node/bundle_builder.go create mode 100644 opnode/node/bundle_builder_test.go diff --git a/opnode/node/api.go b/opnode/node/api.go index 66ab2b4f9fb0..c2229f8c0a86 100644 --- a/opnode/node/api.go +++ b/opnode/node/api.go @@ -150,9 +150,7 @@ func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) ( return nil, ethereum.NotFound } - lastL2Hash := found.Hash - lastL2BlockNum := found.Number - var batches []*derive.BatchData + var bundleBuilder = NewBundleBuilder(found) var totalBatchSizeBytes uint64 var hasLargeNextBatch bool // Now continue fetching the next blocks, and build batches, until we either run out of space, or run out of blocks. @@ -169,8 +167,13 @@ func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) ( return nil, fmt.Errorf("failed to convert L2 block %d (%s) to batch: %v", i, l2Block.Hash(), err) } if batch == nil { // empty block, nothing to submit as batch - lastL2Hash = l2Block.Hash() - lastL2BlockNum = l2Block.Number().Uint64() + bundleBuilder.AddCandidate(BundleCandidate{ + ID: eth.BlockID{ + Hash: l2Block.Hash(), + Number: l2Block.Number().Uint64(), + }, + Batch: nil, + }) continue } @@ -200,16 +203,24 @@ func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) ( } totalBatchSizeBytes += nextBatchSizeBytes - batches = append(batches, batch) - lastL2Hash = l2Block.Hash() - lastL2BlockNum = l2Block.Number().Uint64() + bundleBuilder.AddCandidate(BundleCandidate{ + ID: eth.BlockID{ + Hash: l2Block.Hash(), + Number: l2Block.Number().Uint64(), + }, + Batch: batch, + }) } var pruneCount int for { + if !bundleBuilder.HasNonEmptyCandidate() { + return bundleBuilder.Response(nil), nil + } var buf bytes.Buffer - if err := derive.EncodeBatches(n.config, batches, &buf); err != nil { + err := derive.EncodeBatches(n.config, bundleBuilder.Batches(), &buf) + if err != nil { return nil, fmt.Errorf("failed to encode selected batches as bundle: %v", err) } @@ -220,7 +231,7 @@ func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) ( // occur since our initial greedy estimate has a very small, bounded // error tolerance, so simply remove the last block and try again. if bundleSize > uint64(req.MaxSize) { - batches = batches[:len(batches)-1] + bundleBuilder.PruneLastNonEmpty() pruneCount++ continue } @@ -248,12 +259,6 @@ func (n *nodeAPI) GetBatchBundle(ctx context.Context, req *BatchBundleRequest) ( return nil, nil } - return &BatchBundleResponse{ - PrevL2BlockHash: found.Hash, - PrevL2BlockNum: hexutil.Uint64(found.Number), - LastL2BlockHash: lastL2Hash, - LastL2BlockNum: hexutil.Uint64(lastL2BlockNum), - Bundle: hexutil.Bytes(buf.Bytes()), - }, nil + return bundleBuilder.Response(buf.Bytes()), nil } } diff --git a/opnode/node/bundle_builder.go b/opnode/node/bundle_builder.go new file mode 100644 index 000000000000..07e69567f765 --- /dev/null +++ b/opnode/node/bundle_builder.go @@ -0,0 +1,101 @@ +package node + +import ( + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// BundleCandidate is a struct holding the BlockID of an L2 block and the +// derived batch. +type BundleCandidate struct { + // ID is the block ID of an L2 block. + ID eth.BlockID + + // Batch is batch data drived from the L2 Block. If Batch is nil, the block + // is considered to be empty. Empty blocks do not contribute to the size of + // a bundle. + Batch *derive.BatchData +} + +// BundleBuilder is a helper struct used to construct BatchBundleResponses. This +// struct helps to provide efficient operations to modify a set of +// BundleCandidates that are need to craft bundles. +type BundleBuilder struct { + prevBlockID eth.BlockID + candidates []BundleCandidate + numNonEmpty int +} + +// NewBundleBuilder creates a new instance of a BundleBuilder, where prevBlockID +// is the latest, canonical block that was chosen as the common fork ancestor. +func NewBundleBuilder(prevBlockID eth.BlockID) *BundleBuilder { + return &BundleBuilder{ + prevBlockID: prevBlockID, + candidates: nil, + numNonEmpty: 0, + } +} + +// AddCandidate appends a candidate block to the BundleBuilder. +func (b *BundleBuilder) AddCandidate(candidate BundleCandidate) { + b.candidates = append(b.candidates, candidate) + if candidate.Batch != nil { + b.numNonEmpty++ + } +} + +// HasNonEmptyCandidate returns true if there are a non-zero number of +// non-empty bundle candidates. +func (b *BundleBuilder) HasNonEmptyCandidate() bool { + return b.numNonEmpty > 0 +} + +// PruneLastNonEmpty removes the latest non-empty candidate block and all empty +// blocks follow it. This method is used to reduce the size of the encoded +// bundle in order to satisfy the desired size constraints. +func (b *BundleBuilder) PruneLastNonEmpty() { + if b.numNonEmpty == 0 { + return + } + + for i := len(b.candidates) - 1; i >= 0; i-- { + candidate := b.candidates[i] + if candidate.Batch != nil { + b.candidates = b.candidates[:i] + b.numNonEmpty-- + return + } + } +} + +// Batches returns a slice of all non-nil batches contained within the candidate +// blocks. +func (b *BundleBuilder) Batches() []*derive.BatchData { + var batches = make([]*derive.BatchData, 0, b.numNonEmpty) + for _, candidate := range b.candidates { + if candidate.Batch != nil { + batches = append(batches, candidate.Batch) + } + } + + return batches +} + +// Response returns the BatchBundleResponse given the current state of the +// BundleBuilder. The method accepts the encoded bundle as an argument, and +// fills in the correct metadata in the response. +func (b *BundleBuilder) Response(bundle []byte) *BatchBundleResponse { + lastBlockID := b.prevBlockID + if len(b.candidates) > 0 { + lastBlockID = b.candidates[len(b.candidates)-1].ID + } + + return &BatchBundleResponse{ + PrevL2BlockHash: b.prevBlockID.Hash, + PrevL2BlockNum: hexutil.Uint64(b.prevBlockID.Number), + LastL2BlockHash: lastBlockID.Hash, + LastL2BlockNum: hexutil.Uint64(lastBlockID.Number), + Bundle: hexutil.Bytes(bundle), + } +} diff --git a/opnode/node/bundle_builder_test.go b/opnode/node/bundle_builder_test.go new file mode 100644 index 000000000000..484aa0acbb63 --- /dev/null +++ b/opnode/node/bundle_builder_test.go @@ -0,0 +1,228 @@ +package node_test + +import ( + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +) + +var ( + testPrevBlockID = eth.BlockID{ + Number: 5, + Hash: common.HexToHash("0x55"), + } + testBundleData = []byte{0xbb, 0xbb} +) + +func createResponse( + prevBlock, lastBlock eth.BlockID, + bundle []byte, +) *node.BatchBundleResponse { + + return &node.BatchBundleResponse{ + PrevL2BlockHash: prevBlock.Hash, + PrevL2BlockNum: hexutil.Uint64(prevBlock.Number), + LastL2BlockHash: lastBlock.Hash, + LastL2BlockNum: hexutil.Uint64(lastBlock.Number), + Bundle: hexutil.Bytes(bundle), + } +} + +// TestNewBundleBuilder asserts the state of a BundleBuilder after +// initialization. +func TestNewBundleBuilder(t *testing.T) { + builder := node.NewBundleBuilder(testPrevBlockID) + + require.False(t, builder.HasNonEmptyCandidate()) + require.Equal(t, builder.Batches(), []*derive.BatchData{}) + expResponse := createResponse(testPrevBlockID, testPrevBlockID, nil) + require.Equal(t, expResponse, builder.Response(nil)) +} + +// TestBundleBuilderAddCandidate asserts the state of a BundleBuilder after +// progressively adding various BundleCandidates. +func TestBundleBuilderAddCandidate(t *testing.T) { + builder := node.NewBundleBuilder(testPrevBlockID) + + // Add an empty candidate. + blockID6 := eth.BlockID{ + Number: 6, + Hash: common.HexToHash("0x66"), + } + builder.AddCandidate(node.BundleCandidate{ + ID: blockID6, + Batch: nil, + }) + + // Should behave the same as completely empty builder except for updated + // last block ID fields. + require.False(t, builder.HasNonEmptyCandidate()) + require.Equal(t, builder.Batches(), []*derive.BatchData{}) + expResponse := createResponse(testPrevBlockID, blockID6, nil) + require.Equal(t, expResponse, builder.Response(nil)) + + // Add non-empty candidate. + blockID7 := eth.BlockID{ + Number: 7, + Hash: common.HexToHash("0x77"), + } + batchData7 := &derive.BatchData{ + BatchV1: derive.BatchV1{ + Epoch: 7, + Timestamp: 42, + Transactions: []hexutil.Bytes{ + hexutil.Bytes([]byte{0x42, 0x07}), + }, + }, + } + builder.AddCandidate(node.BundleCandidate{ + ID: blockID7, + Batch: batchData7, + }) + + // HasNonEmptyCandidate should register that we have data to submit to L1, + // last block ID fields should also be updated. + require.True(t, builder.HasNonEmptyCandidate()) + require.Equal(t, builder.Batches(), []*derive.BatchData{batchData7}) + expResponse = createResponse(testPrevBlockID, blockID7, testBundleData) + require.Equal(t, expResponse, builder.Response(testBundleData)) + + // Add another empty block. + blockID8 := eth.BlockID{ + Number: 8, + Hash: common.HexToHash("0x88"), + } + builder.AddCandidate(node.BundleCandidate{ + ID: blockID8, + Batch: nil, + }) + + // Last block ID fields should be updated. + require.True(t, builder.HasNonEmptyCandidate()) + require.Equal(t, builder.Batches(), []*derive.BatchData{batchData7}) + expResponse = createResponse(testPrevBlockID, blockID8, testBundleData) + require.Equal(t, expResponse, builder.Response(testBundleData)) +} + +var pruneLastNonEmptyTests = []pruneLastNonEmptyTestCase{ + { + name: "no candidates", + candidates: nil, + expResponse: createResponse(testPrevBlockID, testPrevBlockID, nil), + }, + { + name: "only empty blocks", + candidates: []node.BundleCandidate{ + { + ID: eth.BlockID{ + Number: 6, + Hash: common.HexToHash("0x66"), + }, + Batch: nil, + }, + { + ID: eth.BlockID{ + Number: 7, + Hash: common.HexToHash("0x77"), + }, + Batch: nil, + }, + }, + expResponse: createResponse( + testPrevBlockID, + eth.BlockID{ + Number: 7, + Hash: common.HexToHash("0x77"), + }, nil, + ), + }, + { + name: "last block is non empty", + candidates: []node.BundleCandidate{ + { + ID: eth.BlockID{ + Number: 6, + Hash: common.HexToHash("0x66"), + }, + Batch: nil, + }, + { + ID: eth.BlockID{ + Number: 7, + Hash: common.HexToHash("0x77"), + }, + Batch: &derive.BatchData{}, + }, + }, + expResponse: createResponse( + testPrevBlockID, + eth.BlockID{ + Number: 6, + Hash: common.HexToHash("0x66"), + }, nil, + ), + }, + { + name: "non empty block followed by empty block", + candidates: []node.BundleCandidate{ + { + ID: eth.BlockID{ + Number: 6, + Hash: common.HexToHash("0x66"), + }, + Batch: nil, + }, + { + ID: eth.BlockID{ + Number: 7, + Hash: common.HexToHash("0x77"), + }, + Batch: &derive.BatchData{}, + }, + { + ID: eth.BlockID{ + Number: 8, + Hash: common.HexToHash("0x88"), + }, + Batch: nil, + }, + }, + expResponse: createResponse( + testPrevBlockID, + eth.BlockID{ + Number: 6, + Hash: common.HexToHash("0x66"), + }, nil, + ), + }, +} + +// TestBundleBuilderPruneLastNonEmpty asserts that pruning the BundleBuilder +// always removes the last non-empty block, if one exists, and any subsequent +// empty blocks. +func TestBundleBuilderPruneLastNonEmpty(t *testing.T) { + for _, test := range pruneLastNonEmptyTests { + t.Run(test.name, test.run) + } +} + +type pruneLastNonEmptyTestCase struct { + name string + candidates []node.BundleCandidate + expResponse *node.BatchBundleResponse +} + +func (tc *pruneLastNonEmptyTestCase) run(t *testing.T) { + builder := node.NewBundleBuilder(testPrevBlockID) + for _, candidate := range tc.candidates { + builder.AddCandidate(candidate) + } + + builder.PruneLastNonEmpty() + require.Equal(t, tc.expResponse, builder.Response(nil)) +} From 35167d4c5e5f2c3fa4a478b028d0aa390326f9cc Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 1 Apr 2022 04:14:48 -0700 Subject: [PATCH 520/585] fix: typo in l2os config docs --- l2os/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l2os/config.go b/l2os/config.go index 84f6efac2394..9e6333e44f43 100644 --- a/l2os/config.go +++ b/l2os/config.go @@ -14,7 +14,7 @@ type Config struct { // L1EthRpc is the HTTP provider URL for L1. L1EthRpc string - // L2EthRpc is the HTTP provider URL for L1. + // L2EthRpc is the HTTP provider URL for L2. L2EthRpc string // RollupRpc is the HTTP provider URL for the rollup node. From ebc23cf0d207b0a5374ac5e4374dfbffdc9ff154 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 1 Apr 2022 04:40:23 -0700 Subject: [PATCH 521/585] feat: add GetBatchBundle method to rollupclient.RollupClient --- l2os/rollupclient/rollupclient.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/l2os/rollupclient/rollupclient.go b/l2os/rollupclient/rollupclient.go index 3ee19ab1df91..7b6033bc1ea7 100644 --- a/l2os/rollupclient/rollupclient.go +++ b/l2os/rollupclient/rollupclient.go @@ -5,6 +5,7 @@ import ( "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" ) @@ -17,6 +18,16 @@ func NewRollupClient(rpc *rpc.Client) *RollupClient { return &RollupClient{rpc} } +func (r *RollupClient) GetBatchBundle( + ctx context.Context, + req *node.BatchBundleRequest, +) (*node.BatchBundleResponse, error) { + + var batchResponse = new(node.BatchBundleResponse) + err := r.rpc.CallContext(ctx, &batchResponse, "optimism_getBatchBundle", req) + return batchResponse, err +} + func (r *RollupClient) OutputAtBlock(ctx context.Context, blockNum *big.Int) ([]l2.Bytes32, error) { var output []l2.Bytes32 err := r.rpc.CallContext(ctx, &output, "optimism_outputAtBlock", hexutil.EncodeBig(blockNum)) From 1de894db46fd50119aecf7c667e52d34175ca109 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 15 Apr 2022 06:21:54 -0400 Subject: [PATCH 522/585] feat: simplify l2os rollupclient init --- l2os/l2_output_submitter.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/l2os/l2_output_submitter.go b/l2os/l2_output_submitter.go index fc32eaeba887..4eef1fd342ad 100644 --- a/l2os/l2_output_submitter.go +++ b/l2os/l2_output_submitter.go @@ -119,7 +119,7 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er return nil, err } - rollupClient, err := dialRpcClientWithTimeout(ctx, cfg.RollupRpc) + rollupClient, err := dialRollupClientWithTimeout(ctx, cfg.RollupRpc) if err != nil { return nil, err } @@ -140,7 +140,7 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er Name: "L2Output Submitter", L1Client: l1Client, L2Client: l2Client, - RollupClient: rollupclient.NewRollupClient(rollupClient), + RollupClient: rollupClient, L2OOAddr: l2ooAddress, ChainID: chainID, PrivKey: l2OutputPrivKey, @@ -183,14 +183,19 @@ func dialEthClientWithTimeout(ctx context.Context, url string) ( return ethclient.DialContext(ctxt, url) } -// dialRpcClientWithTimeout attempts to dial the RPC provider using the provided +// dialRollupClientWithTimeout attempts to dial the RPC provider using the provided // URL. If the dial doesn't complete within defaultDialTimeout seconds, this // method will return an error. -func dialRpcClientWithTimeout(ctx context.Context, url string) (*rpc.Client, error) { +func dialRollupClientWithTimeout(ctx context.Context, url string) (*rollupclient.RollupClient, error) { ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) defer cancel() - return rpc.DialContext(ctxt, url) + client, err := rpc.DialContext(ctxt, url) + if err != nil { + return nil, err + } + + return rollupclient.NewRollupClient(client), nil } // parseAddress parses an ETH address from a hex string. This method will fail if From b2ffad5bde6003036679a4dec4cf79585cd85f93 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 1 Apr 2022 05:32:42 -0700 Subject: [PATCH 523/585] feat: reduce BSS poll interval The current setup assumes the batches are submitted very soon after the block is created on L2. Increasing the poll interval ensures that we discover and publish new batches in response. Without modifying this value, the subsequent changes will still fail even though the code is correct. --- opnode/test/system_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 61651abf14a2..828ed2cde67b 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -151,7 +151,7 @@ func TestL2OutputSubmitter(t *testing.T) { L2EthRpc: cfg.Nodes["sequencer"].L2NodeAddr, RollupRpc: fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPC.ListenAddr, cfg.Nodes["sequencer"].RPC.ListenPort), L2OOAddress: sys.L2OOContractAddr.String(), - PollInterval: 2 * time.Second, + PollInterval: 50 * time.Millisecond, NumConfirmations: 1, ResubmissionTimeout: 3 * time.Second, SafeAbortNonceTooLowCount: 3, From bda9fc853c239764f0545bd1569c13ec038b98c7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 1 Apr 2022 04:15:28 -0700 Subject: [PATCH 524/585] feat: add sequencer history db --- bss/db/history_db.go | 133 +++++++++++++++++++++++++++++++++++++ bss/db/history_db_test.go | 136 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 bss/db/history_db.go create mode 100644 bss/db/history_db_test.go diff --git a/bss/db/history_db.go b/bss/db/history_db.go new file mode 100644 index 000000000000..f59b7969cc33 --- /dev/null +++ b/bss/db/history_db.go @@ -0,0 +1,133 @@ +package db + +import ( + "encoding/json" + "io/ioutil" + "os" + "sort" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" +) + +type History struct { + BlockIDs []eth.BlockID `json:"block_ids"` +} + +func (h *History) LatestID() eth.BlockID { + return h.BlockIDs[len(h.BlockIDs)-1] +} + +func (h *History) AppendEntry(blockID eth.BlockID, maxEntries uint64) { + for _, id := range h.BlockIDs { + if id.Hash == blockID.Hash { + return + } + } + + h.BlockIDs = append(h.BlockIDs, blockID) + if uint64(len(h.BlockIDs)) > maxEntries { + h.BlockIDs = h.BlockIDs[len(h.BlockIDs)-int(maxEntries):] + } +} + +func (h *History) Ancestors() []common.Hash { + var sortedBlockIDs = make([]eth.BlockID, 0, len(h.BlockIDs)) + sortedBlockIDs = append(sortedBlockIDs, h.BlockIDs...) + + // Keep block ids sorted in ascending order to minimize the number of swaps. + // Use stable sort so that newest are prioritized over older ones. + sort.SliceStable(sortedBlockIDs, func(i, j int) bool { + return sortedBlockIDs[i].Number < sortedBlockIDs[j].Number + }) + + var ancestors = make([]common.Hash, 0, len(h.BlockIDs)) + for i := len(h.BlockIDs) - 1; i >= 0; i-- { + ancestors = append(ancestors, h.BlockIDs[i].Hash) + } + + return ancestors +} + +type HistoryDatabase interface { + LoadHistory() (*History, error) + AppendEntry(eth.BlockID) error + Close() error +} + +type JSONFileDatabase struct { + filename string + maxEntries uint64 + genesisHash common.Hash +} + +func OpenJSONFileDatabase( + filename string, + maxEntries uint64, + genesisHash common.Hash, +) (*JSONFileDatabase, error) { + + _, err := os.Stat(filename) + if os.IsNotExist(err) { + file, err := os.Create(filename) + if err != nil { + return nil, err + } + err = file.Close() + if err != nil { + return nil, err + } + } + + return &JSONFileDatabase{ + filename: filename, + maxEntries: maxEntries, + genesisHash: genesisHash, + }, nil +} + +func (d *JSONFileDatabase) LoadHistory() (*History, error) { + fileContents, err := os.ReadFile(d.filename) + if err != nil { + return nil, err + } + + if len(fileContents) == 0 { + return &History{ + BlockIDs: []eth.BlockID{ + { + Number: 0, + Hash: d.genesisHash, + }, + }, + }, nil + } + + var history History + err = json.Unmarshal(fileContents, &history) + if err != nil { + return nil, err + } + + return &history, nil +} + +func (d *JSONFileDatabase) AppendEntry(blockID eth.BlockID) error { + history, err := d.LoadHistory() + if err != nil { + return err + } + + history.AppendEntry(blockID, d.maxEntries) + + newFileContents, err := json.Marshal(history) + if err != nil { + return err + } + + return ioutil.WriteFile(d.filename, newFileContents, 0644) +} + +func (d *JSONFileDatabase) Close() error { + return nil +} diff --git a/bss/db/history_db_test.go b/bss/db/history_db_test.go new file mode 100644 index 000000000000..1f590410863c --- /dev/null +++ b/bss/db/history_db_test.go @@ -0,0 +1,136 @@ +package db_test + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/bss/db" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +const ( + testMaxDepth uint64 = 10 +) + +var ( + testGenesisHash = common.HexToHash("0xabcd") + + genesisEntry = eth.BlockID{ + Number: 0, + Hash: testGenesisHash, + } +) + +func TestOpenJSONFileDatabaseNoFile(t *testing.T) { + file, err := ioutil.TempFile("", "history_db.*.json") + require.Nil(t, err) + + filename := file.Name() + + err = os.Remove(filename) + require.Nil(t, err) + + hdb, err := db.OpenJSONFileDatabase(filename, testMaxDepth, testGenesisHash) + require.Nil(t, err) + require.NotNil(t, hdb) + + err = hdb.Close() + require.Nil(t, err) +} + +func TestOpenJSONFileDatabaseEmptyFile(t *testing.T) { + file, err := ioutil.TempFile("", "history_db.*.json") + require.Nil(t, err) + + filename := file.Name() + defer os.Remove(filename) + + hdb, err := db.OpenJSONFileDatabase(filename, testMaxDepth, testGenesisHash) + require.Nil(t, err) + require.NotNil(t, hdb) + + err = hdb.Close() + require.Nil(t, err) +} + +func TestOpenJSONFileDatabase(t *testing.T) { + file, err := ioutil.TempFile("", "history_db.*.json") + require.Nil(t, err) + + filename := file.Name() + defer os.Remove(filename) + + hdb, err := db.OpenJSONFileDatabase(filename, testMaxDepth, testGenesisHash) + require.Nil(t, err) + require.NotNil(t, hdb) + + err = hdb.Close() + require.Nil(t, err) +} + +func makeDB(t *testing.T) (*db.JSONFileDatabase, func()) { + file, err := ioutil.TempFile("", "history_db.*.json") + require.Nil(t, err) + + filename := file.Name() + hdb, err := db.OpenJSONFileDatabase(filename, testMaxDepth, testGenesisHash) + require.Nil(t, err) + require.NotNil(t, hdb) + + cleanup := func() { + _ = hdb.Close() + _ = os.Remove(filename) + } + + return hdb, cleanup +} + +func TestLoadHistoryEmpty(t *testing.T) { + hdb, cleanup := makeDB(t) + defer cleanup() + + history, err := hdb.LoadHistory() + require.Nil(t, err) + require.NotNil(t, history) + require.Equal(t, int(1), len(history.BlockIDs)) + + expHistory := &db.History{ + BlockIDs: []eth.BlockID{genesisEntry}, + } + require.Equal(t, expHistory, history) +} + +func TestAppendEntry(t *testing.T) { + hdb, cleanup := makeDB(t) + defer cleanup() + + genExpHistory := func(n uint64) *db.History { + var history db.History + history.AppendEntry(genesisEntry, testMaxDepth) + for i := uint64(0); i < n+1; i++ { + history.AppendEntry(eth.BlockID{ + Number: i, + Hash: common.Hash{byte(i)}, + }, testMaxDepth) + } + return &history + } + + for i := uint64(0); i < 2*testMaxDepth; i++ { + err := hdb.AppendEntry(eth.BlockID{ + Number: i, + Hash: common.Hash{byte(i)}, + }) + require.Nil(t, err) + + history, err := hdb.LoadHistory() + require.Nil(t, err) + + expHistory := genExpHistory(i) + require.Equal(t, expHistory, history) + require.LessOrEqual(t, uint64(len(history.BlockIDs)), testMaxDepth+1) + } +} From 40494e6d864fc28b67e41a155d121ddd3cdd9533 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 1 Apr 2022 04:41:56 -0700 Subject: [PATCH 525/585] feat: add sequencer BSS driver to submit batches --- bss/sequencer/driver.go | 238 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 bss/sequencer/driver.go diff --git a/bss/sequencer/driver.go b/bss/sequencer/driver.go new file mode 100644 index 000000000000..7f8f9e776541 --- /dev/null +++ b/bss/sequencer/driver.go @@ -0,0 +1,238 @@ +package sequencer + +import ( + "context" + "crypto/ecdsa" + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/bss/db" + "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" + "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" +) + +type Config struct { + Log log.Logger + Name string + L1Client *ethclient.Client + L2Client *ethclient.Client + RollupClient *rollupclient.RollupClient + MinL1TxSize uint64 + MaxL1TxSize uint64 + BatchInboxAddress common.Address + HistoryDB db.HistoryDatabase + ChainID *big.Int + PrivKey *ecdsa.PrivateKey +} + +type Driver struct { + cfg Config + walletAddr common.Address + l log.Logger + + currentBatch *node.BatchBundleResponse +} + +func NewDriver(cfg Config) (*Driver, error) { + walletAddr := crypto.PubkeyToAddress(cfg.PrivKey.PublicKey) + + return &Driver{ + cfg: cfg, + walletAddr: walletAddr, + l: cfg.Log, + }, nil +} + +// Name is an identifier used to prefix logs for a particular service. +func (d *Driver) Name() string { + return d.cfg.Name +} + +// WalletAddr is the wallet address used to pay for transaction fees. +func (d *Driver) WalletAddr() common.Address { + return d.walletAddr +} + +// GetBlockRange returns the start and end L2 block heights that need to be +// processed. Note that the end value is *exclusive*, therefore if the returned +// values are identical nothing needs to be processed. +func (d *Driver) GetBlockRange( + ctx context.Context, +) (*big.Int, *big.Int, error) { + + // Clear prior batch, if any. + d.currentBatch = nil + + history, err := d.cfg.HistoryDB.LoadHistory() + if err != nil { + return nil, nil, err + } + + latestBlockID := history.LatestID() + ancestors := history.Ancestors() + + d.l.Info("Fetching bundle", + "latest_number", latestBlockID.Number, + "lastest_hash", latestBlockID.Hash, + "num_ancestors", len(ancestors), + "min_tx_size", d.cfg.MinL1TxSize, + "max_tx_size", d.cfg.MaxL1TxSize) + + batchResp, err := d.cfg.RollupClient.GetBatchBundle( + ctx, + &node.BatchBundleRequest{ + L2History: ancestors, + MinSize: hexutil.Uint64(d.cfg.MinL1TxSize), + MaxSize: hexutil.Uint64(d.cfg.MaxL1TxSize), + }, + ) + if err != nil { + return nil, nil, err + } + + // Bundle is not available yet, return the next expected block number. + if batchResp == nil { + start64 := latestBlockID.Number + 1 + start := big.NewInt(int64(start64)) + return start, start, nil + } + + // There is nothing to be done if the rollup returns a last block hash equal + // to the previous block hash. Return identical start and end block heights + // to signal that there is no work to be done. + start := big.NewInt(int64(batchResp.PrevL2BlockNum) + 1) + if batchResp.LastL2BlockHash == batchResp.PrevL2BlockHash { + return start, start, nil + } + + if batchResp.PrevL2BlockHash != latestBlockID.Hash { + d.l.Warn("Reorg", "rpc_prev_block_hash", batchResp.PrevL2BlockHash, + "db_prev_block_hash", latestBlockID.Hash) + } + + // If the bundle is empty, this implies that all blocks in the range were + // empty blocks. Simply commit the new head and return that there is no work + // to be done. + if len(batchResp.Bundle) == 0 { + err = d.cfg.HistoryDB.AppendEntry(eth.BlockID{ + Number: uint64(batchResp.LastL2BlockNum), + Hash: batchResp.LastL2BlockHash, + }) + if err != nil { + return nil, nil, err + } + + next := big.NewInt(int64(batchResp.LastL2BlockNum + 1)) + return next, next, nil + } + + d.currentBatch = batchResp + end := big.NewInt(int64(batchResp.LastL2BlockNum + 1)) + + return start, end, nil +} + +// CraftTx transforms the L2 blocks between start and end into a transaction +// using the given nonce. +// +// NOTE: This method SHOULD NOT publish the resulting transaction. +func (d *Driver) CraftTx( + ctx context.Context, + start, end, nonce *big.Int, +) (*types.Transaction, error) { + + gasTipCap, err := d.cfg.L1Client.SuggestGasTipCap(ctx) + if err != nil { + // TODO(conner): handle fallback + return nil, err + } + + head, err := d.cfg.L1Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, err + } + + gasFeeCap := txmgr.CalcGasFeeCap(head.BaseFee, gasTipCap) + + rawTx := &types.DynamicFeeTx{ + ChainID: d.cfg.ChainID, + Nonce: nonce.Uint64(), + To: &d.cfg.BatchInboxAddress, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Data: d.currentBatch.Bundle, + } + + gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true) + if err != nil { + return nil, err + } + rawTx.Gas = gas + + return types.SignNewTx( + d.cfg.PrivKey, types.LatestSignerForChainID(d.cfg.ChainID), rawTx, + ) +} + +// UpdateGasPrice signs an otherwise identical txn to the one provided but with +// updated gas prices sampled from the existing network conditions. +// +// NOTE: Thie method SHOULD NOT publish the resulting transaction. +func (d *Driver) UpdateGasPrice( + ctx context.Context, + tx *types.Transaction, +) (*types.Transaction, error) { + + gasTipCap, err := d.cfg.L1Client.SuggestGasTipCap(ctx) + if err != nil { + // TODO(conner): handle fallback + return nil, err + } + + head, err := d.cfg.L1Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, err + } + + gasFeeCap := txmgr.CalcGasFeeCap(head.BaseFee, gasTipCap) + + rawTx := &types.DynamicFeeTx{ + ChainID: d.cfg.ChainID, + Nonce: tx.Nonce(), + To: tx.To(), + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Gas: tx.Gas(), + Data: tx.Data(), + } + + return types.SignNewTx( + d.cfg.PrivKey, types.LatestSignerForChainID(d.cfg.ChainID), rawTx, + ) +} + +// SendTransaction injects a signed transaction into the pending pool for +// execution. +func (d *Driver) SendTransaction( + ctx context.Context, + tx *types.Transaction, +) error { + + err := d.cfg.HistoryDB.AppendEntry(eth.BlockID{ + Number: uint64(d.currentBatch.LastL2BlockNum), + Hash: d.currentBatch.LastL2BlockHash, + }) + if err != nil { + return err + } + + return d.cfg.L1Client.SendTransaction(ctx, tx) +} From 07c937af56574bf2da024627e35211b552c082a1 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 15 Apr 2022 06:17:21 -0400 Subject: [PATCH 526/585] feat: add bss configuration --- bss/config.go | 98 ++++++++++++++++++++++++++++++ bss/flags/flags.go | 148 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 bss/config.go create mode 100644 bss/flags/flags.go diff --git a/bss/config.go b/bss/config.go new file mode 100644 index 000000000000..f5e5cdf047fb --- /dev/null +++ b/bss/config.go @@ -0,0 +1,98 @@ +package bss + +import ( + "time" + + "github.com/urfave/cli" + + "github.com/ethereum-optimism/optimistic-specs/bss/flags" +) + +type Config struct { + /* Required Params */ + + // L1EthRpc is the HTTP provider URL for L1. + L1EthRpc string + + // L2EthRpc is the HTTP provider URL for L2. + L2EthRpc string + + // RollupRpc is the HTTP provider URL for the rollup node. + RollupRpc string + + // MinL1TxSize is the minimum size of a batch tx submitted to L1. + MinL1TxSize uint64 + + // MaxL1TxSize is the maximum size of a batch tx submitted to L1. + MaxL1TxSize uint64 + + // PollInterval is the delay between querying L2 for more transaction + // and creating a new batch. + PollInterval time.Duration + + // NumConfirmations is the number of confirmations which we will wait after + // appending new batches. + NumConfirmations uint64 + + // SafeAbortNonceTooLowCount is the number of ErrNonceTooLowObservations + // required to give up on a tx at a particular nonce without receiving + // confirmation. + SafeAbortNonceTooLowCount uint64 + + // ResubmissionTimeout is time we will wait before resubmitting a + // transaction. + ResubmissionTimeout time.Duration + + // Mnemonic is the HD seed used to derive the wallet private keys for both + // the sequence and proposer. Must be used in conjunction with + // SequencerHDPath and ProposerHDPath. + Mnemonic string + + // SequencerHDPath is the derivation path used to obtain the private key for + // batched submission of sequencer transactions. + SequencerHDPath string + + // SequencerHistoryDBFilename is the filename of the database used to track + // the latest L2 sequencer batches that were published. + SequencerHistoryDBFilename string + + // SequencerGenesisHash is the genesis hash of the L2 chain. + SequencerGenesisHash string + + // SequencerBatchInboxAddress is the address in which to send batch + // transactions. + SequencerBatchInboxAddress string + + /* Optional Params */ + + // LogLevel is the lowest log level that will be output. + LogLevel string + + // LogTerminal if true, will log to stdout in terminal format. Otherwise the + // output will be in JSON format. + LogTerminal bool +} + +// NewConfig parses the Config from the provided flags or environment variables. +func NewConfig(ctx *cli.Context) Config { + return Config{ + /* Required Flags */ + L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name), + L2EthRpc: ctx.GlobalString(flags.L2EthRpcFlag.Name), + RollupRpc: ctx.GlobalString(flags.RollupRpcFlag.Name), + MinL1TxSize: ctx.GlobalUint64(flags.MinL1TxSizeBytesFlag.Name), + MaxL1TxSize: ctx.GlobalUint64(flags.MaxL1TxSizeBytesFlag.Name), + PollInterval: ctx.GlobalDuration(flags.PollIntervalFlag.Name), + NumConfirmations: ctx.GlobalUint64(flags.NumConfirmationsFlag.Name), + SafeAbortNonceTooLowCount: ctx.GlobalUint64(flags.SafeAbortNonceTooLowCountFlag.Name), + ResubmissionTimeout: ctx.GlobalDuration(flags.ResubmissionTimeoutFlag.Name), + Mnemonic: ctx.GlobalString(flags.MnemonicFlag.Name), + SequencerHDPath: ctx.GlobalString(flags.SequencerHDPathFlag.Name), + SequencerHistoryDBFilename: ctx.GlobalString(flags.SequencerHistoryDBFilenameFlag.Name), + SequencerGenesisHash: ctx.GlobalString(flags.SequencerGenesisHashFlag.Name), + SequencerBatchInboxAddress: ctx.GlobalString(flags.SequencerBatchInboxAddressFlag.Name), + /* Optional Flags */ + LogLevel: ctx.GlobalString(flags.LogLevelFlag.Name), + LogTerminal: ctx.GlobalBool(flags.LogTerminalFlag.Name), + } +} diff --git a/bss/flags/flags.go b/bss/flags/flags.go new file mode 100644 index 000000000000..64995eb70243 --- /dev/null +++ b/bss/flags/flags.go @@ -0,0 +1,148 @@ +package flags + +import ( + "github.com/urfave/cli" +) + +const envVarPrefix = "BATCH_SUBMITTER_" + +func prefixEnvVar(name string) string { + return envVarPrefix + name +} + +var ( + /* Required Flags */ + + L1EthRpcFlag = cli.StringFlag{ + Name: "l1-eth-rpc", + Usage: "HTTP provider URL for L1", + Required: true, + EnvVar: "L1_ETH_RPC", + } + L2EthRpcFlag = cli.StringFlag{ + Name: "l2-eth-rpc", + Usage: "HTTP provider URL for L2", + Required: true, + EnvVar: "L2_ETH_RPC", + } + RollupRpcFlag = cli.StringFlag{ + Name: "rollup-rpc", + Usage: "HTTP provider URL for the rollup node", + Required: true, + EnvVar: "ROLLUP_RPC", + } + MinL1TxSizeBytesFlag = cli.Uint64Flag{ + Name: "min-l1-tx-size-bytes", + Usage: "The minimum size of a batch tx submitted to L1.", + Required: true, + EnvVar: prefixEnvVar("MIN_L1_TX_SIZE_BYTES"), + } + MaxL1TxSizeBytesFlag = cli.Uint64Flag{ + Name: "max-l1-tx-size-bytes", + Usage: "The maximum size of a batch tx submitted to L1.", + Required: true, + EnvVar: prefixEnvVar("MAX_L1_TX_SIZE_BYTES"), + } + PollIntervalFlag = cli.DurationFlag{ + Name: "poll-interval", + Usage: "Delay between querying L2 for more transactions and " + + "creating a new batch", + Required: true, + EnvVar: prefixEnvVar("POLL_INTERVAL"), + } + NumConfirmationsFlag = cli.Uint64Flag{ + Name: "num-confirmations", + Usage: "Number of confirmations which we will wait after " + + "appending a new batch", + Required: true, + EnvVar: prefixEnvVar("NUM_CONFIRMATIONS"), + } + SafeAbortNonceTooLowCountFlag = cli.Uint64Flag{ + Name: "safe-abort-nonce-too-low-count", + Usage: "Number of ErrNonceTooLow observations required to " + + "give up on a tx at a particular nonce without receiving " + + "confirmation", + Required: true, + EnvVar: prefixEnvVar("SAFE_ABORT_NONCE_TOO_LOW_COUNT"), + } + ResubmissionTimeoutFlag = cli.DurationFlag{ + Name: "resubmission-timeout", + Usage: "Duration we will wait before resubmitting a " + + "transaction to L1", + Required: true, + EnvVar: prefixEnvVar("RESUBMISSION_TIMEOUT"), + } + MnemonicFlag = cli.StringFlag{ + Name: "mnemonic", + Usage: "The mnemonic used to derive the wallets for either the " + + "sequencer or the l2output", + Required: true, + EnvVar: prefixEnvVar("MNEMONIC"), + } + SequencerHDPathFlag = cli.StringFlag{ + Name: "sequencer-hd-path", + Usage: "The HD path used to derive the sequencer wallet from the " + + "mnemonic. The mnemonic flag must also be set.", + Required: true, + EnvVar: prefixEnvVar("SEQUENCER_HD_PATH"), + } + SequencerHistoryDBFilenameFlag = cli.StringFlag{ + Name: "sequencer-history-db-filename", + Usage: "File name used to identify the latest L2 batches submitted " + + "by the sequencer", + Required: true, + EnvVar: prefixEnvVar("SEQUENCER_HISTORY_DB_FILENAME"), + } + SequencerGenesisHashFlag = cli.StringFlag{ + Name: "sequencer-genesis-hash", + Usage: "Genesis hash of the L2 chain", + Required: true, + EnvVar: prefixEnvVar("SEQUENCER_GENESIS_HASH"), + } + SequencerBatchInboxAddressFlag = cli.StringFlag{ + Name: "sequencer-batch-inbox-address", + Usage: "L1 Address to receive batch transactions", + Required: true, + EnvVar: prefixEnvVar("SEQUENCER_BATCH_INBOX_ADDRESS"), + } + + /* Optional Flags */ + + LogLevelFlag = cli.StringFlag{ + Name: "log-level", + Usage: "The lowest log level that will be output", + Value: "info", + EnvVar: prefixEnvVar("LOG_LEVEL"), + } + LogTerminalFlag = cli.BoolFlag{ + Name: "log-terminal", + Usage: "If true, outputs logs in terminal format, otherwise prints " + + "in JSON format.", + EnvVar: prefixEnvVar("LOG_TERMINAL"), + } +) + +var requiredFlags = []cli.Flag{ + L1EthRpcFlag, + L2EthRpcFlag, + RollupRpcFlag, + MinL1TxSizeBytesFlag, + MaxL1TxSizeBytesFlag, + PollIntervalFlag, + NumConfirmationsFlag, + SafeAbortNonceTooLowCountFlag, + ResubmissionTimeoutFlag, + MnemonicFlag, + SequencerHDPathFlag, + SequencerHistoryDBFilenameFlag, + SequencerGenesisHashFlag, + SequencerBatchInboxAddressFlag, +} + +var optionalFlags = []cli.Flag{ + LogLevelFlag, + LogTerminalFlag, +} + +// Flags contains the list of configuration options available to the binary. +var Flags = append(requiredFlags, optionalFlags...) From c224c2505899e4cc4b7a1956f7f44b3e61d0a583 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 28 Apr 2022 15:28:47 -0700 Subject: [PATCH 527/585] feat: add LOG_TERMINAL flag to l2os, use non-global log instance Also modifies the shutdown logic of l2os.Service to abort if stuck publishing a transaction. --- l2os/config.go | 7 ++++- l2os/drivers/l2output/driver.go | 21 ++++++++------ l2os/flags/flags.go | 7 +++++ l2os/l2_output_submitter.go | 49 ++++++++++++++++++++----------- l2os/service.go | 51 ++++++++++++++++++--------------- l2os/txmgr/txmgr.go | 34 +++++++++++++--------- l2os/txmgr/txmgr_test.go | 2 ++ opnode/test/system_test.go | 3 +- ops/docker-compose.yml | 1 + 9 files changed, 110 insertions(+), 65 deletions(-) diff --git a/l2os/config.go b/l2os/config.go index 9e6333e44f43..3cb21e336d1b 100644 --- a/l2os/config.go +++ b/l2os/config.go @@ -53,6 +53,10 @@ type Config struct { // LogLevel is the lowest log level that will be output. LogLevel string + + // LogTerminal if true, will log to stdout in terminal format. Otherwise the + // output will be in JSON format. + LogTerminal bool } // NewConfig parses the Config from the provided flags or environment variables. @@ -70,6 +74,7 @@ func NewConfig(ctx *cli.Context) Config { Mnemonic: ctx.GlobalString(flags.MnemonicFlag.Name), L2OutputHDPath: ctx.GlobalString(flags.L2OutputHDPathFlag.Name), /* Optional Flags */ - LogLevel: ctx.GlobalString(flags.LogLevelFlag.Name), + LogLevel: ctx.GlobalString(flags.LogLevelFlag.Name), + LogTerminal: ctx.GlobalBool(flags.LogTerminalFlag.Name), } } diff --git a/l2os/drivers/l2output/driver.go b/l2os/drivers/l2output/driver.go index f98f9c789341..9db818580566 100644 --- a/l2os/drivers/l2output/driver.go +++ b/l2os/drivers/l2output/driver.go @@ -23,6 +23,7 @@ var bigOne = big.NewInt(1) var supportedL2OutputVersion = l2.Bytes32{} type Config struct { + Log log.Logger Name string L1Client *ethclient.Client L2Client *ethclient.Client @@ -37,6 +38,7 @@ type Driver struct { l2ooContract *l2oo.L2OutputOracle rawL2ooContract *bind.BoundContract walletAddr common.Address + l log.Logger } func NewDriver(cfg Config) (*Driver, error) { @@ -65,6 +67,7 @@ func NewDriver(cfg Config) (*Driver, error) { l2ooContract: l2ooContract, rawL2ooContract: rawL2ooContract, walletAddr: walletAddr, + l: cfg.Log, }, nil } @@ -96,12 +99,12 @@ func (d *Driver) GetBlockRange( // adding one. l2ooTimestamp, err := d.l2ooContract.LatestBlockTimestamp(callOpts) if err != nil { - log.Error(name+" unable to get latest block timestamp", "err", err) + d.l.Error(name+" unable to get latest block timestamp", "err", err) return nil, nil, err } start, err := d.l2ooContract.ComputeL2BlockNumber(callOpts, l2ooTimestamp) if err != nil { - log.Error(name+" unable to compute latest l2 block number", "err", err) + d.l.Error(name+" unable to compute latest l2 block number", "err", err) return nil, nil, err } start.Add(start, bigOne) @@ -112,12 +115,12 @@ func (d *Driver) GetBlockRange( // the latter inspects the timestamp of the latest block. nextTimestamp, err := d.l2ooContract.NextTimestamp(callOpts) if err != nil { - log.Error(name+" unable to get next block timestamp", "err", err) + d.l.Error(name+" unable to get next block timestamp", "err", err) return nil, nil, err } latestHeader, err := d.cfg.L1Client.HeaderByNumber(ctx, nil) if err != nil { - log.Error(name+" unable to retrieve latest header", "err", err) + d.l.Error(name+" unable to retrieve latest header", "err", err) return nil, nil, err } currentTimestamp := big.NewInt(int64(latestHeader.Time)) @@ -126,12 +129,12 @@ func (d *Driver) GetBlockRange( // submitting our L2 output commitment. Return start as the end value which // will signal that there is no work to be done. if currentTimestamp.Cmp(nextTimestamp) < 0 { - log.Info(name+" submission interval has not elapsed", + d.l.Info(name+" submission interval has not elapsed", "currentTimestamp", currentTimestamp, "nextTimestamp", nextTimestamp) return start, start, nil } - log.Info(name+" submission interval has elapsed", + d.l.Info(name+" submission interval has elapsed", "currentTimestamp", currentTimestamp, "nextTimestamp", nextTimestamp) // Otherwise the submission interval has elapsed. Transform the next @@ -139,7 +142,7 @@ func (d *Driver) GetBlockRange( // exclusive. end, err := d.l2ooContract.ComputeL2BlockNumber(callOpts, nextTimestamp) if err != nil { - log.Error(name+" unable to compute next l2 block number", "err", err) + d.l.Error(name+" unable to compute next l2 block number", "err", err) return nil, nil, err } end.Add(end, bigOne) @@ -158,7 +161,7 @@ func (d *Driver) CraftTx( name := d.cfg.Name - log.Info(name+" crafting checkpoint tx", "start", start, "end", end, + d.l.Info(name+" crafting checkpoint tx", "start", start, "end", end, "nonce", nonce) // Fetch the final block in the range, as this is the only L2 output we need @@ -195,7 +198,7 @@ func (d *Driver) CraftTx( } numElements := new(big.Int).Sub(start, end).Uint64() - log.Info(name+" checkpoint constructed", "start", start, "end", end, + d.l.Info(name+" checkpoint constructed", "start", start, "end", end, "nonce", nonce, "blocks_committed", numElements, "checkpoint_block", nextCheckpointBlock) header, err := d.cfg.L1Client.HeaderByNumber(ctx, nil) diff --git a/l2os/flags/flags.go b/l2os/flags/flags.go index e7afc7743904..20a35daf473b 100644 --- a/l2os/flags/flags.go +++ b/l2os/flags/flags.go @@ -89,6 +89,12 @@ var ( Value: "info", EnvVar: prefixEnvVar("LOG_LEVEL"), } + LogTerminalFlag = cli.BoolFlag{ + Name: "log-terminal", + Usage: "If true, outputs logs in terminal format, otherwise prints " + + "in JSON format.", + EnvVar: prefixEnvVar("LOG_TERMINAL"), + } ) var requiredFlags = []cli.Flag{ @@ -106,6 +112,7 @@ var requiredFlags = []cli.Flag{ var optionalFlags = []cli.Flag{ LogLevelFlag, + LogTerminalFlag, } // Flags contains the list of configuration options available to the binary. diff --git a/l2os/l2_output_submitter.go b/l2os/l2_output_submitter.go index 4eef1fd342ad..202d9618f618 100644 --- a/l2os/l2_output_submitter.go +++ b/l2os/l2_output_submitter.go @@ -34,23 +34,39 @@ func Main(version string) func(ctx *cli.Context) error { return func(ctx *cli.Context) error { cfg := NewConfig(ctx) - log.Info("Initializing L2 Output Submitter") + // Set up our logging to stdout. + var logHandler log.Handler + if cfg.LogTerminal { + logHandler = log.StreamHandler(os.Stdout, log.TerminalFormat(true)) + } else { + logHandler = log.StreamHandler(os.Stdout, log.JSONFormat()) + } + + logLevel, err := log.LvlFromString(cfg.LogLevel) + if err != nil { + return err + } + + l := log.New() + l.SetHandler(log.LvlFilterHandler(logLevel, logHandler)) + + l.Info("Initializing L2 Output Submitter") - l2OutputSubmitter, err := NewL2OutputSubmitter(cfg, version) + l2OutputSubmitter, err := NewL2OutputSubmitter(cfg, version, l) if err != nil { - log.Error("Unable to create L2 Output Submitter", "error", err) + l.Error("Unable to create L2 Output Submitter", "error", err) return err } - log.Info("Starting L2 Output Submitter") + l.Info("Starting L2 Output Submitter") if err := l2OutputSubmitter.Start(); err != nil { - log.Error("Unable to start L2 Output Submitter", "error", err) + l.Error("Unable to start L2 Output Submitter", "error", err) return err } defer l2OutputSubmitter.Stop() - log.Info("L2 Output Submitter started") + l.Info("L2 Output Submitter started") interruptChannel := make(chan os.Signal, 1) signal.Notify(interruptChannel, []os.Signal{ @@ -74,18 +90,13 @@ type L2OutputSubmitter struct { // NewL2OutputSubmitter initializes the L2OutputSubmitter, gathering any resources // that will be needed during operation. -func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, error) { - ctx := context.Background() - - // Set up our logging to stdout. - logHandler := log.StreamHandler(os.Stdout, log.TerminalFormat(true)) +func NewL2OutputSubmitter( + cfg Config, + gitVersion string, + l log.Logger, +) (*L2OutputSubmitter, error) { - logLevel, err := log.LvlFromString(cfg.LogLevel) - if err != nil { - return nil, err - } - - log.Root().SetHandler(log.LvlFilterHandler(logLevel, logHandler)) + ctx := context.Background() // Parse l2output wallet private key and L2OO contract address. wallet, err := hdwallet.NewFromMnemonic(cfg.Mnemonic) @@ -130,6 +141,8 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er } txManagerConfig := txmgr.Config{ + Log: l, + Name: "L2Output Submitter", ResubmissionTimeout: cfg.ResubmissionTimeout, ReceiptQueryInterval: time.Second, NumConfirmations: cfg.NumConfirmations, @@ -137,6 +150,7 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er } l2OutputDriver, err := l2output.NewDriver(l2output.Config{ + Log: l, Name: "L2Output Submitter", L1Client: l1Client, L2Client: l2Client, @@ -150,6 +164,7 @@ func NewL2OutputSubmitter(cfg Config, gitVersion string) (*L2OutputSubmitter, er } l2OutputService := NewService(ServiceConfig{ + Log: l, Context: ctx, Driver: l2OutputDriver, PollInterval: cfg.PollInterval, diff --git a/l2os/service.go b/l2os/service.go index d8cf0e58005c..aa88e758ce67 100644 --- a/l2os/service.go +++ b/l2os/service.go @@ -51,6 +51,7 @@ type Driver interface { } type ServiceConfig struct { + Log log.Logger Context context.Context Driver Driver PollInterval time.Duration @@ -61,9 +62,11 @@ type ServiceConfig struct { type Service struct { cfg ServiceConfig txMgr txmgr.TxManager + l log.Logger - done chan struct{} - wg sync.WaitGroup + ctx context.Context + cancel func() + wg sync.WaitGroup } func NewService(cfg ServiceConfig) *Service { @@ -71,10 +74,14 @@ func NewService(cfg ServiceConfig) *Service { cfg.Driver.Name(), cfg.TxManagerConfig, cfg.L1Client, ) + ctx, cancel := context.WithCancel(cfg.Context) + return &Service{ - cfg: cfg, - txMgr: txMgr, - done: make(chan struct{}), + cfg: cfg, + txMgr: txMgr, + l: cfg.Log, + ctx: ctx, + cancel: cancel, } } @@ -85,14 +92,12 @@ func (s *Service) Start() error { } func (s *Service) Stop() error { - close(s.done) + s.cancel() s.wg.Wait() return nil } func (s *Service) eventLoop() { - ctx, cancel := context.WithCancel(s.cfg.Context) - defer cancel() defer s.wg.Done() name := s.cfg.Driver.Name() @@ -102,36 +107,36 @@ func (s *Service) eventLoop() { case <-time.After(s.cfg.PollInterval): // Determine the range of L2 blocks that the submitter has not // processed, and needs to take action on. - log.Info(name + " fetching current block range") - start, end, err := s.cfg.Driver.GetBlockRange(ctx) + s.l.Info(name + " fetching current block range") + start, end, err := s.cfg.Driver.GetBlockRange(s.ctx) if err != nil { - log.Error(name+" unable to get block range", "err", err) + s.l.Error(name+" unable to get block range", "err", err) continue } // No new updates. if start.Cmp(end) == 0 { - log.Info(name+" no updates", "start", start, "end", end) + s.l.Info(name+" no updates", "start", start, "end", end) continue } - log.Info(name+" block range", "start", start, "end", end) + s.l.Info(name+" block range", "start", start, "end", end) // Query for the submitter's current nonce. nonce64, err := s.cfg.L1Client.NonceAt( - ctx, s.cfg.Driver.WalletAddr(), nil, + s.ctx, s.cfg.Driver.WalletAddr(), nil, ) if err != nil { - log.Error(name+" unable to get current nonce", + s.l.Error(name+" unable to get current nonce", "err", err) continue } nonce := new(big.Int).SetUint64(nonce64) tx, err := s.cfg.Driver.CraftTx( - ctx, start, end, nonce, + s.ctx, start, end, nonce, ) if err != nil { - log.Error(name+" unable to craft tx", + s.l.Error(name+" unable to craft tx", "err", err) continue } @@ -139,7 +144,7 @@ func (s *Service) eventLoop() { // Construct the a closure that will update the txn with the current // gas prices. updateGasPrice := func(ctx context.Context) (*types.Transaction, error) { - log.Info(name+" updating batch tx gas price", "start", start, + s.l.Info(name+" updating batch tx gas price", "start", start, "end", end, "nonce", nonce) return s.cfg.Driver.UpdateGasPrice(ctx, tx) @@ -148,19 +153,19 @@ func (s *Service) eventLoop() { // Wait until one of our submitted transactions confirms. If no // receipt is received it's likely our gas price was too low. receipt, err := s.txMgr.Send( - ctx, updateGasPrice, s.cfg.Driver.SendTransaction, + s.ctx, updateGasPrice, s.cfg.Driver.SendTransaction, ) if err != nil { - log.Error(name+" unable to publish tx", "err", err) + s.l.Error(name+" unable to publish tx", "err", err) continue } // The transaction was successfully submitted. - log.Info(name+" tx successfully published", + s.l.Info(name+" tx successfully published", "tx_hash", receipt.TxHash) - case <-s.done: - log.Info(name + " service shutting down") + case <-s.ctx.Done(): + s.l.Info(name + " service shutting down") return } } diff --git a/l2os/txmgr/txmgr.go b/l2os/txmgr/txmgr.go index 90379c3a6217..f09b94dacbee 100644 --- a/l2os/txmgr/txmgr.go +++ b/l2os/txmgr/txmgr.go @@ -21,6 +21,9 @@ type SendTransactionFunc = func(ctx context.Context, tx *types.Transaction) erro // Config houses parameters for altering the behavior of a SimpleTxManager. type Config struct { + // Log is a local logging instance. + Log log.Logger + // Name the name of the driver to appear in log lines. Name string @@ -82,6 +85,7 @@ type SimpleTxManager struct { name string cfg Config backend ReceiptSource + l log.Logger } // NewSimpleTxManager initializes a new SimpleTxManager with the passed Config. @@ -96,6 +100,7 @@ func NewSimpleTxManager( name: name, cfg: cfg, backend: backend, + l: cfg.Log, } } @@ -140,7 +145,7 @@ func (m *SimpleTxManager) Send( strings.Contains(err.Error(), "context canceled") { return } - log.Error(name+" unable to update txn gas price", "err", err) + m.l.Error(name+" unable to update txn gas price", "err", err) return } @@ -148,7 +153,7 @@ func (m *SimpleTxManager) Send( nonce := tx.Nonce() gasTipCap := tx.GasTipCap() gasFeeCap := tx.GasFeeCap() - log.Info(name+" publishing transaction", "txHash", txHash, + m.l.Info(name+" publishing transaction", "txHash", txHash, "nonce", nonce, "gasTipCap", gasTipCap, "gasFeeCap", gasFeeCap) // Sign and publish transaction with current gas price. @@ -159,7 +164,7 @@ func (m *SimpleTxManager) Send( strings.Contains(err.Error(), "context canceled") { return } - log.Error(name+" unable to publish transaction", "err", err) + m.l.Error(name+" unable to publish transaction", "err", err) if sendState.ShouldAbortImmediately() { cancel() } @@ -167,17 +172,17 @@ func (m *SimpleTxManager) Send( return } - log.Info(name+" transaction published successfully", "hash", txHash, + m.l.Info(name+" transaction published successfully", "hash", txHash, "nonce", nonce, "gasTipCap", gasTipCap, "gasFeeCap", gasFeeCap) // Wait for the transaction to be mined, reporting the receipt // back to the main event loop if found. receipt, err := waitMined( - ctxc, m.backend, tx, m.cfg.ReceiptQueryInterval, + m.l, ctxc, m.backend, tx, m.cfg.ReceiptQueryInterval, m.cfg.NumConfirmations, sendState, ) if err != nil { - log.Debug(name+" send tx failed", "hash", txHash, + m.l.Debug(name+" send tx failed", "hash", txHash, "nonce", nonce, "gasTipCap", gasTipCap, "gasFeeCap", gasFeeCap, "err", err) } @@ -186,7 +191,7 @@ func (m *SimpleTxManager) Send( // if more than one receipt is discovered. select { case receiptChan <- receipt: - log.Trace(name+" send tx succeeded", "hash", txHash, + m.l.Trace(name+" send tx succeeded", "hash", txHash, "nonce", nonce, "gasTipCap", gasTipCap, "gasFeeCap", gasFeeCap) default: @@ -241,12 +246,13 @@ func WaitMined( queryInterval time.Duration, numConfirmations uint64, ) (*types.Receipt, error) { - return waitMined(ctx, backend, tx, queryInterval, numConfirmations, nil) + return waitMined(log.New(), ctx, backend, tx, queryInterval, numConfirmations, nil) } // waitMined implements the core functionality of WaitMined, with the option to // pass in a SendState to record whether or not the transaction is mined. func waitMined( + l log.Logger, ctx context.Context, backend ReceiptSource, tx *types.Transaction, @@ -271,11 +277,11 @@ func waitMined( txHeight := receipt.BlockNumber.Uint64() tipHeight, err := backend.BlockNumber(ctx) if err != nil { - log.Error("Unable to fetch block number", "err", err) + l.Error("Unable to fetch block number", "err", err) break } - log.Trace("Transaction mined, checking confirmations", + l.Trace("Transaction mined, checking confirmations", "txHash", txHash, "txHeight", txHeight, "tipHeight", tipHeight, "numConfirmations", numConfirmations) @@ -288,24 +294,24 @@ func waitMined( // tipHeight. The equation is rewritten in this form to avoid // underflows. if txHeight+numConfirmations <= tipHeight+1 { - log.Info("Transaction confirmed", "txHash", txHash) + l.Info("Transaction confirmed", "txHash", txHash) return receipt, nil } // Safe to subtract since we know the LHS above is greater. confsRemaining := (txHeight + numConfirmations) - (tipHeight + 1) - log.Info("Transaction not yet confirmed", "txHash", txHash, + l.Info("Transaction not yet confirmed", "txHash", txHash, "confsRemaining", confsRemaining) case err != nil: - log.Trace("Receipt retrievel failed", "hash", txHash, + l.Trace("Receipt retrievel failed", "hash", txHash, "err", err) default: if sendState != nil { sendState.TxNotMined(txHash) } - log.Trace("Transaction not yet mined", "hash", txHash) + l.Trace("Transaction not yet mined", "hash", txHash) } select { diff --git a/l2os/txmgr/txmgr_test.go b/l2os/txmgr/txmgr_test.go index 81cf9cab01a7..8c99c3012b9e 100644 --- a/l2os/txmgr/txmgr_test.go +++ b/l2os/txmgr/txmgr_test.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" ) @@ -45,6 +46,7 @@ func newTestHarness() *testHarness { func configWithNumConfs(numConfirmations uint64) txmgr.Config { return txmgr.Config{ + Log: log.New(), ResubmissionTimeout: time.Second, ReceiptQueryInterval: 50 * time.Millisecond, NumConfirmations: numConfirmations, diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 828ed2cde67b..b65c7b9d017c 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -156,9 +156,10 @@ func TestL2OutputSubmitter(t *testing.T) { ResubmissionTimeout: 3 * time.Second, SafeAbortNonceTooLowCount: 3, LogLevel: "error", + LogTerminal: true, Mnemonic: cfg.Mnemonic, L2OutputHDPath: l2OutputHDPath, - }, "") + }, "", log.New()) require.Nil(t, err) err = l2OutputSubmitter.Start() diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index c65376a14aeb..0df2e75afafd 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -70,4 +70,5 @@ services: OUTPUT_SUBMITTER_RESUBMISSION_TIMEOUT: 30s OUTPUT_SUBMITTER_MNEMONIC: test test test test test test test test test test test junk OUTPUT_SUBMITTER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" + OUTPUT_SUBMITTER_LOG_TERMINAL: "true" L2OO_ADDRESS: "${L2OO_ADDRESS}" From 08288c07c0ddcd95719b3d61eb3045e91ecdacab Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 1 Apr 2022 05:31:37 -0700 Subject: [PATCH 528/585] feat: enable standalone bss, disable simple bss --- bss/batch_submitter.go | 238 ++++++++++++++++++++++++++++++++++ bss/cmd/bss/main.go | 43 ++++++ opnode/rollup/driver/state.go | 13 -- opnode/test/setup.go | 98 ++++++++++++-- opnode/test/system_test.go | 31 +---- 5 files changed, 377 insertions(+), 46 deletions(-) create mode 100644 bss/batch_submitter.go create mode 100644 bss/cmd/bss/main.go diff --git a/bss/batch_submitter.go b/bss/batch_submitter.go new file mode 100644 index 000000000000..986c0d703e37 --- /dev/null +++ b/bss/batch_submitter.go @@ -0,0 +1,238 @@ +package bss + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" + "time" + + "github.com/ethereum-optimism/optimistic-specs/bss/db" + "github.com/ethereum-optimism/optimistic-specs/bss/sequencer" + "github.com/ethereum-optimism/optimistic-specs/l2os" + "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" + "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + hdwallet "github.com/miguelmota/go-ethereum-hdwallet" + "github.com/urfave/cli" +) + +const ( + // defaultDialTimeout is default duration the service will wait on + // startup to make a connection to either the L1 or L2 backends. + defaultDialTimeout = 5 * time.Second +) + +// Main is the entrypoint into the Batch Submitter. This method returns a +// closure that executes the service and blocks until the service exits. The use +// of a closure allows the parameters bound to the top-level main package, e.g. +// GitVersion, to be captured and used once the function is executed. +func Main(version string) func(ctx *cli.Context) error { + return func(ctx *cli.Context) error { + cfg := NewConfig(ctx) + + // Set up our logging to stdout. + var logHandler log.Handler + if cfg.LogTerminal { + logHandler = log.StreamHandler(os.Stdout, log.TerminalFormat(true)) + } else { + logHandler = log.StreamHandler(os.Stdout, log.JSONFormat()) + } + + logLevel, err := log.LvlFromString(cfg.LogLevel) + if err != nil { + return err + } + + l := log.New() + l.SetHandler(log.LvlFilterHandler(logLevel, logHandler)) + + l.Info("Initializing Batch Submitter") + + batchSubmitter, err := NewBatchSubmitter(cfg, version, l) + if err != nil { + l.Error("Unable to create Batch Submitter", "error", err) + return err + } + + l.Info("Starting Batch Submitter") + + if err := batchSubmitter.Start(); err != nil { + l.Error("Unable to start Batch Submitter", "error", err) + return err + } + defer batchSubmitter.Stop() + + l.Info("Batch Submitter started") + + interruptChannel := make(chan os.Signal, 1) + signal.Notify(interruptChannel, []os.Signal{ + os.Interrupt, + os.Kill, + syscall.SIGTERM, + syscall.SIGQUIT, + }...) + <-interruptChannel + + return nil + } +} + +// BatchSubmitter encapsulates a service responsible for submitting L2 tx +// batches to L1 for availability. +type BatchSubmitter struct { + ctx context.Context + sequencerService *l2os.Service +} + +// NewBatchSubmitter initializes the BatchSubmitter, gathering any resources +// that will be needed during operation. +func NewBatchSubmitter( + cfg Config, + gitVersion string, + l log.Logger, +) (*BatchSubmitter, error) { + + ctx := context.Background() + + // Parse wallet private key that will be used to submit L2 txs to the batch + // inbox address. + wallet, err := hdwallet.NewFromMnemonic(cfg.Mnemonic) + if err != nil { + return nil, err + } + + sequencerPrivKey, err := wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: cfg.SequencerHDPath, + }, + }) + if err != nil { + return nil, err + } + + batchInboxAddress, err := parseAddress(cfg.SequencerBatchInboxAddress) + if err != nil { + return nil, err + } + + genesisHash := common.HexToHash(cfg.SequencerGenesisHash) + + // Connect to L1 and L2 providers. Perform these last since they are the + // most expensive. + l1Client, err := dialEthClientWithTimeout(ctx, cfg.L1EthRpc) + if err != nil { + return nil, err + } + + l2Client, err := dialEthClientWithTimeout(ctx, cfg.L2EthRpc) + if err != nil { + return nil, err + } + + rollupClient, err := dialRollupClientWithTimeout(ctx, cfg.RollupRpc) + if err != nil { + return nil, err + } + + historyDB, err := db.OpenJSONFileDatabase( + cfg.SequencerHistoryDBFilename, 600, genesisHash, + ) + if err != nil { + return nil, err + } + + chainID, err := l1Client.ChainID(ctx) + if err != nil { + return nil, err + } + + txManagerConfig := txmgr.Config{ + Log: l, + Name: "Batch Submitter", + ResubmissionTimeout: cfg.ResubmissionTimeout, + ReceiptQueryInterval: time.Second, + NumConfirmations: cfg.NumConfirmations, + SafeAbortNonceTooLowCount: cfg.SafeAbortNonceTooLowCount, + } + + sequencerDriver, err := sequencer.NewDriver(sequencer.Config{ + Log: l, + Name: "Batch Submitter", + L1Client: l1Client, + L2Client: l2Client, + RollupClient: rollupClient, + MinL1TxSize: cfg.MinL1TxSize, + MaxL1TxSize: cfg.MaxL1TxSize, + BatchInboxAddress: batchInboxAddress, + HistoryDB: historyDB, + ChainID: chainID, + PrivKey: sequencerPrivKey, + }) + if err != nil { + return nil, err + } + + sequencerService := l2os.NewService(l2os.ServiceConfig{ + Log: l, + Context: ctx, + Driver: sequencerDriver, + PollInterval: cfg.PollInterval, + L1Client: l1Client, + TxManagerConfig: txManagerConfig, + }) + + return &BatchSubmitter{ + ctx: ctx, + sequencerService: sequencerService, + }, nil +} + +func (l *BatchSubmitter) Start() error { + return l.sequencerService.Start() +} + +func (l *BatchSubmitter) Stop() { + _ = l.sequencerService.Stop() +} + +// dialEthClientWithTimeout attempts to dial the L1 provider using the provided +// URL. If the dial doesn't complete within defaultDialTimeout seconds, this +// method will return an error. +func dialEthClientWithTimeout(ctx context.Context, url string) ( + *ethclient.Client, error) { + + ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) + defer cancel() + + return ethclient.DialContext(ctxt, url) +} + +// dialRollupClientWithTimeout attempts to dial the RPC provider using the provided +// URL. If the dial doesn't complete within defaultDialTimeout seconds, this +// method will return an error. +func dialRollupClientWithTimeout(ctx context.Context, url string) (*rollupclient.RollupClient, error) { + ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) + defer cancel() + + client, err := rpc.DialContext(ctxt, url) + if err != nil { + return nil, err + } + + return rollupclient.NewRollupClient(client), nil +} + +// parseAddress parses an ETH address from a hex string. This method will fail if +// the address is not a valid hexadecimal address. +func parseAddress(address string) (common.Address, error) { + if common.IsHexAddress(address) { + return common.HexToAddress(address), nil + } + return common.Address{}, fmt.Errorf("invalid address: %v", address) +} diff --git a/bss/cmd/bss/main.go b/bss/cmd/bss/main.go new file mode 100644 index 000000000000..64f7b57e7014 --- /dev/null +++ b/bss/cmd/bss/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "os" + + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli" + + "github.com/ethereum-optimism/optimistic-specs/bss" + "github.com/ethereum-optimism/optimistic-specs/bss/flags" +) + +var ( + Version = "" + GitCommit = "" + GitDate = "" +) + +func main() { + // Set up logger with a default INFO level in case we fail to parse flags, + // otherwise the final critical log won't show what the parsing error was. + log.Root().SetHandler( + log.LvlFilterHandler( + log.LvlInfo, + log.StreamHandler(os.Stdout, log.TerminalFormat(true)), + ), + ) + + app := cli.NewApp() + app.Flags = flags.Flags + app.Version = fmt.Sprintf("%s-%s-%s", Version, GitCommit, GitDate) + app.Name = "bss" + app.Usage = "Batch Submitter Service" + app.Description = "Service for generating and submitting L2 tx batches " + + "to L1" + + app.Action = bss.Main(Version) + err := app.Run(os.Args) + if err != nil { + log.Crit("Application failed", "message", err) + } +} diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 8af5b2f6854f..9e5db088c3e2 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -12,7 +12,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" "github.com/ethereum/go-ethereum/log" ) @@ -240,18 +239,6 @@ func (s *state) createNewL2Block(ctx context.Context) error { s.l2Head = newUnsafeL2Head s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin, "txs", len(batch.Transactions), "time", s.l2Head.Time) - // Submit batch to L1. Right now this is part of the Sequencer loop inside of the rollup node - // but it's much cleaner to have it in a separate service. Will be removed from this loop - // before Bedrock goes into production. - s.wg.Add(1) - go func() { - defer s.wg.Done() - _, err := s.bss.Submit(&s.Config, []*derive.BatchData{batch}) // TODO: submit multiple batches - if err != nil { - s.log.Error("Error submitting batch", "err", err) - } - }() - return nil } diff --git a/opnode/test/setup.go b/opnode/test/setup.go index ae23f15cf237..91470552f077 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -3,10 +3,14 @@ package test import ( "context" "fmt" + "io/ioutil" "math/big" + "os" "strings" "time" + "github.com/ethereum-optimism/optimistic-specs/bss" + "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" @@ -96,14 +100,17 @@ type System struct { wallet *hdwallet.Wallet // Connections to running nodes - nodes map[string]*node.Node - backends map[string]*eth.Ethereum - Clients map[string]*ethclient.Client - RolupGenesis rollup.Genesis - rollupNodes map[string]*rollupNode.OpNode - L2OOContractAddr common.Address - DepositContractAddr common.Address - Mocknet mocknet.Mocknet + nodes map[string]*node.Node + backends map[string]*eth.Ethereum + Clients map[string]*ethclient.Client + RolupGenesis rollup.Genesis + rollupNodes map[string]*rollupNode.OpNode + l2OutputSubmitter *l2os.L2OutputSubmitter + sequencerHistoryDBFileName string + batchSubmitter *bss.BatchSubmitter + L2OOContractAddr common.Address + DepositContractAddr common.Address + Mocknet mocknet.Mocknet } func precompileAlloc() core.GenesisAlloc { @@ -133,6 +140,16 @@ func cliqueExtraData(w accounts.Wallet, signers []string) []byte { } func (sys *System) Close() { + if sys.l2OutputSubmitter != nil { + sys.l2OutputSubmitter.Stop() + } + if sys.batchSubmitter != nil { + sys.batchSubmitter.Stop() + } + if sys.sequencerHistoryDBFileName != "" { + _ = os.Remove(sys.sequencerHistoryDBFileName) + } + for _, node := range sys.rollupNodes { node.Stop() } @@ -461,5 +478,70 @@ func (cfg SystemConfig) start() (*System, error) { } + rollupEndpoint := fmt.Sprintf( + "http://%s:%d", + sys.cfg.Nodes["sequencer"].RPC.ListenAddr, + sys.cfg.Nodes["sequencer"].RPC.ListenPort, + ) + + // L2Output Submitter + sys.l2OutputSubmitter, err = l2os.NewL2OutputSubmitter(l2os.Config{ + L1EthRpc: "ws://127.0.0.1:9090", + L2EthRpc: sys.cfg.Nodes["sequencer"].L2NodeAddr, + RollupRpc: rollupEndpoint, + L2OOAddress: sys.L2OOContractAddr.String(), + PollInterval: 50 * time.Millisecond, + NumConfirmations: 1, + ResubmissionTimeout: 3 * time.Second, + SafeAbortNonceTooLowCount: 3, + LogLevel: "info", + LogTerminal: true, + Mnemonic: sys.cfg.Mnemonic, + L2OutputHDPath: sys.cfg.L2OutputHDPath, + }, "", log.New()) + if err != nil { + return nil, fmt.Errorf("unable to setup l2 output submitter: %w", err) + } + + if err := sys.l2OutputSubmitter.Start(); err != nil { + return nil, fmt.Errorf("unable to start l2 output submitter: %w", err) + } + + sequencerHistoryDBFile, err := ioutil.TempFile("", "bss.*.json") + if err != nil { + return nil, fmt.Errorf("unable to create sequencer history db file: %w", err) + } + sys.sequencerHistoryDBFileName = sequencerHistoryDBFile.Name() + if err = sequencerHistoryDBFile.Close(); err != nil { + return nil, fmt.Errorf("unable to close sequencer history db file: %w", err) + } + + // Batch Submitter + sys.batchSubmitter, err = bss.NewBatchSubmitter(bss.Config{ + L1EthRpc: "ws://127.0.0.1:9090", + L2EthRpc: sys.cfg.Nodes["sequencer"].L2NodeAddr, + RollupRpc: rollupEndpoint, + MinL1TxSize: 1, + MaxL1TxSize: 120000, + PollInterval: 50 * time.Millisecond, + NumConfirmations: 1, + ResubmissionTimeout: 5 * time.Second, + SafeAbortNonceTooLowCount: 3, + LogLevel: "info", + LogTerminal: true, + Mnemonic: sys.cfg.Mnemonic, + SequencerHDPath: sys.cfg.BatchSubmitterHDPath, + SequencerHistoryDBFilename: sys.sequencerHistoryDBFileName, + SequencerGenesisHash: sys.RolupGenesis.L2.Hash.String(), + SequencerBatchInboxAddress: sys.cfg.RollupConfig.BatchInboxAddress.String(), + }, "", log.New()) + if err != nil { + return nil, fmt.Errorf("failed to setup batch submitter: %w", err) + } + + if err := sys.batchSubmitter.Start(); err != nil { + return nil, fmt.Errorf("unable to start batch submitter: %w", err) + } + return sys, nil } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index b65c7b9d017c..9958309c0c9a 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" @@ -54,6 +53,10 @@ const ( bssHDPath = "m/44'/60'/0'/0/4" ) +var ( + batchInboxAddress = common.Address{0xff, 0x02} +) + func defaultSystemConfig(t *testing.T) SystemConfig { return SystemConfig{ Mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness", @@ -113,7 +116,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { L1ChainID: big.NewInt(900), // TODO pick defaults FeeRecipientAddress: common.Address{0xff, 0x01}, - BatchInboxAddress: common.Address{0xff, 0x02}, + BatchInboxAddress: batchInboxAddress, // Batch Sender address is filled out in system start DepositContractAddress: MockDepositContractAddr, }, @@ -145,27 +148,6 @@ func TestL2OutputSubmitter(t *testing.T) { initialSroTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{}) require.Nil(t, err) - // L2Output Submitter - l2OutputSubmitter, err := l2os.NewL2OutputSubmitter(l2os.Config{ - L1EthRpc: "ws://127.0.0.1:9090", - L2EthRpc: cfg.Nodes["sequencer"].L2NodeAddr, - RollupRpc: fmt.Sprintf("http://%s:%d", cfg.Nodes["sequencer"].RPC.ListenAddr, cfg.Nodes["sequencer"].RPC.ListenPort), - L2OOAddress: sys.L2OOContractAddr.String(), - PollInterval: 50 * time.Millisecond, - NumConfirmations: 1, - ResubmissionTimeout: 3 * time.Second, - SafeAbortNonceTooLowCount: 3, - LogLevel: "error", - LogTerminal: true, - Mnemonic: cfg.Mnemonic, - L2OutputHDPath: l2OutputHDPath, - }, "", log.New()) - require.Nil(t, err) - - err = l2OutputSubmitter.Start() - require.Nil(t, err) - defer l2OutputSubmitter.Stop() - // Wait for batch submitter to update L2 output oracle. timeoutCh := time.After(15 * time.Second) for { @@ -215,6 +197,7 @@ func TestSystemE2E(t *testing.T) { if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } + cfg := defaultSystemConfig(t) sys, err := cfg.start() @@ -386,8 +369,6 @@ func TestMissingBatchE2E(t *testing.T) { cfg := defaultSystemConfig(t) // Specifically set batch submitter balance to stop batches from being included cfg.Premine[bssHDPath] = 0 - // Don't pollute log with expected "Error submitting batch" logs - cfg.Loggers["sequencer"] = testlog.Logger(t, log.LvlCrit) sys, err := cfg.start() require.Nil(t, err, "Error starting up system") From ef43fbc07f2283f65e31d40ea95a8c6d3e8d6b01 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 15 Apr 2022 08:00:31 -0400 Subject: [PATCH 529/585] feat: remove simple bss --- opnode/bss/submitter.go | 100 ----------------------------- opnode/node/node.go | 13 +--- opnode/rollup/driver/driver.go | 8 +-- opnode/rollup/driver/state.go | 4 +- opnode/rollup/driver/state_test.go | 2 +- 5 files changed, 5 insertions(+), 122 deletions(-) delete mode 100644 opnode/bss/submitter.go diff --git a/opnode/bss/submitter.go b/opnode/bss/submitter.go deleted file mode 100644 index 4bb39fc67afd..000000000000 --- a/opnode/bss/submitter.go +++ /dev/null @@ -1,100 +0,0 @@ -package bss - -import ( - "bytes" - "context" - "crypto/ecdsa" - "errors" - "math/big" - "time" - - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" -) - -type BatchSubmitter struct { - Client *ethclient.Client - ToAddress common.Address - ChainID *big.Int - PrivKey *ecdsa.PrivateKey -} - -// Submit creates & submits batches to L1. Blocks until the transaction is included. -// Return the tx hash as well as a possible error. -func (b *BatchSubmitter) Submit(config *rollup.Config, batches []*derive.BatchData) (common.Hash, error) { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - - var buf bytes.Buffer - if err := derive.EncodeBatches(config, batches, &buf); err != nil { - return common.Hash{}, err - } - - tip, err := b.Client.SuggestGasTipCap(ctx) - if err != nil { - return common.Hash{}, err - } - fee, err := b.Client.SuggestGasPrice(ctx) - if err != nil { - return common.Hash{}, err - } - - // Note: If the BSS acts up, look into the pending nonce. - addr := crypto.PubkeyToAddress(b.PrivKey.PublicKey) - nonce, err := b.Client.PendingNonceAt(ctx, addr) - if err != nil { - return common.Hash{}, err - } - - rawTx := &types.DynamicFeeTx{ - ChainID: b.ChainID, - Nonce: nonce, - To: &b.ToAddress, - GasTipCap: tip, - GasFeeCap: fee, - Data: buf.Bytes(), - } - - // No contract execution so we just pay intrinsic gas. - // If we add contract execution, making it gas usage deterministic is very helpful. - gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true) - if err != nil { - return common.Hash{}, err - } - rawTx.Gas = gas - - tx, err := types.SignNewTx(b.PrivKey, types.LatestSignerForChainID(b.ChainID), rawTx) - if err != nil { - return common.Hash{}, err - } - - err = b.Client.SendTransaction(ctx, tx) - if err != nil { - return common.Hash{}, err - } - - timeout := time.After(30 * time.Second) - - for { - receipt, err := b.Client.TransactionReceipt(context.Background(), tx.Hash()) - if receipt != nil { - return tx.Hash(), nil - } else if err != nil && !errors.Is(err, ethereum.NotFound) { - return common.Hash{}, err - } - <-time.After(150 * time.Millisecond) - - select { - case <-timeout: - return common.Hash{}, errors.New("timeout") - default: - } - } - -} diff --git a/opnode/node/node.go b/opnode/node/node.go index 76b50da9c07c..8d663f013315 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -13,14 +13,12 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/backoff" - "github.com/ethereum-optimism/optimistic-specs/opnode/bss" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l1" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/driver" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" @@ -104,16 +102,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* return nil, err } - var submitter *bss.BatchSubmitter - if cfg.Sequencer { - submitter = &bss.BatchSubmitter{ - Client: ethclient.NewClient(l1Node), - ToAddress: cfg.Rollup.BatchInboxAddress, - ChainID: cfg.Rollup.L1ChainID, - PrivKey: cfg.SubmitterPrivKey, - } - } - engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), submitter, cfg.Sequencer) + engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), cfg.Sequencer) l2Engines = append(l2Engines, engine) } diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index c27890cc464a..e2d7d3f98bc3 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -58,11 +58,7 @@ type outputInterface interface { createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) } -func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, submitter BatchSubmitter, sequencer bool) *Driver { - if sequencer && submitter == nil { - log.Error("Bad configuration") - // TODO: return error - } +func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, sequencer bool) *Driver { output := &outputImpl{ Config: cfg, dl: l1, @@ -70,7 +66,7 @@ func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, log: log, } return &Driver{ - s: NewState(log, cfg, l1, l2, output, submitter, sequencer), + s: NewState(log, cfg, l1, l2, output, sequencer), } } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 9e5db088c3e2..614e0e254a02 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -33,7 +33,6 @@ type state struct { l1 L1Chain l2 L2Chain output outputInterface - bss BatchSubmitter log log.Logger done chan struct{} @@ -41,7 +40,7 @@ type state struct { wg gosync.WaitGroup } -func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, submitter BatchSubmitter, sequencer bool) *state { +func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, sequencer bool) *state { return &state{ Config: config, done: make(chan struct{}), @@ -49,7 +48,6 @@ func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, outp l1: l1, l2: l2, output: output, - bss: submitter, sequencer: sequencer, } } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 85179d4fee8a..ced26036c0fd 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -145,7 +145,7 @@ func (tc *stateTestCase) Run(t *testing.T) { return r.l2Head, r.l2Head, false, r.err } config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis, BlockTime: 2} - state := NewState(log, config, chainSource, chainSource, outputHandlerFn(outputHandler), nil, false) + state := NewState(log, config, chainSource, chainSource, outputHandlerFn(outputHandler), false) defer func() { assert.NoError(t, state.Close(), "Error closing state") }() From 153e21d3aed4eda8019c4beb121c1d4dd425c8e9 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 15 Apr 2022 08:16:57 -0400 Subject: [PATCH 530/585] feat: add bss to devnet --- Makefile | 8 ++++-- ops/Dockerfile.bss | 22 ++++++++++++++++ ops/Dockerfile.l2os | 6 +++-- ops/Dockerfile.opnode | 5 +++- ops/bss-entrypoint.sh | 14 +++++++++++ ops/devnet-up.sh | 9 ++++++- ops/docker-compose.yml | 25 +++++++++++++++++++ ops/genesis-l1.json | 3 +++ ops/rollup.json | 2 +- ops/test-integration.sh | 0 .../test/000_withdrawals.spec.ts | 2 +- 11 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 ops/Dockerfile.bss create mode 100644 ops/bss-entrypoint.sh mode change 100644 => 100755 ops/devnet-up.sh mode change 100644 => 100755 ops/test-integration.sh diff --git a/Makefile b/Makefile index faea4c67e4b9..4423dac26711 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ COMPOSEFLAGS=-d ITESTS_L2_HOST=http://localhost:9545 -build: submodules opnode contracts integration-tests +build: build-go contracts integration-tests .PHONY: build -build-go: submodules opnode l2os +build-go: submodules opnode l2os bss .PHONY: build-go build-ts: submodules contracts integration-tests @@ -64,6 +64,10 @@ devnet-genesis: bash ./ops/devnet-genesis.sh .PHONY: devnet-genesis +bss: + go build -o ./bin/bss ./bss/cmd/bss +.PHONY: bss + l2os: go build -o ./bin/l2os ./l2os/cmd/l2os .PHONY: l2os diff --git a/ops/Dockerfile.bss b/ops/Dockerfile.bss new file mode 100644 index 000000000000..4913db53dee6 --- /dev/null +++ b/ops/Dockerfile.bss @@ -0,0 +1,22 @@ +FROM golang:1.18.0-alpine3.15 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 -x + +COPY Makefile /app/Makefile +COPY ./opnode /app/opnode +COPY ./l2os /app/l2os +COPY ./bss /app/bss + +RUN make bss + +FROM alpine:3.15 + +COPY --from=builder /app/bin/bss /usr/local/bin + +ENTRYPOINT ["bss"] diff --git a/ops/Dockerfile.l2os b/ops/Dockerfile.l2os index 4cadc3577864..4141a870b3da 100644 --- a/ops/Dockerfile.l2os +++ b/ops/Dockerfile.l2os @@ -2,14 +2,16 @@ FROM golang:1.18.0-alpine3.15 as builder RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash -COPY Makefile /app/Makefile COPY go.mod /app/go.mod COPY go.sum /app/go.sum WORKDIR /app +RUN go mod download -x -COPY ./l2os /app/l2os +COPY Makefile /app/Makefile COPY ./opnode /app/opnode +COPY ./l2os /app/l2os + RUN make l2os FROM alpine:3.15 diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode index ba07689d1d04..1b712e2c7134 100644 --- a/ops/Dockerfile.opnode +++ b/ops/Dockerfile.opnode @@ -2,12 +2,15 @@ FROM golang:1.18.0-alpine3.15 as builder RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash -COPY Makefile /app/Makefile COPY go.mod /app/go.mod COPY go.sum /app/go.sum WORKDIR /app +RUN go mod download -x + +COPY Makefile /app/Makefile COPY ./opnode /app/opnode + RUN make opnode FROM alpine:3.15 diff --git a/ops/bss-entrypoint.sh b/ops/bss-entrypoint.sh new file mode 100644 index 000000000000..1a66f6c071df --- /dev/null +++ b/ops/bss-entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -exu + +curl \ + --fail \ + --retry 10 \ + --retry-delay 2 \ + --retry-connrefused \ + -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + http://l1:8545 + +exec bss diff --git a/ops/devnet-up.sh b/ops/devnet-up.sh old mode 100644 new mode 100755 index fa17d0220a7a..6e59fa459804 --- a/ops/devnet-up.sh +++ b/ops/devnet-up.sh @@ -135,10 +135,17 @@ jq ". | .genesis.l1.hash = \"$(echo $L1_GENESIS | jq -r '.result.hash')\"" < ./o jq ". | .genesis.l2_time = $(echo $L2_GENESIS | jq -r '.result.timestamp' | xargs printf "%d")" | \ jq ". | .deposit_contract_address = \"$DEPOSIT_CONTRACT_ADDRESS\"" > ./.devnet/rollup.json + +SEQUENCER_GENESIS_HASH="$(echo $L2_GENESIS | jq -r '.result.hash')" +SEQUENCER_BATCH_INBOX_ADDRESS="$(cat ./ops/rollup.json | jq -r '.batch_inbox_address')" + # Bring up everything else. cd ops echo "Bringing up devnet..." -L2OO_ADDRESS="$L2OO_ADDRESS" docker-compose up -d l2os +L2OO_ADDRESS="$L2OO_ADDRESS" \ + SEQUENCER_GENESIS_HASH="$SEQUENCER_GENESIS_HASH" \ + SEQUENCER_BATCH_INBOX_ADDRESS="$SEQUENCER_BATCH_INBOX_ADDRESS" \ + docker-compose up -d l2os bss cd ../ echo "Devnet ready." diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 0df2e75afafd..ed986ec0979d 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -72,3 +72,28 @@ services: OUTPUT_SUBMITTER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" OUTPUT_SUBMITTER_LOG_TERMINAL: "true" L2OO_ADDRESS: "${L2OO_ADDRESS}" + + bss: + depends_on: + - l1 + - l2 + - opnode + build: + context: ../ + dockerfile: ./ops/Dockerfile.bss + environment: + L1_ETH_RPC: http://l1:8545 + L2_ETH_RPC: http://l2:8545 + ROLLUP_RPC: http://opnode:8545 + BATCH_SUBMITTER_MIN_L1_TX_SIZE_BYTES: 1 + BATCH_SUBMITTER_MAX_L1_TX_SIZE_BYTES: 120000 + BATCH_SUBMITTER_POLL_INTERVAL: 1s + BATCH_SUBMITTER_NUM_CONFIRMATIONS: 1 + BATCH_SUBMITTER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 + BATCH_SUBMITTER_RESUBMISSION_TIMEOUT: 30s + BATCH_SUBMITTER_MNEMONIC: test test test test test test test test test test test junk + BATCH_SUBMITTER_SEQUENCER_HD_PATH: "m/44'/60'/0'/0/2" + BATCH_SUBMITTER_SEQUENCER_HISTORY_DB_FILENAME: "history_db.json" + BATCH_SUBMITTER_SEQUENCER_GENESIS_HASH: "${SEQUENCER_GENESIS_HASH}" + BATCH_SUBMITTER_SEQUENCER_BATCH_INBOX_ADDRESS: "${SEQUENCER_BATCH_INBOX_ADDRESS}" + BATCH_SUBMITTER_LOG_TERMINAL: "true" diff --git a/ops/genesis-l1.json b/ops/genesis-l1.json index 74f1a1b66640..d766ef98cd3c 100644 --- a/ops/genesis-l1.json +++ b/ops/genesis-l1.json @@ -796,6 +796,9 @@ "de3829a23df1479438622a08a116e8eb3f620bb5": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, + "3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, "f39fd6e51aad88f6f4ce6ab8827279cfffb92266": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, diff --git a/ops/rollup.json b/ops/rollup.json index 7285c0391d78..586f6b47dac4 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -23,7 +23,7 @@ "batch_inbox_address": "0xff00000000000000000000000000000000000002", - "batch_sender_address": "0xde3829a23df1479438622a08a116e8eb3f620bb5", + "batch_sender_address": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", "deposit_contract_address": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001" } diff --git a/ops/test-integration.sh b/ops/test-integration.sh old mode 100644 new mode 100755 diff --git a/packages/integration-tests/test/000_withdrawals.spec.ts b/packages/integration-tests/test/000_withdrawals.spec.ts index 27572483bdf9..bb01c90d6784 100644 --- a/packages/integration-tests/test/000_withdrawals.spec.ts +++ b/packages/integration-tests/test/000_withdrawals.spec.ts @@ -171,7 +171,7 @@ describe('Withdrawals', () => { }) } return output != constants.HashZero - }, 2000, 240) + }, 2000, 2*difference) // suppress compilation errors since Typescript cannot detect // that awaitCondition above will throw if it times out. From a087de8018d37c4f1be117951bcd0e20dc1d31bd Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Wed, 4 May 2022 05:20:49 -0700 Subject: [PATCH 531/585] fix: ci build bindings (#406) * ci: build bindings in ci * ci: install abigen * ci: fix geth install * bindings: regenerate * contracts: no metadata hash in contracts * bindings: regenerate --- .github/workflows/go-ci.yml | 46 ++++++++++++++++++++++++++ l2os/bindings/l2oo/l2_output_oracle.go | 2 +- packages/contracts/foundry.toml | 1 + 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index c3510c21227c..c461598fc7d3 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -30,3 +30,49 @@ jobs: run: go test -coverpkg=./... -coverprofile=coverage.out -covermode=atomic ./... - name: Upload coverage output uses: codecov/codecov-action@v2 + + build: + runs-on: ubuntu-latest + name: Builds Bindings + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.18 + + - name: Install abigen + run: | + git clone https://github.com/ethereum/go-ethereum /tmp/geth + cd /tmp/geth + make devtools + + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly + + - uses: actions/setup-node@v2 + with: + node-version: "16" + cache: "yarn" + + - name: Install Dependencies + run: | + cd packages/contracts + yarn install + + - name: opnode Contracts + run: | + cd opnode/contracts + make + git diff --exit-code + + - name: l2os Bindings + run: | + cd l2os + make bindings + git diff --exit-code diff --git a/l2os/bindings/l2oo/l2_output_oracle.go b/l2os/bindings/l2oo/l2_output_oracle.go index 2dd74f953165..932bb9f5e18a 100644 --- a/l2os/bindings/l2oo/l2_output_oracle.go +++ b/l2os/bindings/l2oo/l2_output_oracle.go @@ -31,7 +31,7 @@ var ( // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x61010060405234801561001157600080fd5b50604051610e66380380610e6683398101604081905261003091610148565b610039336100f8565b61004385876101ac565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052600082815260026020526040902084905560c0839052600182905560e08290526100ed816100f8565b5050505050506101ce565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561016157600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b038116811461019e57600080fd5b809150509295509295509295565b6000826101c957634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610c36610230600039600081816101af015281816102d401526103aa01526000818161028e01526103db01526000818160e801526103890152600081816101e30152818161085801526108880152610c366000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad1461027c578063f2fde38b146102b057600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b806325188104116100b057806325188104146101535780632b5d15d914610168578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d5780630c1952d31461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610aeb565b6102d0565b34801561014957600080fd5b5061010a60015481565b610166610161366004610b04565b610405565b005b34801561017457600080fd5b50610166610183366004610aeb565b6106ee565b34801561019457600080fd5b5061010a610884565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b506101666108b9565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b5061010a61026a366004610aeb565b60009081526002602052604090205490565b34801561028857600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102bc57600080fd5b506101666102cb366004610b36565b610946565b60007f0000000000000000000000000000000000000000000000000000000000000000821015610387576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008303816103d8576103d8610b73565b047f0000000000000000000000000000000000000000000000000000000000000000600101019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b428310610515576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f6500000000000000000000000000000000000000000000000000000000000000606482015260840161037e565b61051d610884565b83146105ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d70000000000000000000000000000000000000606482015260840161037e565b83610612576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000604482015260640161037e565b81156106a857818140146106a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e00000000000000606482015260840161037e565b600083815260026020526040808220869055600185905551849186917f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b9190a350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b600154600090815260026020526040902054818114610810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e00000000000000000000000000000000000000000000000000606482015260840161037e565b60015460405182907f36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f26690600090a3600180546000908152600260205260408120555461087d907f000000000000000000000000000000000000000000000000000000000000000090610bd1565b6001555050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546108b49190610be8565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331461093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b6109446000610a76565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b73ffffffffffffffffffffffffffffffffffffffff8116610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161037e565b610a7381610a76565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610afd57600080fd5b5035919050565b60008060008060808587031215610b1a57600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610b4857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610b6c57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610be357610be3610ba2565b500390565b60008219821115610bfb57610bfb610ba2565b50019056fea26469706673582212202b75e7488f5da959d6f6a42e7994006e9678d900e97b36879b2d9afc9ee2659b64736f6c634300080a0033", + Bin: "0x61010060405234801561001157600080fd5b50604051610e3d380380610e3d83398101604081905261003091610148565b610039336100f8565b61004385876101ac565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052600082815260026020526040902084905560c0839052600182905560e08290526100ed816100f8565b5050505050506101ce565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561016157600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b038116811461019e57600080fd5b809150509295509295509295565b6000826101c957634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610c0d610230600039600081816101af015281816102d401526103aa01526000818161028e01526103db01526000818160e801526103890152600081816101e30152818161085801526108880152610c0d6000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad1461027c578063f2fde38b146102b057600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b806325188104116100b057806325188104146101535780632b5d15d914610168578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d5780630c1952d31461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610aeb565b6102d0565b34801561014957600080fd5b5061010a60015481565b610166610161366004610b04565b610405565b005b34801561017457600080fd5b50610166610183366004610aeb565b6106ee565b34801561019457600080fd5b5061010a610884565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b506101666108b9565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b5061010a61026a366004610aeb565b60009081526002602052604090205490565b34801561028857600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102bc57600080fd5b506101666102cb366004610b36565b610946565b60007f0000000000000000000000000000000000000000000000000000000000000000821015610387576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008303816103d8576103d8610b73565b047f0000000000000000000000000000000000000000000000000000000000000000600101019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b428310610515576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f6500000000000000000000000000000000000000000000000000000000000000606482015260840161037e565b61051d610884565b83146105ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d70000000000000000000000000000000000000606482015260840161037e565b83610612576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000604482015260640161037e565b81156106a857818140146106a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e00000000000000606482015260840161037e565b600083815260026020526040808220869055600185905551849186917f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b9190a350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b600154600090815260026020526040902054818114610810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e00000000000000000000000000000000000000000000000000606482015260840161037e565b60015460405182907f36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f26690600090a3600180546000908152600260205260408120555461087d907f000000000000000000000000000000000000000000000000000000000000000090610bd1565b6001555050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546108b49190610be8565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331461093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b6109446000610a76565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b73ffffffffffffffffffffffffffffffffffffffff8116610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161037e565b610a7381610a76565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610afd57600080fd5b5035919050565b60008060008060808587031215610b1a57600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610b4857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610b6c57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610be357610be3610ba2565b500390565b60008219821115610bfb57610bfb610ba2565b50019056fea164736f6c634300080a000a", } // L2OutputOracleABI is the input ABI used to generate the binding from. diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml index 258788e3e239..a08e0b7df33b 100644 --- a/packages/contracts/foundry.toml +++ b/packages/contracts/foundry.toml @@ -10,3 +10,4 @@ remappings = [ '@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/', '@eth-optimism/contracts/=node_modules/@eth-optimism/contracts/' ] +bytecode_hash = "none" From db4b4ffe6c719cb01b10e77829de056ae5f4196e Mon Sep 17 00:00:00 2001 From: inphi Date: Wed, 4 May 2022 19:30:36 -0400 Subject: [PATCH 532/585] opnode: Avoid busy-waiting while L2 head is behind L1 In the state select loop, we immediately request for new L2 blocks whenever the latest L1 origin is behind L1. This can be an issue as we attempt to re-request the latest L2 block without any delay. This is a DoS hazard particularly when an L2 block cannot be retrieved because either the `L1Chain` or `L2Chain` backends have errors. Another problem with this is that other, more useful events in the state select loop, are less likely to be scheduled by the Go runtime due to the busy-wait. Adding a small delay, before calling `reql2BlockCreation` of about 10ms should be enough to prevent issues. --- opnode/rollup/driver/state.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 614e0e254a02..745c12a20b85 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -352,7 +352,8 @@ func (s *state) loop() { // TODO: If we want to consider confirmations, need to consider here too. if s.l1Head.Number > s.l2Head.L1Origin.Number { s.log.Trace("Asking for a second L2 block asap", "l2Head", s.l2Head) - reqL2BlockCreation() + // But not too quickly to minimize busy-waiting for new blocks + time.AfterFunc(time.Millisecond*10, reqL2BlockCreation) } case newL1Head := <-s.l1Heads: From e6d8d443d3dcf73ac543584458dcf9bdd2336d09 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 5 May 2022 09:55:55 -0700 Subject: [PATCH 533/585] opnode: Fix Incorrect error handling when creating an L2 block (#391) * opnode: Fix Incorrect error handling when creating an L2 block This is an issue ToB identified (issue #8). What happens is that the ethereum.NotFound error would never be returned, but in general if there is an error in the lookup, the state loop should keep going. * opnode: Properly wrap errors in l1/source.go --- opnode/l1/source.go | 14 +++++++------- opnode/rollup/driver/state.go | 6 ++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/opnode/l1/source.go b/opnode/l1/source.go index 7d78ddc2d30f..3b7d7db177cf 100644 --- a/opnode/l1/source.go +++ b/opnode/l1/source.go @@ -124,7 +124,7 @@ type Source struct { func NewSource(client RPCClient, log log.Logger, config *SourceConfig) (*Source, error) { if err := config.Check(); err != nil { - return nil, fmt.Errorf("bad config, cannot create L1 source: %v", err) + return nil, fmt.Errorf("bad config, cannot create L1 source: %w", err) } // no errors if the size is positive, as already validated by Check() above. receiptsCache, _ := lru.New(config.ReceiptsCacheSize) @@ -277,7 +277,7 @@ func (s *Source) FetchAllTransactions(ctx context.Context, window []eth.BlockID) if blockRequests[i].Error == nil { info, txs, err := blockRequests[i].Result.(*rpcBlock).Info(s.trustRPC) if err != nil { - return nil, fmt.Errorf("bad block data for block %s: %v", blockRequests[i].Args[0], err) + return nil, fmt.Errorf("bad block data for block %s: %w", blockRequests[i].Args[0], err) } s.headersCache.Add(info.hash, info) s.transactionsCache.Add(info.hash, txs) @@ -287,7 +287,7 @@ func (s *Source) FetchAllTransactions(ctx context.Context, window []eth.BlockID) for i := 0; i < len(blockRequests); i++ { if blockRequests[i].Error != nil { - return nil, fmt.Errorf("failed to retrieve transactions of block %s in batch of %d blocks: %v", window[i], len(blockRequests), blockRequests[i].Error) + return nil, fmt.Errorf("failed to retrieve transactions of block %s in batch of %d blocks: %w", window[i], len(blockRequests), blockRequests[i].Error) } } @@ -297,7 +297,7 @@ func (s *Source) FetchAllTransactions(ctx context.Context, window []eth.BlockID) func (s *Source) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { head, err := s.InfoHead(ctx) if err != nil { - return eth.L1BlockRef{}, fmt.Errorf("failed to fetch head header: %v", err) + return eth.L1BlockRef{}, fmt.Errorf("failed to fetch head header: %w", err) } return head.BlockRef(), nil } @@ -305,7 +305,7 @@ func (s *Source) L1HeadBlockRef(ctx context.Context) (eth.L1BlockRef, error) { func (s *Source) L1BlockRefByNumber(ctx context.Context, l1Num uint64) (eth.L1BlockRef, error) { head, err := s.InfoByNumber(ctx, l1Num) if err != nil { - return eth.L1BlockRef{}, fmt.Errorf("failed to fetch header by num %d: %v", l1Num, err) + return eth.L1BlockRef{}, fmt.Errorf("failed to fetch header by num %d: %w", l1Num, err) } return head.BlockRef(), nil } @@ -345,7 +345,7 @@ func (s *Source) L1Range(ctx context.Context, begin eth.BlockID, max uint64) ([] } info, err := result.Info(s.trustRPC) if err != nil { - return nil, fmt.Errorf("bad header data for block %s: %v", headerRequests[i].Args[0], err) + return nil, fmt.Errorf("bad header data for block %s: %w", headerRequests[i].Args[0], err) } s.headersCache.Add(info.hash, info) out = append(out, info.ID()) @@ -359,7 +359,7 @@ func (s *Source) L1Range(ctx context.Context, begin eth.BlockID, max uint64) ([] } else if errors.Is(headerRequests[i].Error, ethereum.NotFound) { break // no more headers from here } else { - return nil, fmt.Errorf("failed to retrieve block: %s: %v", headerRequests[i].Args[0], headerRequests[i].Error) + return nil, fmt.Errorf("failed to retrieve block: %s: %w", headerRequests[i].Args[0], headerRequests[i].Error) } } return out, nil diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 745c12a20b85..e05ce3f0e58c 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -2,13 +2,10 @@ package driver import ( "context" - "errors" "fmt" gosync "sync" "time" - "github.com/ethereum/go-ethereum" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" @@ -183,7 +180,8 @@ func (s *state) findL1Origin(ctx context.Context) (eth.L1BlockRef, error) { // Attempt to find the next L1 origin block, where the next origin is the immediate child of // the current origin block. nextOrigin, err := s.l1.L1BlockRefByNumber(ctx, currentOrigin.Number+1) - if errors.Is(err, ethereum.NotFound) { + if err != nil { + s.log.Error("Failed to get next origin. Falling back to current origin", "err", err) return currentOrigin, nil } From 3a1f6ff85374b0c335f41ff047d6360c335a22e6 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Thu, 5 May 2022 12:40:50 -0700 Subject: [PATCH 534/585] opnode: Fuzz manual ABI parsing (#384) * opnode: Add OptimismPortal deployed bytecode This is important for fuzzing * opnode: Add differential fuzzing test for deposit events fixup: Proper tests * build: Add fuzz target * opnode: Fix ineffctual error assignment * opnode: More fuzzing cleanup The purpose of this is to make it more likely that the deposit succeeds and that we fuzz what we actually want to fuzz (the parsing). --- .github/workflows/go-ci.yml | 15 ++ go.mod | 1 + go.sum | 2 + opnode/Makefile | 9 +- opnode/contracts/Makefile | 17 +- .../deposit/optimism_portal_deployed.go | 5 + opnode/rollup/derive/fuzz_parsers_test.go | 246 ++++++++++++++++++ 7 files changed, 292 insertions(+), 3 deletions(-) create mode 100644 opnode/contracts/deposit/optimism_portal_deployed.go create mode 100644 opnode/rollup/derive/fuzz_parsers_test.go diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index c461598fc7d3..878dc7550300 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -76,3 +76,18 @@ jobs: cd l2os make bindings git diff --exit-code + + opnode-fuzz: + runs-on: ubuntu-latest + name: Fuzz parsers in the opnode + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.18 + - name: Checkout code + uses: actions/checkout@v2 + - name: Fuzz + run: | + cd opnode + make fuzz diff --git a/go.mod b/go.mod index 4a52b43bbae2..739b405c6026 100644 --- a/go.mod +++ b/go.mod @@ -58,6 +58,7 @@ require ( github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-cmp v0.5.8 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect diff --git a/go.sum b/go.sum index 84fd706eacb2..efdcbf9d37ca 100644 --- a/go.sum +++ b/go.sum @@ -362,6 +362,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= diff --git a/opnode/Makefile b/opnode/Makefile index d2c8a6c09c55..409863ae8683 100644 --- a/opnode/Makefile +++ b/opnode/Makefile @@ -19,8 +19,15 @@ test: lint: golangci-lint run -E asciicheck,goimports,misspell ./... +fuzz: + go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoRoundTrip ./rollup/derive + go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoAgainstContract ./rollup/derive + go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzUnmarshallLogEvent ./rollup/derive + + .PHONY: \ bss \ clean \ test \ - lint + lint \ + fuzz diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index dd89831eb026..20dfa49c0b7e 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -5,7 +5,7 @@ OPTIMISM_PORTAL := ../../packages/contracts/contracts/L1/OptimismPortal.sol L1_BLOCK_INFO := ../../packages/contracts/contracts/L2/L1Block.sol -bindings: bindings-l1-block-info bindings-optimism-portal deployed-bin-l1-block-info +bindings: bindings-l1-block-info bindings-optimism-portal deployed-bin-l1-block-info deployed-bin-optimism-portal # Split up b/c I don't know how to include this step in the L1 Block Info Bindings @@ -18,6 +18,16 @@ deployed-bin-l1-block-info: bindings-l1-block-info echo "var L1blockDeployedBin = \"$(deployedBytecode)\"" >> l1block/l1_block_info_deployed.go gofmt -s -w l1block/l1_block_info_deployed.go +# Split up b/c I don't know how to include this step in the L1 Block Info Bindings +# What is occuring is that the `temp` variable is hard to pull into the `eval` +deployed-bin-optimism-portal: bindings-optimism-portal + $(eval deployedBytecode := $(shell cat bin/portal_deployed.hex)) + echo "// Code generated - DO NOT EDIT." > deposit/optimism_portal_deployed.go + echo "// This file is a generated binding and any manual changes will be lost." >> deposit/optimism_portal_deployed.go + echo "package deposit" >> deposit/optimism_portal_deployed.go + echo "var OptimismPortalDeployedBin = \"$(deployedBytecode)\"" >> deposit/optimism_portal_deployed.go + gofmt -s -w deposit/optimism_portal_deployed.go + bindings-l1-block-info: $(eval temp := $(shell mktemp -d)) $(eval cwd := $(shell pwd)) @@ -36,10 +46,13 @@ bindings-l1-block-info: bindings-optimism-portal: $(eval temp := $(shell mktemp -d)) + $(eval cwd := $(shell pwd)) + mkdir -p bin cd ../../packages/contracts; \ forge build \ && forge inspect OptimismPortal abi > $(temp)/OptimismPortal.abi \ - && forge inspect OptimismPortal bytecode > $(temp)/OptimismPortal.bin + && forge inspect OptimismPortal bytecode > $(temp)/OptimismPortal.bin \ + && forge inspect OptimismPortal deployedBytecode > $(cwd)/bin/portal_deployed.hex abigen \ --abi $(temp)/OptimismPortal.abi \ --bin $(temp)/OptimismPortal.bin \ diff --git a/opnode/contracts/deposit/optimism_portal_deployed.go b/opnode/contracts/deposit/optimism_portal_deployed.go new file mode 100644 index 000000000000..4f695d309cff --- /dev/null +++ b/opnode/contracts/deposit/optimism_portal_deployed.go @@ -0,0 +1,5 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. +package deposit + +var OptimismPortalDeployedBin = "0x6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015e578063eecf1c3614610171578063ff61cc931461019157600080fd5b80621c2ff6146100935780639bf62d82146100f1578063a14238e71461011e57600080fd5b3661008e5761008c33346175306000604051806020016040528060008152506101d3565b005b600080fd5b34801561009f57600080fd5b506100c77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fd57600080fd5b506000546100c79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012a57600080fd5b5061014e610139366004611c41565b60016020526000908152604090205460ff1681565b60405190151581526020016100e8565b61008c61016c366004611cb2565b6101d3565b34801561017d57600080fd5b5061008c61018c366004611e18565b6102c2565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e8565b8180156101f5575073ffffffffffffffffffffffffffffffffffffffff851615155b1561022c576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3332811461024d575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102b2959493929190611f18565b60405180910390a3505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000840142101561031e576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401602060405180830381865afa1580156103ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d09190611fb4565b9050610424846040805182356020828101919091528301358183015290820135606082810191909152820135608082015260009060a001604051602081830303815290604052805190602001209050919050565b811461045c576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046d8d8d8d8d8d8d8d610648565b905061047f818660400135868661068a565b6104b5576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff1615151415610504576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161059b929190611fcd565b600060405180830381858888f193505050503d80600081146105d9576040519150601f19603f3d011682016040523d82523d6000602084013e6105de565b606091505b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17815560405191925083917f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f9190a25050505050505050505050505050565b6000878787878787876040516020016106679796959493929190611fdd565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016106aa929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052925061077091016040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061077a915050565b9695505050505050565b60008061078686610794565b9050610770818686866107c6565b606081805190602001206040516020016107b091815260200190565b6040516020818303038152906040529050919050565b60008060006107d68786866107f7565b915091508180156107ec57506107ec86826108f1565b979650505050505050565b6000606060006108068561090d565b90506000806000610818848a89610a08565b8151929550909350915015808061082c5750815b610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064015b60405180910390fd5b6000816108b357604051806020016040528060008152506108df565b6108df866108c2600188612099565b815181106108d2576108d26120b0565b6020026020010151610f25565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b6060600061091a83610f4f565b90506000815167ffffffffffffffff81111561093857610938611c83565b60405190808252806020026020018201604052801561097d57816020015b60408051808201909152606080825260208201528152602001906001900390816109565790505b50905060005b8251811015610a005760006109b08483815181106109a3576109a36120b0565b6020026020010151610f82565b905060405180604001604052808281526020016109cc83610f4f565b8152508383815181106109e1576109e16120b0565b60200260200101819052505080806109f8906120df565b915050610983565b509392505050565b60006060818080610a188761102c565b90506000869050600080610a3f604051806040016040528060608152602001606081525090565b60005b8c51811015610ee1578c8181518110610a5d57610a5d6120b0565b602002602001015191508284610a739190612118565b9350610a80600188612118565b965083610afe57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f742068617368000000000000000000000000000000604482015260640161088e565b610bef565b815151602011610b7a57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161088e565b84610b8883600001516111af565b14610bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161088e565b610bfb60106001612118565b8260200151511415610c74578551841415610c1557610ee1565b6000868581518110610c2957610c296120b0565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c5457610c546120b0565b60200260200101519050610c67816111d7565b9650600194505050610ecf565b60028260200151511415610e6d576000610c8d83611214565b9050600081600081518110610ca457610ca46120b0565b016020015160f81c90506000610cbb60028361215f565b610cc6906002612181565b90506000610cd7848360ff16611238565b90506000610ce58b8a611238565b90506000610cf3838361126e565b905060ff851660021480610d0a575060ff85166003145b15610d6057808351148015610d1f5750808251145b15610d3157610d2e818b612118565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b60ff85161580610d73575060ff85166001145b15610de55782518114610daf57507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b610dd68860200151600181518110610dc957610dc96120b0565b60200260200101516111d7565b9a509750610ecf945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f7072656669780000000000000000000000000000000000000000000000000000606482015260840161088e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161088e565b80610ed9816120df565b915050610a42565b507f8000000000000000000000000000000000000000000000000000000000000000841486610f108786611238565b909e909d50909b509950505050505050505050565b6020810151805160609161090791610f3f90600190612099565b815181106109a3576109a36120b0565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906109079061131a565b60606000806000610f928561154d565b919450925090506000816001811115610fad57610fad6121a4565b14611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161088e565b61102385602001518484611954565b95945050505050565b606060008251600261103e91906121d3565b67ffffffffffffffff81111561105657611056611c83565b6040519080825280601f01601f191660200182016040528015611080576020820181803683370190505b50905060005b83518110156111a85760048482815181106110a3576110a36120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826110d88360026121d3565b815181106110e8576110e86120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061112b5761112b6120b0565b016020015161113d919060f81c61215f565b60f81b8261114c8360026121d3565b611157906001612118565b81518110611167576111676120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111a0816120df565b915050611086565b5092915050565b60006020825110156111c357506020015190565b818060200190518101906109079190611fb4565b600060606020836000015110156111f8576111f183611a33565b9050611204565b61120183610f82565b90505b61120d816111af565b9392505050565b606061090761123383602001516000815181106109a3576109a36120b0565b61102c565b6060825182106112575750604080516020810190915260008152610907565b61120d83838486516112699190612099565b611a3e565b6000805b8084511180156112825750808351115b8015611303575082818151811061129b5761129b6120b0565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112da576112da6120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561120d5780611312816120df565b915050611272565b60606000806113288461154d565b91935090915060019050816001811115611344576113446121a4565b146113ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161088e565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816113c45790505090506000835b8651811015611542576020821061148a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161088e565b6000806114c76040518060400160405280858c600001516114ab9190612099565b8152602001858c602001516114c09190612118565b905261154d565b5091509150604051806040016040528083836114e39190612118565b8152602001848b602001516114f89190612118565b81525085858151811061150d5761150d6120b0565b6020908102919091010152611523600185612118565b935061152f8183612118565b6115399084612118565b925050506113f1565b508152949350505050565b6000806000808460000151116115bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161088e565b6020840151805160001a607f81116115e457600060016000945094509450505061194d565b60b7811161167a5760006115f9608083612099565b905080876000015111611668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161088e565b6001955093506000925061194d915050565b60bf811161179d57600061168f60b783612099565b9050808760000151116116fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161088e565b600183015160208290036101000a90046117188183612118565b885111611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161088e565b61178c826001612118565b965094506000935061194d92505050565b60f781116118325760006117b260c083612099565b905080876000015111611821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161088e565b60019550935084925061194d915050565b600061183f60f783612099565b9050808760000151116118ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161088e565b600183015160208290036101000a90046118c88183612118565b885111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161088e565b61193c826001612118565b965094506001935061194d92505050565b9193909250565b606060008267ffffffffffffffff81111561197157611971611c83565b6040519080825280601f01601f19166020018201604052801561199b576020820181803683370190505b5090508051600014156119af57905061120d565b60006119bb8587612118565b90506020820160005b6119cf602087612210565b811015611a0657825182526119e5602084612118565b92506119f2602083612118565b9150806119fe816120df565b9150506119c4565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061090782611c2b565b606081611a4c81601f612118565b1015611ab4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b82611abf8382612118565b1015611b27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b611b318284612118565b84511015611b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161088e565b606082158015611bba5760405191506000825260208201604052611c22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bf3578051835260209283019201611bdb565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610907826020015160008460000151611954565b600060208284031215611c5357600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c7e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a08688031215611cca57600080fd5b611cd386611c5a565b945060208601359350604086013567ffffffffffffffff8082168214611cf857600080fd5b9093506060870135908115158214611d0f57600080fd5b90925060808701359080821115611d2557600080fd5b818801915088601f830112611d3957600080fd5b813581811115611d4b57611d4b611c83565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611d9157611d91611c83565b816040528281528b6020848701011115611daa57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b60008083601f840112611de157600080fd5b50813567ffffffffffffffff811115611df957600080fd5b602083019150836020828501011115611e1157600080fd5b9250929050565b60008060008060008060008060008060006101808c8e031215611e3a57600080fd5b8b359a50611e4a60208d01611c5a565b9950611e5860408d01611c5a565b985060608c0135975060808c0135965067ffffffffffffffff60a08d01351115611e8157600080fd5b611e918d60a08e01358e01611dcf565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215611ecf57600080fd5b60e08c01925067ffffffffffffffff6101608d01351115611eef57600080fd5b611f008d6101608e01358e01611dcf565b81935080925050509295989b509295989b9093969950565b85815260006020868184015267ffffffffffffffff86166040840152841515606084015260a0608084015283518060a085015260005b81811015611f6a5785810183015185820160c001528201611f4e565b81811115611f7c57600060c083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160c001979650505050505050565b600060208284031215611fc657600080fd5b5051919050565b8183823760009101908152919050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015284608083015260c060a08301528260c0830152828460e0840137600060e0848401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121115761211161206a565b5060010190565b6000821982111561212b5761212b61206a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061217257612172612130565b8060ff84160691505092915050565b600060ff821660ff84168082101561219b5761219b61206a565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561220b5761220b61206a565b500290565b60008261221f5761221f612130565b50049056fea164736f6c634300080a000a" diff --git a/opnode/rollup/derive/fuzz_parsers_test.go b/opnode/rollup/derive/fuzz_parsers_test.go new file mode 100644 index 000000000000..2894548724d9 --- /dev/null +++ b/opnode/rollup/derive/fuzz_parsers_test.go @@ -0,0 +1,246 @@ +package derive + +import ( + "bytes" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm/runtime" + "github.com/ethereum/go-ethereum/crypto" + "github.com/google/go-cmp/cmp" +) + +var ( + pk, _ = crypto.GenerateKey() + addr = common.Address{0x42, 0xff} + opts, _ = bind.NewKeyedTransactorWithChainID(pk, common.Big1) + from = crypto.PubkeyToAddress(pk.PublicKey) + portalContract, _ = deposit.NewOptimismPortal(addr, nil) + l1BlockInfoContract, _ = l1block.NewL1Block(addr, nil) +) + +func cap_byte_slice(b []byte, c int) []byte { + if len(b) <= c { + return b + } else { + return b[:c] + } +} + +func BytesToBigInt(b []byte) *big.Int { + return new(big.Int).SetBytes(cap_byte_slice(b, 32)) +} + +func BigEqual(a, b *big.Int) bool { + if a == nil || b == nil { + return a == b + } else { + return a.Cmp(b) == 0 + } +} + +// FuzzL1InfoRoundTrip checks that our encoder round trips properly +func FuzzL1InfoRoundTrip(f *testing.F) { + f.Fuzz(func(t *testing.T, number, time uint64, baseFee, hash []byte, seqNumber uint64) { + in := L1BlockInfo{ + Number: number, + Time: time, + BaseFee: BytesToBigInt(baseFee), + BlockHash: common.BytesToHash(hash), + SequenceNumber: seqNumber, + } + enc, err := in.MarshalBinary() + if err != nil { + t.Fatalf("Failed to marshal binary: %v", err) + } + var out L1BlockInfo + err = out.UnmarshalBinary(enc) + if err != nil { + t.Fatalf("Failed to unmarshal binary: %v", err) + } + if !cmp.Equal(in, out, cmp.Comparer(BigEqual)) { + t.Fatalf("The data did not round trip correctly. in: %v. out: %v", in, out) + } + + }) +} + +// FuzzL1InfoAgainstContract checks the custom marshalling functions against the contract +// bindings to ensure that our functions are up to date and match the bindings. +func FuzzL1InfoAgainstContract(f *testing.F) { + f.Fuzz(func(t *testing.T, number, time uint64, baseFee, hash []byte, seqNumber uint64) { + expected := L1BlockInfo{ + Number: number, + Time: time, + BaseFee: BytesToBigInt(baseFee), + BlockHash: common.BytesToHash(hash), + SequenceNumber: seqNumber, + } + + // Setup opts + opts.GasPrice = big.NewInt(100) + opts.GasLimit = 100_000 + opts.NoSend = true + opts.Nonce = common.Big0 + // Create the SetL1BlockValues transaction + tx, err := l1BlockInfoContract.SetL1BlockValues( + opts, + number, + time, + BytesToBigInt(baseFee), + common.BytesToHash(hash), + seqNumber, + ) + if err != nil { + t.Fatalf("Failed to create the transaction: %v", err) + } + + // Check that our encoder produces the same value and that we + // can decode the contract values exactly + enc, err := expected.MarshalBinary() + if err != nil { + t.Fatalf("Failed to marshal binary: %v", err) + } + if !bytes.Equal(enc, tx.Data()) { + t.Fatalf("Custom marshal does not match contract bindings") + } + + var actual L1BlockInfo + err = actual.UnmarshalBinary(tx.Data()) + if err != nil { + t.Fatalf("Failed to unmarshal binary: %v", err) + } + + if !cmp.Equal(expected, actual, cmp.Comparer(BigEqual)) { + t.Fatalf("The data did not round trip correctly. expected: %v. actual: %v", expected, actual) + } + + }) +} + +// FuzzUnmarshallLogEvent runs a deposit event through the EVM and checks that output of the abigen parsing matches +// what was inputted and what we parsed during the UnmarshalLogEvent function (which turns it into a deposit tx) +// The purpose is to check that we can never create a transaction that emits a log that we cannot parse as well +// as ensuring that our custom marshalling matches abigen. +func FuzzUnmarshallLogEvent(f *testing.F) { + b := func(i int64) []byte { + return big.NewInt(i).Bytes() + } + type setup struct { + to common.Address + mint int64 + value int64 + gasLimit uint64 + data string + isCreation bool + } + cases := []setup{ + { + mint: 100, + value: 50, + gasLimit: 100000, + }, + } + for _, c := range cases { + f.Add(c.to.Bytes(), b(c.mint), b(c.value), []byte(c.data), c.gasLimit, c.isCreation) + } + + f.Fuzz(func(t *testing.T, _to, _mint, _value, data []byte, l2GasLimit uint64, isCreation bool) { + to := common.BytesToAddress(_to) + mint := BytesToBigInt(_mint) + value := BytesToBigInt(_value) + + // Setup opts + opts.Value = mint + opts.GasPrice = common.Big2 + opts.GasLimit = 500_000 + opts.NoSend = true + opts.Nonce = common.Big0 + // Create the deposit transaction + tx, err := portalContract.DepositTransaction(opts, to, value, l2GasLimit, isCreation, data) + if err != nil { + t.Fatal(err) + } + + state, err := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + if err != nil { + t.Fatal(err) + } + state.SetBalance(from, BytesToBigInt([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})) + state.SetCode(addr, common.FromHex(deposit.OptimismPortalDeployedBin)) + _, err = state.Commit(false) + if err != nil { + t.Fatal(err) + } + + cfg := runtime.Config{ + Origin: from, + Value: tx.Value(), + State: state, + GasLimit: opts.GasLimit, + } + + _, _, err = runtime.Call(addr, tx.Data(), &cfg) + logs := state.Logs() + if err == nil && len(logs) != 1 { + t.Fatal("No logs or error after execution") + } else if err != nil { + return + } + + // Test that our custom parsing matches the ABI parsing + depositEvent, err := portalContract.ParseTransactionDeposited(*(logs[0])) + if err != nil { + t.Fatalf("Could not parse log that was emitted by the deposit contract: %v", err) + } + depositEvent.Raw = types.Log{} // Clear out the log + + // Verify that is passes our custom unmarshalling logic + dep, err := UnmarshalLogEvent(logs[0]) + if err != nil { + t.Fatalf("Could not unmarshal log that was emitted by the deposit contract: %v", err) + } + + reconstructed := &deposit.OptimismPortalTransactionDeposited{ + From: dep.From, + Value: dep.Value, + GasLimit: dep.Gas, + IsCreation: dep.To == nil, + Data: dep.Data, + Raw: types.Log{}, + } + if dep.To != nil { + reconstructed.To = *dep.To + } + if dep.Mint != nil { + reconstructed.Mint = dep.Mint + } else { + reconstructed.Mint = common.Big0 + } + + if !cmp.Equal(depositEvent, reconstructed, cmp.Comparer(BigEqual)) { + t.Fatalf("The deposit tx did not match. tx: %v. actual: %v", reconstructed, depositEvent) + } + + inputArgs := &deposit.OptimismPortalTransactionDeposited{ + From: from, + To: to, + Mint: mint, + Value: value, + GasLimit: l2GasLimit, + IsCreation: isCreation, + Data: data, + Raw: types.Log{}, + } + if !cmp.Equal(depositEvent, inputArgs, cmp.Comparer(BigEqual)) { + t.Fatalf("The input args did not match. input: %v. actual: %v", inputArgs, depositEvent) + } + }) +} From a8a60baff021026997d84717284f84eaed9959be Mon Sep 17 00:00:00 2001 From: Luca Donno <30298476+lucadonnoh@users.noreply.github.com> Date: Fri, 6 May 2022 22:45:26 +0200 Subject: [PATCH 535/585] fix: DepositFeed.sol link --- specs/deposits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index e57d1196c8b8..81f856c38db1 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -266,4 +266,4 @@ it possible for users to interact with contracts on L2 even when the Sequencer i A reference implementation of the Deposit Feed contract can be found in [DepositFeed.sol]. -[DepositFeed.sol]: ../packages/contracts/contracts/L1/DepositFeed.sol +[DepositFeed.sol]: ../packages/contracts/contracts/L1/abstracts/DepositFeed.sol From 46fa0d475e93a71a63a43406c4479dd876d9e466 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sat, 30 Apr 2022 02:14:54 +0200 Subject: [PATCH 536/585] opnode: gossip blocks topic validator and subscriber --- go.mod | 4 +- go.sum | 2 +- opnode/node/node.go | 20 ++- opnode/p2p/gossip.go | 259 +++++++++++++++++++++++++++++++++++++ opnode/rollup/types.go | 5 + opnode/test/system_test.go | 2 + ops/rollup.json | 4 + specs/rollup-node-p2p.md | 13 +- 8 files changed, 298 insertions(+), 11 deletions(-) create mode 100644 opnode/p2p/gossip.go diff --git a/go.mod b/go.mod index 739b405c6026..57fb17d943ce 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.18 require ( github.com/ethereum/go-ethereum v1.10.16 + github.com/golang/snappy v0.0.4 + github.com/google/go-cmp v0.5.8 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.0 github.com/ipfs/go-datastore v0.5.0 @@ -57,8 +59,6 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/go-cmp v0.5.8 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect diff --git a/go.sum b/go.sum index efdcbf9d37ca..d75be364f044 100644 --- a/go.sum +++ b/go.sum @@ -360,7 +360,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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= @@ -1568,6 +1567,7 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= diff --git a/opnode/node/node.go b/opnode/node/node.go index 8d663f013315..f4a560afb55f 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -6,6 +6,8 @@ import ( "sync" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/libp2p/go-libp2p-core/host" @@ -36,6 +38,7 @@ type OpNode struct { p2pCtx context.Context // all p2p activity take this context so p2p can be shut down without stopping the node. p2pClose context.CancelFunc gs *pubsub.PubSub + blocks chan p2p.BlockMessage // incoming unsafe block messages done chan struct{} wg sync.WaitGroup } @@ -127,6 +130,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* server: server, done: make(chan struct{}), l2Nodes: l2Nodes, + blocks: make(chan p2p.BlockMessage, 10), } if cfg.P2P != nil { @@ -145,17 +149,24 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* // not a context leak, gossipsub is closed with a context. // TODO: maybe we can improve this, or closing the Host is enough? n.p2pCtx, n.p2pClose = context.WithCancel(context.Background()) - gs, err := pubsub.NewGossipSub(n.p2pCtx, n.host) // TODO options - if err != nil { - // close p2p stack if we cannot create the opnode successfully + closeP2P := func() { if n.dv5Udp != nil { n.dv5Udp.Close() } _ = n.host.Close() n.p2pClose() + } + gs, err := p2p.NewGossipSub(n.p2pCtx, n.host, &cfg.Rollup) + if err != nil { + closeP2P() return nil, fmt.Errorf("failed to start gossipsub router: %v", err) } n.gs = gs + + if err := p2p.JoinGossip(n.p2pCtx, n.gs, log, &cfg.Rollup, n.blocks); err != nil { + closeP2P() + return nil, fmt.Errorf("failed to join blocks gossip topic: %v", err) + } } } @@ -225,6 +236,9 @@ func (c *OpNode) Start(ctx context.Context) error { defer c.wg.Done() for { select { + case l2Block := <-c.blocks: + c.log.Info("Received L2 unsafe block", "hash", l2Block.Block.BlockHash, "from", l2Block.ReceivedFrom) + // TODO: process unsafe block in all engines case l1Head := <-l1Heads: c.log.Info("New L1 head", "head", l1Head, "parent", l1Head.ParentHash) // TODO: maybe log other info on interval or other chain events (individual engines also log things) diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go new file mode 100644 index 000000000000..a1823694cb5d --- /dev/null +++ b/opnode/p2p/gossip.go @@ -0,0 +1,259 @@ +package p2p + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/binary" + "fmt" + "sync" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" + "github.com/golang/snappy" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/peer" + pubsub "github.com/libp2p/go-libp2p-pubsub" + pb "github.com/libp2p/go-libp2p-pubsub/pb" +) + +func init() { + // TODO: a PR is open to make this configurable upstream as option instead of having to override a global + pubsub.TimeCacheDuration = 80 * pubsub.GossipSubHeartbeatInterval +} + +const maxGossipSize = 1 << 20 +const maxOutboundQueue = 256 +const maxValidateQueue = 256 +const globalValidateThrottle = 512 + +// Message domains, the msg id function uncompresses to keep data monomorphic, +// but invalid compressed data will need a unique different id. + +var MessageDomainInvalidSnappy = [4]byte{0, 0, 0, 0} +var MessageDomainValidSnappy = [4]byte{1, 0, 0, 0} + +const MaxGossipSize = 1 << 20 + +func blocksTopicV1(cfg *rollup.Config) string { + return fmt.Sprintf("/optimism/%s/0/blocks", cfg.L2ChainID.String()) +} + +// BuildSubscriptionFilter builds a simple subscription filter, +// to help protect against peers spamming useless subscriptions. +func BuildSubscriptionFilter(cfg *rollup.Config) pubsub.SubscriptionFilter { + return pubsub.NewAllowlistSubscriptionFilter(blocksTopicV1(cfg)) // add more topics here in the future, if any. +} + +var msgIdBufPool = sync.Pool{New: func() any { + // note: the topic validator concurrency is limited, so pool won't blow up, even with large pre-allocation. + x := make([]byte, 0, MaxGossipSize) + return &x +}} + +// BuildMsgIdFn builds a generic message ID function for gossipsub that can handle compressed payloads, +// mirroring the eth2 p2p gossip spec. +func BuildMsgIdFn(cfg *rollup.Config) pubsub.MsgIdFunction { + return func(pmsg *pb.Message) string { + valid := false + var data []byte + // If it's a valid compressed snappy data, then hash the uncompressed contents. + // The validator can throw away the message later when recognized as invalid, + // and the unique hash helps detect duplicates. + dLen, err := snappy.DecodedLen(pmsg.Data) + if err == nil && dLen <= MaxGossipSize { + res := msgIdBufPool.Get().(*[]byte) + defer msgIdBufPool.Put(res) + if data, err = snappy.Decode((*res)[:0], pmsg.Data); err == nil { + *res = data // if we ended up growing the slice capacity, fine, keep the larger one. + valid = true + } + } + if data == nil { + data = pmsg.Data + } + h := sha256.New() + if valid { + h.Write(MessageDomainValidSnappy[:]) + } else { + h.Write(MessageDomainInvalidSnappy[:]) + } + // The chain ID is part of the gossip topic, making the msg id unique + topic := pmsg.GetTopic() + var topicLen [8]byte + binary.LittleEndian.PutUint64(topicLen[:], uint64(len(topic))) + h.Write(topicLen[:]) + h.Write([]byte(topic)) + h.Write(data) + // the message ID is shortened to save space, a lot of these may be gossiped. + return string(h.Sum(nil)[:20]) + } +} + +func BuildGlobalGossipParams(cfg *rollup.Config) pubsub.GossipSubParams { + params := pubsub.DefaultGossipSubParams() + params.D = 8 // topic stable mesh target count + params.Dlo = 6 // topic stable mesh low watermark + params.Dhi = 12 // topic stable mesh high watermark + params.Dlazy = 6 // gossip target + params.HeartbeatInterval = 500 * time.Millisecond // frequency of heartbeat, seconds + params.FanoutTTL = 24 * time.Second // ttl for fanout maps for topics we are not subscribed to but have published to, seconds + params.HistoryLength = 12 // number of windows to retain full messages in cache for IWANT responses + params.HistoryGossip = 3 // number of windows to gossip about + + return params +} + +func NewGossipSub(p2pCtx context.Context, h host.Host, cfg *rollup.Config) (*pubsub.PubSub, error) { + denyList, err := pubsub.NewTimeCachedBlacklist(30 * time.Second) + if err != nil { + return nil, err + } + return pubsub.NewGossipSub(p2pCtx, h, + pubsub.WithMaxMessageSize(maxGossipSize), + pubsub.WithMessageIdFn(BuildMsgIdFn(cfg)), + pubsub.WithNoAuthor(), + pubsub.WithMessageSignaturePolicy(pubsub.StrictNoSign), + pubsub.WithSubscriptionFilter(BuildSubscriptionFilter(cfg)), + pubsub.WithValidateQueueSize(maxValidateQueue), + pubsub.WithPeerOutboundQueueSize(maxOutboundQueue), + pubsub.WithValidateThrottle(globalValidateThrottle), + pubsub.WithPeerExchange(false), + pubsub.WithBlacklist(denyList), + pubsub.WithGossipSubParams(BuildGlobalGossipParams(cfg))) + // TODO: pubsub.WithDiscovery(discover) to search for peers instead of randomly grabbing from open connections + // TODO: pubsub.WithPeerScoreInspect(inspect, InspectInterval) to update peerstore scores with gossip scores +} + +func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx { + return func(ctx context.Context, id peer.ID, message *pubsub.Message) pubsub.ValidationResult { + // [REJECT] if the compression is not valid + // TODO snappy uncompress, avoid zip-bomb, pool data + uncompressedData := message.Data + + // message starts with compact-encoding secp256k1 encoded signature + signatureBytes, blockBytes := uncompressedData[:65], uncompressedData[65:] + + // [REJECT] if the block encoding is not valid + var block types.Block + if err := block.DecodeRLP(rlp.NewStream(bytes.NewReader(blockBytes), maxGossipSize)); err != nil { + log.Warn("invalid block RLP", "err", err, "peer", id) + return pubsub.ValidationReject + } + + // [REJECT] if the block timestamp is older than 20 seconds in the past + // TODO + + // [REJECT] if the block timestamp is more than 5 seconds into the future + // TODO + + // [REJECT] if more than 5 blocks have been seen with the same block height + // TODO + + // [REJECT] if the signature by the sequencer is not valid + var msgInput [32 + 32 + 32]byte + copy(msgInput[0:32], "optimism bedrock block v1") // message domain + cfg.L2ChainID.FillBytes(msgInput[32:64]) // protect against replaying on other chains + h := block.Hash() + copy(msgInput[64:], h[:]) + signedHash := crypto.Keccak256Hash(msgInput[:]) + // TODO: is this sufficient to verify the signature? + pub, err := crypto.SigToPub(signedHash[:], signatureBytes) + if err != nil { + log.Warn("invalid block signature", "err", err, "peer", id) + return pubsub.ValidationReject + } + addr := crypto.PubkeyToAddress(*pub) + if addr != cfg.P2PSequencerAddress { + log.Warn("unexpected block author", "err", err, "peer", id) + return pubsub.ValidationReject + } + + payload, err := l2.BlockAsPayload(&block) + if err != nil { + log.Warn("failed to convert block to execution payload", "err", err, "peer", id) + return pubsub.ValidationReject + } + // remember the decoded payload for later usage in topic subscriber. + message.ValidatorData = payload + return pubsub.ValidationAccept + } +} + +type BlockMessage struct { + ReceivedFrom peer.ID + Block *l2.ExecutionPayload +} + +func JoinGossip(p2pCtx context.Context, ps *pubsub.PubSub, log log.Logger, cfg *rollup.Config, blocks chan<- BlockMessage) error { + val := BuildBlocksValidator(log, cfg) + topicName := blocksTopicV1(cfg) + err := ps.RegisterTopicValidator(topicName, + val, + pubsub.WithValidatorTimeout(3*time.Second), + pubsub.WithValidatorConcurrency(4)) + if err != nil { + return fmt.Errorf("failed to register blocks gossip topic: %v", err) + } + topic, err := ps.Join(topicName) + if err != nil { + return fmt.Errorf("failed to join blocks gossip topic: %v", err) + } + // TODO: block topic scoring parameters + // See prysm: https://github.com/prysmaticlabs/prysm/blob/develop/beacon-chain/p2p/gossip_scoring_params.go + // And research from lighthouse: https://gist.github.com/blacktemplar/5c1862cb3f0e32a1a7fb0b25e79e6e2c + // And docs: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#topic-parameter-calculation-and-decay + //err := topic.SetScoreParams(&pubsub.TopicScoreParams{......}) + + subscription, err := topic.Subscribe() + if err != nil { + return fmt.Errorf("failed to subscribe to blocks gossip topic: %v", err) + } + + subscriber := MakeSubscriber(log, BlocksHandler(blocks)) + go subscriber(p2pCtx, subscription) + return nil +} + +type TopicSubscriber func(ctx context.Context, sub *pubsub.Subscription) +type MessageHandler func(ctx context.Context, from peer.ID, msg interface{}) error + +func BlocksHandler(out chan<- BlockMessage) MessageHandler { + return func(ctx context.Context, from peer.ID, msg interface{}) error { + payload, ok := msg.(*l2.ExecutionPayload) + if !ok { + return fmt.Errorf("expected topic validator to parse and validate data into execution payload, but got %T", msg) + } + select { + case <-ctx.Done(): + return ctx.Err() + case out <- BlockMessage{ReceivedFrom: from, Block: payload}: + return nil + } + } +} + +func MakeSubscriber(log log.Logger, msgHandler MessageHandler) TopicSubscriber { + return func(ctx context.Context, sub *pubsub.Subscription) { + topicLog := log.New("topic", sub.Topic()) + for { + msg, err := sub.Next(ctx) + if err != nil { // ctx was closed, or subscription was closed + topicLog.Debug("stopped subscriber") + return + } + if msg.ValidatorData == nil { + topicLog.Error("gossip message with no data", "from", msg.ReceivedFrom) + continue + } + if err := msgHandler(ctx, msg.ReceivedFrom, msg.ValidatorData); err != nil { + topicLog.Error("failed to process gossip message", "err", err) + } + } + } +} diff --git a/opnode/rollup/types.go b/opnode/rollup/types.go index 36dcf6b42410..20d97121ad75 100644 --- a/opnode/rollup/types.go +++ b/opnode/rollup/types.go @@ -34,6 +34,11 @@ type Config struct { SeqWindowSize uint64 `json:"seq_window_size"` // Required to verify L1 signatures L1ChainID *big.Int `json:"l1_chain_id"` + // Required to identify the L2 network and create p2p signatures unique for this chain. + L2ChainID *big.Int `json:"l2_chain_id"` + + // Address of the key the sequencer uses to sign blocks on the P2P layer + P2PSequencerAddress common.Address `json:"p2p_sequencer_address"` // Note: below addresses are part of the block-derivation process, // and required to be the same network-wide to stay in consensus. diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 9958309c0c9a..7cca9076f223 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -114,7 +114,9 @@ func defaultSystemConfig(t *testing.T) SystemConfig { MaxSequencerDrift: 10, SeqWindowSize: 2, L1ChainID: big.NewInt(900), + L2ChainID: big.NewInt(901), // TODO pick defaults + P2PSequencerAddress: common.Address{}, // TODO configure sequencer p2p key FeeRecipientAddress: common.Address{0xff, 0x01}, BatchInboxAddress: batchInboxAddress, // Batch Sender address is filled out in system start diff --git a/ops/rollup.json b/ops/rollup.json index 586f6b47dac4..1ec6c9ddc621 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -19,6 +19,10 @@ "l1_chain_id": 900, + "l2_chain_id": 901, + + "p2p_sequencer_address": "TODOTODO", + "fee_recipient_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "batch_inbox_address": "0xff00000000000000000000000000000000000002", diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index c1cace6925c5..bff4f748cf02 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -209,7 +209,7 @@ GossipSub [parameters][gossip-parameters]: - `fanout_ttl` (ttl for fanout maps for topics we are not subscribed to but have published to, seconds): 24 - `mcache_len` (number of windows to retain full messages in cache for `IWANT` responses): 12 - `mcache_gossip` (number of windows to gossip about): 3 -- `seen_ttl` (number of heartbeat intervals to retain message IDs): 40 +- `seen_ttl` (number of heartbeat intervals to retain message IDs): 80 (= 40 seconds) Notable differences from L1 consensus (Eth2): @@ -250,19 +250,22 @@ To ensure malicious peers get scored based on application behavior the validatio In order of operation: -- `[REJECT]` if the encoding or compression is not valid +- `[REJECT]` if the compression is not valid +- `[REJECT]` if the block encoding is not valid - `[REJECT]` if the block timestamp is older than 20 seconds in the past (graceful boundary for worst-case propagation and clock skew) - `[REJECT]` if the block timestamp is more than 5 seconds into the future (graceful boundary for clock skew) -- `[REJECT]` if the signature by the sequencer is not valid - `[REJECT]` if more than 5 blocks have been seen with the same block height -- `[IGNORE]` if a conflicting block was already seen on L1. - It may not be malicious due to racing between L1 confirmation and L2 propagation, but should be filtered out. +- `[REJECT]` if the signature by the sequencer is not valid The block is signed by the corresponding sequencer, to filter malicious messages. The sequencer model is singular but may change to multiple sequencers in the future. A default sequencer pubkey is distributed with rollup nodes and should be configurable. +Note that blocks that a block may still be propagated even if the L1 already confirmed a different block. +The local L1 view of the node may be wrong, and the time and signature validation will prevent spam. +Hence, calling into the execution engine with a block lookup every propagation step is not worth the added delay. + ##### Block processing A node may apply the block to their local engine ahead of L1 availability, if it ensures that: From 5ac7f925c23d1fac55f97c2e56694a1d692bbe58 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sun, 8 May 2022 21:08:11 +0200 Subject: [PATCH 537/585] opnode/l2: ExecutionPayload SSZ encoding/decoding --- .gitignore | 5 +- opnode/Makefile | 2 + opnode/l2/ssz.go | 225 ++++++++++++++++++++++++++++++++++++++++++ opnode/l2/ssz_test.go | 79 +++++++++++++++ 4 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 opnode/l2/ssz.go create mode 100644 opnode/l2/ssz_test.go diff --git a/.gitignore b/.gitignore index 49732cb8a1e3..6866feb22c82 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,7 @@ bin integration-tests/cache/ integration-tests/artifacts/ **/*.env -.devnet \ No newline at end of file +.devnet + +# Ignore local fuzzing results +**/testdata/fuzz/ diff --git a/opnode/Makefile b/opnode/Makefile index 409863ae8683..923684723ae3 100644 --- a/opnode/Makefile +++ b/opnode/Makefile @@ -20,6 +20,8 @@ lint: golangci-lint run -E asciicheck,goimports,misspell ./... fuzz: + go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzExecutionPayloadUnmarshal ./l2 + go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzExecutionPayloadMarshalUnmarshal ./l2 go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoRoundTrip ./rollup/derive go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoAgainstContract ./rollup/derive go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzUnmarshallLogEvent ./rollup/derive diff --git a/opnode/l2/ssz.go b/opnode/l2/ssz.go new file mode 100644 index 000000000000..7a0aa4fae351 --- /dev/null +++ b/opnode/l2/ssz.go @@ -0,0 +1,225 @@ +package l2 + +import ( + "encoding/binary" + "fmt" + "io" + "sync" +) + +// ExecutionPayload is the only SSZ type we have to marshal/unmarshal, +// so instead of importing a SSZ lib we implement the bare minimum. +// This is more efficient than RLP, and matches the L1 consensus-layer encoding of ExecutionPayload. + +// All fields (4s are offsets to dynamic data) +const executionPayloadFixedPart = 32 + 20 + 32 + 32 + 256 + 32 + 8 + 8 + 8 + 8 + 4 + 32 + 32 + 4 + +// MAX_TRANSACTIONS_PER_PAYLOAD in consensus spec +const maxTransactionsPerPayload = 1 << 20 + +// The payloads are small enough to read and write at once. +// But this happens often enough that we want to avoid re-allocating buffers for this. +var payloadBufPool = sync.Pool{New: func() any { + x := make([]byte, 0, 100_000) + return &x +}} + +func (payload *ExecutionPayload) SizeSSZ() (full uint32) { + full = executionPayloadFixedPart + uint32(len(payload.ExtraData)) + // One offset to each transaction + full += uint32(len(payload.Transactions)) * 4 + // Each transaction + for _, tx := range payload.Transactions { + full += uint32(len(tx)) + } + return full +} + +// marshalBytes32LE returns the value of z as a 32-byte little-endian array. +func marshalBytes32LE(out []byte, z *Uint256Quantity) { + _ = out[31] // bounds check hint to compiler + binary.LittleEndian.PutUint64(out[0:8], z[0]) + binary.LittleEndian.PutUint64(out[8:16], z[1]) + binary.LittleEndian.PutUint64(out[16:24], z[2]) + binary.LittleEndian.PutUint64(out[24:32], z[3]) +} + +func unmarshalBytes32LE(in []byte, z *Uint256Quantity) { + _ = in[31] // bounds check hint to compiler + z[0] = binary.LittleEndian.Uint64(in[0:8]) + z[1] = binary.LittleEndian.Uint64(in[8:16]) + z[2] = binary.LittleEndian.Uint64(in[16:24]) + z[3] = binary.LittleEndian.Uint64(in[24:32]) +} + +// MarshalSSZ encodes the ExecutionPayload as SSZ type +func (payload *ExecutionPayload) MarshalSSZ(w io.Writer) (n int, err error) { + scope := payload.SizeSSZ() + + buf := *payloadBufPool.Get().(*[]byte) + if uint32(cap(buf)) < scope { + buf = make([]byte, scope) + } else { + buf = buf[:scope] + } + defer payloadBufPool.Put(&buf) + + offset := uint32(0) + copy(buf[offset:offset+32], payload.ParentHash[:]) + offset += 32 + copy(buf[offset:offset+32], payload.FeeRecipient[:]) + offset += 20 + copy(buf[offset:offset+32], payload.StateRoot[:]) + offset += 32 + copy(buf[offset:offset+32], payload.ReceiptsRoot[:]) + offset += 32 + copy(buf[offset:offset+256], payload.LogsBloom[:]) + offset += 256 + copy(buf[offset:offset+32], payload.PrevRandao[:]) + offset += 32 + binary.LittleEndian.PutUint64(buf[offset:offset+8], uint64(payload.BlockNumber)) + offset += 8 + binary.LittleEndian.PutUint64(buf[offset:offset+8], uint64(payload.GasLimit)) + offset += 8 + binary.LittleEndian.PutUint64(buf[offset:offset+8], uint64(payload.GasUsed)) + offset += 8 + binary.LittleEndian.PutUint64(buf[offset:offset+8], uint64(payload.Timestamp)) + offset += 8 + // offset to ExtraData + binary.LittleEndian.PutUint32(buf[offset:offset+4], executionPayloadFixedPart) + offset += 4 + marshalBytes32LE(buf[offset:offset+32], &payload.BaseFeePerGas) + offset += 32 + copy(buf[offset:offset+32], payload.BlockHash[:]) + offset += 32 + // offset to Transactions + binary.LittleEndian.PutUint32(buf[offset:offset+4], executionPayloadFixedPart+uint32(len(payload.ExtraData))) + offset += 4 + if offset != executionPayloadFixedPart { + panic("fixed part size is inconsistent") + } + // dynamic value 1: ExtraData + copy(buf[offset:offset+uint32(len(payload.ExtraData))], payload.ExtraData[:]) + offset += uint32(len(payload.ExtraData)) + // dynamic value 2: Transactions + marshalTransactions(buf[offset:], payload.Transactions) + return w.Write(buf) +} + +func marshalTransactions(out []byte, txs []Data) { + offset := uint32(0) + txOffset := uint32(len(txs)) * 4 + for _, tx := range txs { + binary.LittleEndian.PutUint32(out[offset:offset+4], txOffset) + offset += 4 + nextTxOffset := txOffset + uint32(len(tx)) + copy(out[txOffset:nextTxOffset], tx) + txOffset = nextTxOffset + } +} + +// UnmarshalSSZ decodes the ExecutionPayload as SSZ type +func (payload *ExecutionPayload) UnmarshalSSZ(scope uint32, r io.Reader) error { + if scope < executionPayloadFixedPart { + return fmt.Errorf("scope too small to decode execution payload: %d", scope) + } + + buf := *payloadBufPool.Get().(*[]byte) + if uint32(cap(buf)) < scope { + buf = make([]byte, scope) + } else { + buf = buf[:scope] + } + defer payloadBufPool.Put(&buf) + + if _, err := io.ReadFull(r, buf); err != nil { + return fmt.Errorf("failed to read fixed-size part of ExecutionPayload: %w", err) + } + offset := uint32(0) + copy(payload.ParentHash[:], buf[offset:offset+32]) + offset += 32 + copy(payload.FeeRecipient[:], buf[offset:offset+20]) + offset += 20 + copy(payload.StateRoot[:], buf[offset:offset+32]) + offset += 32 + copy(payload.ReceiptsRoot[:], buf[offset:offset+32]) + offset += 32 + copy(payload.LogsBloom[:], buf[offset:offset+256]) + offset += 256 + copy(payload.PrevRandao[:], buf[offset:offset+32]) + offset += 32 + payload.BlockNumber = Uint64Quantity(binary.LittleEndian.Uint64(buf[offset : offset+8])) + offset += 8 + payload.GasLimit = Uint64Quantity(binary.LittleEndian.Uint64(buf[offset : offset+8])) + offset += 8 + payload.GasUsed = Uint64Quantity(binary.LittleEndian.Uint64(buf[offset : offset+8])) + offset += 8 + payload.Timestamp = Uint64Quantity(binary.LittleEndian.Uint64(buf[offset : offset+8])) + offset += 8 + extraDataOffset := binary.LittleEndian.Uint32(buf[offset : offset+4]) + if extraDataOffset != executionPayloadFixedPart { + return fmt.Errorf("unexpected extra data offset: %d <> %d", extraDataOffset, executionPayloadFixedPart) + } + offset += 4 + unmarshalBytes32LE(buf[offset:offset+32], &payload.BaseFeePerGas) + offset += 32 + copy(payload.BlockHash[:], buf[offset:offset+32]) + offset += 32 + transactionsOffset := binary.LittleEndian.Uint32(buf[offset : offset+4]) + offset += 4 + if offset != executionPayloadFixedPart { + panic("fixed part size is inconsistent") + } + if transactionsOffset > extraDataOffset+32 || transactionsOffset > scope { + return fmt.Errorf("extra-data is too large: %d", transactionsOffset-extraDataOffset) + } + extraDataSize := transactionsOffset - extraDataOffset + payload.ExtraData = make(BytesMax32, extraDataSize) + copy(payload.ExtraData, buf[extraDataOffset:transactionsOffset]) + txs, err := unmarshalTransactions(buf[transactionsOffset:]) + if err != nil { + return fmt.Errorf("failed to unmarshal transactions list: %v", err) + } + payload.Transactions = txs + return nil +} + +func unmarshalTransactions(in []byte) (txs []Data, err error) { + scope := uint32(len(in)) + if scope == 0 { // empty txs list + return make([]Data, 0), nil + } + if scope < 4 { + return nil, fmt.Errorf("not enough scope to read first tx offset: %d", scope) + } + offset := uint32(0) + firstTxOffset := binary.LittleEndian.Uint32(in[offset : offset+4]) + offset += 4 + if firstTxOffset%4 != 0 { + return nil, fmt.Errorf("invalid first tx offset: %d, not a multiple of offset size", firstTxOffset) + } + if firstTxOffset > scope { + return nil, fmt.Errorf("invalid first tx offset: %d, out of scope %d", firstTxOffset, scope) + } + txCount := firstTxOffset / 4 + if txCount > maxTransactionsPerPayload { + return nil, fmt.Errorf("too many transactions: %d > %d", txCount, maxTransactionsPerPayload) + } + txs = make([]Data, txCount) + currentTxOffset := firstTxOffset + for i := uint32(0); i < txCount; i++ { + nextTxOffset := scope + if i+1 < txCount { + nextTxOffset = binary.LittleEndian.Uint32(in[offset : offset+4]) + offset += 4 + } + if nextTxOffset < currentTxOffset || nextTxOffset > scope { + return nil, fmt.Errorf("tx %d has bad next offset: %d, current is %d, scope is %d", i, nextTxOffset, currentTxOffset, scope) + } + currentTxSize := nextTxOffset - currentTxOffset + txs[i] = make(Data, currentTxSize) + copy(txs[i], in[currentTxOffset:nextTxOffset]) + currentTxOffset = nextTxOffset + } + return txs, nil +} diff --git a/opnode/l2/ssz_test.go b/opnode/l2/ssz_test.go new file mode 100644 index 000000000000..11927b39b964 --- /dev/null +++ b/opnode/l2/ssz_test.go @@ -0,0 +1,79 @@ +package l2 + +import ( + "bytes" + "encoding/binary" + "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" + "testing" +) + +// FuzzExecutionPayloadUnmarshal checks that our SSZ decoding never panics +func FuzzExecutionPayloadUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + var payload ExecutionPayload + err := payload.UnmarshalSSZ(uint32(len(data)), bytes.NewReader(data)) + if err != nil { + // not every input is a valid ExecutionPayload, that's ok. Should just not panic. + return + } + }) +} + +// FuzzExecutionPayloadMarshalUnmarshal checks that our SSZ encoding>decoding round trips properly +func FuzzExecutionPayloadMarshalUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte, a, b, c, d uint64, extraData []byte, txs uint16, txsData []byte) { + if len(data) < 32+20+32+32+256+32+32+32 { + return + } + var payload ExecutionPayload + payload.ParentHash = *(*common.Hash)(data[:32]) + data = data[32:] + payload.FeeRecipient = *(*common.Address)(data[:20]) + data = data[20:] + payload.StateRoot = *(*Bytes32)(data[:32]) + data = data[32:] + payload.ReceiptsRoot = *(*Bytes32)(data[:32]) + data = data[32:] + payload.LogsBloom = *(*Bytes256)(data[:256]) + data = data[256:] + payload.PrevRandao = *(*Bytes32)(data[:32]) + data = data[32:] + payload.BlockNumber = Uint64Quantity(a) + payload.GasLimit = Uint64Quantity(a) + payload.GasUsed = Uint64Quantity(a) + payload.Timestamp = Uint64Quantity(a) + if len(extraData) > 32 { + extraData = extraData[:32] + } + payload.ExtraData = extraData + payload.BaseFeePerGas.SetBytes(data[:32]) + payload.BlockHash = *(*common.Hash)(data[:32]) + payload.Transactions = make([]Data, txs) + for i := 0; i < int(txs); i++ { + if len(txsData) < 2 { + payload.Transactions[i] = make(Data, 0) + continue + } + txSize := binary.LittleEndian.Uint16(txsData[:2]) + txsData = txsData[2:] + if int(txSize) > len(txsData) { + txSize = uint16(len(txsData)) + } + payload.Transactions[i] = txsData[:txSize] + txsData = txsData[txSize:] + } + var buf bytes.Buffer + if _, err := payload.MarshalSSZ(&buf); err != nil { + t.Fatalf("failed to marshal ExecutionPayload: %v", err) + } + var roundTripped ExecutionPayload + err := roundTripped.UnmarshalSSZ(uint32(len(buf.Bytes())), bytes.NewReader(buf.Bytes())) + if err != nil { + t.Fatalf("failed to decode previously marshalled payload: %v", err) + } + if diff := cmp.Diff(payload, roundTripped); diff != "" { + t.Fatalf("The data did not round trip correctly:\n%s", diff) + } + }) +} From bdc831e1b3840ea8af804c02c7139ffda88ed8ed Mon Sep 17 00:00:00 2001 From: protolambda Date: Sun, 8 May 2022 21:08:40 +0200 Subject: [PATCH 538/585] opnode/l2: check payload block hash consistency --- opnode/l2/api.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index cb0980ad6a37..56fcbf118bbc 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -2,7 +2,10 @@ package l2 import ( + "bytes" "fmt" + "github.com/ethereum/go-ethereum/trie" + "math/big" "reflect" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -111,6 +114,40 @@ func (payload *ExecutionPayload) ID() eth.BlockID { return eth.BlockID{Hash: payload.BlockHash, Number: uint64(payload.BlockNumber)} } +type rawTransactions []Data + +func (s rawTransactions) Len() int { return len(s) } +func (s rawTransactions) EncodeIndex(i int, w *bytes.Buffer) { + w.Write(s[i]) +} + +// CheckBlockHash recomputes the block hash and returns if the embedded block hash matches. +func (payload *ExecutionPayload) CheckBlockHash() bool { + hasher := trie.NewStackTrie(nil) + txHash := types.DeriveSha(rawTransactions(payload.Transactions), hasher) + + header := types.Header{ + ParentHash: payload.ParentHash, + UncleHash: types.EmptyUncleHash, + Coinbase: payload.FeeRecipient, + Root: common.Hash(payload.StateRoot), + TxHash: txHash, + ReceiptHash: common.Hash(payload.ReceiptsRoot), + Bloom: types.Bloom(payload.LogsBloom), + Difficulty: big.NewInt(0), // zeroed, proof-of-work legacy + Number: big.NewInt(int64(payload.BlockNumber)), + GasLimit: uint64(payload.GasLimit), + GasUsed: uint64(payload.GasUsed), + Time: uint64(payload.Timestamp), + Extra: payload.ExtraData, + MixDigest: common.Hash(payload.PrevRandao), + Nonce: types.BlockNonce{}, // zeroed, proof-of-work legacy + BaseFee: payload.BaseFeePerGas.ToBig(), + } + blockHash := header.Hash() + return blockHash == payload.BlockHash +} + func BlockAsPayload(bl *types.Block) (*ExecutionPayload, error) { baseFee, overflow := uint256.FromBig(bl.BaseFee()) if overflow { From 67d5fcc0c9954967778cd1b75fe0c060d5653336 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sun, 8 May 2022 21:09:13 +0200 Subject: [PATCH 539/585] opnode/p2p,specs: update p2p block gossip validation --- opnode/l2/api.go | 3 +- opnode/l2/ssz_test.go | 3 +- opnode/p2p/gossip.go | 117 +++++++++++++++++++++++++++++---------- specs/rollup-node-p2p.md | 28 ++++++++-- 4 files changed, 115 insertions(+), 36 deletions(-) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 56fcbf118bbc..74d7b094198f 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -4,10 +4,11 @@ package l2 import ( "bytes" "fmt" - "github.com/ethereum/go-ethereum/trie" "math/big" "reflect" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum/go-ethereum/common" diff --git a/opnode/l2/ssz_test.go b/opnode/l2/ssz_test.go index 11927b39b964..94949fd5342a 100644 --- a/opnode/l2/ssz_test.go +++ b/opnode/l2/ssz_test.go @@ -3,9 +3,10 @@ package l2 import ( "bytes" "encoding/binary" + "testing" + "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" - "testing" ) // FuzzExecutionPayloadUnmarshal checks that our SSZ decoding never panics diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index a1823694cb5d..12fe925251f0 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -6,15 +6,15 @@ import ( "crypto/sha256" "encoding/binary" "fmt" + "github.com/ethereum/go-ethereum/common" + lru "github.com/hashicorp/golang-lru" "sync" "time" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" "github.com/golang/snappy" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" @@ -50,7 +50,7 @@ func BuildSubscriptionFilter(cfg *rollup.Config) pubsub.SubscriptionFilter { return pubsub.NewAllowlistSubscriptionFilter(blocksTopicV1(cfg)) // add more topics here in the future, if any. } -var msgIdBufPool = sync.Pool{New: func() any { +var msgBufPool = sync.Pool{New: func() any { // note: the topic validator concurrency is limited, so pool won't blow up, even with large pre-allocation. x := make([]byte, 0, MaxGossipSize) return &x @@ -67,8 +67,8 @@ func BuildMsgIdFn(cfg *rollup.Config) pubsub.MsgIdFunction { // and the unique hash helps detect duplicates. dLen, err := snappy.DecodedLen(pmsg.Data) if err == nil && dLen <= MaxGossipSize { - res := msgIdBufPool.Get().(*[]byte) - defer msgIdBufPool.Put(res) + res := msgBufPool.Get().(*[]byte) + defer msgBufPool.Put(res) if data, err = snappy.Decode((*res)[:0], pmsg.Data); err == nil { *res = data // if we ended up growing the slice capacity, fine, keep the larger one. valid = true @@ -131,60 +131,119 @@ func NewGossipSub(p2pCtx context.Context, h host.Host, cfg *rollup.Config) (*pub } func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx { + + // Seen block hashes per block height + // uint64 -> []common.Hash + blockHeightLRU, err := lru.New(100) + if err != nil { + panic(fmt.Errorf("failed to set up block height LRU cache: %v", err)) + } + return func(ctx context.Context, id peer.ID, message *pubsub.Message) pubsub.ValidationResult { // [REJECT] if the compression is not valid - // TODO snappy uncompress, avoid zip-bomb, pool data - uncompressedData := message.Data + outLen, err := snappy.DecodedLen(message.Data) + if err != nil { + log.Warn("invalid snappy compression length data", "err", err, "peer", id) + return pubsub.ValidationReject + } + if outLen > maxGossipSize { + log.Warn("possible snappy zip bomb, decoded length is too large", "decoded_length", outLen, "peer", id) + return pubsub.ValidationReject + } + + res := msgBufPool.Get().(*[]byte) + defer msgBufPool.Put(res) + data, err := snappy.Decode((*res)[:0], message.Data) + if err != nil { + log.Warn("invalid snappy compression", "err", err, "peer", id) + return pubsub.ValidationReject + } + *res = data // if we ended up growing the slice capacity, fine, keep the larger one. // message starts with compact-encoding secp256k1 encoded signature - signatureBytes, blockBytes := uncompressedData[:65], uncompressedData[65:] + signatureBytes, payloadBytes := data[:65], data[65:] // [REJECT] if the block encoding is not valid - var block types.Block - if err := block.DecodeRLP(rlp.NewStream(bytes.NewReader(blockBytes), maxGossipSize)); err != nil { - log.Warn("invalid block RLP", "err", err, "peer", id) + var payload l2.ExecutionPayload + if err := payload.UnmarshalSSZ(uint32(len(payloadBytes)), bytes.NewReader(payloadBytes)); err != nil { + log.Warn("invalid payload", "err", err, "peer", id) return pubsub.ValidationReject } - // [REJECT] if the block timestamp is older than 20 seconds in the past - // TODO + // rounding down to seconds is fine here. + now := uint64(time.Now().Unix()) + + // [REJECT] if the `payload.timestamp` is older than 20 seconds in the past + if uint64(payload.Timestamp) < now-20 { + log.Warn("payload is too old", "timestamp", uint64(payload.Timestamp)) + return pubsub.ValidationReject + } + + // [REJECT] if the `payload.timestamp` is more than 5 seconds into the future + if uint64(payload.Timestamp) > now+5 { + log.Warn("payload is too new", "timestamp", uint64(payload.Timestamp)) + return pubsub.ValidationReject + } - // [REJECT] if the block timestamp is more than 5 seconds into the future - // TODO + // [REJECT] if the `block_hash` in the `payload` is not valid + if !payload.CheckBlockHash() { + log.Warn("payload has bad block hash", "bad_hash", payload.BlockHash) + return pubsub.ValidationReject + } // [REJECT] if more than 5 blocks have been seen with the same block height - // TODO + seen, ok := blockHeightLRU.Get(uint64(payload.BlockNumber)) + if !ok { + seen = []common.Hash{} + } + if len(seen.([]common.Hash)) > 5 { + log.Warn("seen too many different blocks at same height", "height", payload.BlockNumber) + return pubsub.ValidationReject + } + for _, prev := range seen.([]common.Hash) { + // [IGNORE] if the block has already been seen + if prev == payload.BlockHash { + log.Warn("validated already seen message again") + return pubsub.ValidationIgnore + } + } // [REJECT] if the signature by the sequencer is not valid - var msgInput [32 + 32 + 32]byte - copy(msgInput[0:32], "optimism bedrock block v1") // message domain - cfg.L2ChainID.FillBytes(msgInput[32:64]) // protect against replaying on other chains - h := block.Hash() - copy(msgInput[64:], h[:]) - signedHash := crypto.Keccak256Hash(msgInput[:]) - // TODO: is this sufficient to verify the signature? - pub, err := crypto.SigToPub(signedHash[:], signatureBytes) + signingHash := BlockSigningHash(cfg, payloadBytes) + + pub, err := crypto.SigToPub(signingHash[:], signatureBytes) if err != nil { log.Warn("invalid block signature", "err", err, "peer", id) return pubsub.ValidationReject } addr := crypto.PubkeyToAddress(*pub) + + // TODO: in the future we can support multiple valid p2p addresses. if addr != cfg.P2PSequencerAddress { log.Warn("unexpected block author", "err", err, "peer", id) return pubsub.ValidationReject } - payload, err := l2.BlockAsPayload(&block) - if err != nil { - log.Warn("failed to convert block to execution payload", "err", err, "peer", id) - return pubsub.ValidationReject - } + seen = append(seen.([]common.Hash), payload.BlockHash) + blockHeightLRU.Add(uint64(payload.BlockNumber), seen) + // remember the decoded payload for later usage in topic subscriber. message.ValidatorData = payload return pubsub.ValidationAccept } } +func BlockSigningHash(cfg *rollup.Config, payloadBytes []byte) common.Hash { + var msgInput [32 + 32 + 32]byte + // domain: first 32 bytes, always zero for now + // chain_id: second 32 bytes + cfg.L2ChainID.FillBytes(msgInput[32:64]) + // payload_hash: third 32 bytes, hash of encoded payload + copy(msgInput[32:], crypto.Keccak256(payloadBytes)) + + return crypto.Keccak256Hash(msgInput[:]) +} + type BlockMessage struct { ReceivedFrom peer.ID Block *l2.ExecutionPayload diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index bff4f748cf02..88c91f145134 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -239,9 +239,24 @@ The primary topic of the L2, to distribute blocks to other nodes faster than pro #### Block encoding -TODO: encode execution payload (SSZ or RLP), with sequencer identifier and signature. +A block is structured as the concatenation of: -TODO: signature type and verification (`secp256k1` like transactions, with some different signature domain) +- `signature`: A `secp256k1` signature, always 65 bytes, `r (uint256), s (uint256), y_parity (uint8)` +- `payload`: A SSZ-encoded `ExecutionPayload`, always the remaining bytes. + +The topic uses Snappy block-compression (i.e. no snappy frames): +the above needs to be compressed after encoding, and decompressed before decoding. + +#### Block signatures + +The `signature` is a `secp256k1` signature, and signs over a message: +`keccak256(domain ++ chain_id ++ payload_hash)`, where: + +- `domain` is 32 bytes, reserved for message types and versioning info. All zero for this signature. +- `chain_id` is a big-endian encoded `uint256`. +- `payload_hash` is `keccak256(payload)`, where `payload` is the SSZ-encoded `ExecutionPayload` + +The `secp256k1` signature must have `y_parity = 1 or 0`, the `chain_id` is already signed over. #### Block validation @@ -252,11 +267,14 @@ In order of operation: - `[REJECT]` if the compression is not valid - `[REJECT]` if the block encoding is not valid -- `[REJECT]` if the block timestamp is older than 20 seconds in the past +- `[REJECT]` if the `payload.timestamp` is older than 20 seconds in the past (graceful boundary for worst-case propagation and clock skew) -- `[REJECT]` if the block timestamp is more than 5 seconds into the future (graceful boundary for clock skew) -- `[REJECT]` if more than 5 blocks have been seen with the same block height +- `[REJECT]` if the `payload.timestamp` is more than 5 seconds into the future +- `[REJECT]` if the `block_hash` in the `payload` is not valid +- `[REJECT]` if more than 5 different blocks have been seen with the same block height + - `[IGNORE]` if the block has already been seen - `[REJECT]` if the signature by the sequencer is not valid +- Mark the block as seen for the given block height The block is signed by the corresponding sequencer, to filter malicious messages. The sequencer model is singular but may change to multiple sequencers in the future. From ffdbc0cedf334c2ac76c774b4b0ccd18bd06fffa Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 00:05:03 +0200 Subject: [PATCH 540/585] opnode: refactor node initialization, change l1-head fan out, implement l2 payload driver receiver, setup block signing, update config / cli / e2e --- go.mod | 2 + go.sum | 2 + opnode/cmd/main.go | 2 +- opnode/eth/heads.go | 4 +- opnode/flags/flags.go | 8 - opnode/flags/p2p_flags.go | 9 + opnode/node/config.go | 6 +- opnode/node/node.go | 435 +++++++++++++++++------------ opnode/p2p/gossip.go | 86 ++++-- opnode/p2p/signer.go | 100 +++++++ opnode/rollup/driver/driver.go | 23 +- opnode/rollup/driver/state.go | 54 +++- opnode/rollup/driver/state_test.go | 40 +-- opnode/rollup/driver/step.go | 44 ++- opnode/service.go | 41 ++- opnode/test/setup.go | 24 +- opnode/test/system_test.go | 2 + 17 files changed, 570 insertions(+), 312 deletions(-) create mode 100644 opnode/p2p/signer.go diff --git a/go.mod b/go.mod index 57fb17d943ce..810faac0d8ee 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/ethereum/go-ethereum v1.10.16 github.com/golang/snappy v0.0.4 github.com/google/go-cmp v0.5.8 + github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.0 github.com/ipfs/go-datastore v0.5.0 @@ -62,6 +63,7 @@ require ( github.com/google/gopacket v1.1.19 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.0.3 // indirect diff --git a/go.sum b/go.sum index d75be364f044..b3fcf12cfed1 100644 --- a/go.sum +++ b/go.sum @@ -412,6 +412,7 @@ github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfm github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= @@ -419,6 +420,7 @@ github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 8b082b0c7fb2..fbcd2fb97bb4 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -84,7 +84,7 @@ func RollupNodeMain(ctx *cli.Context) error { log.Error("Unable to start rollup node", "error", err) return err } - defer n.Stop() + defer n.Close() log.Info("Rollup node started") diff --git a/opnode/eth/heads.go b/opnode/eth/heads.go index ee76dcb973bb..125cb8759b31 100644 --- a/opnode/eth/heads.go +++ b/opnode/eth/heads.go @@ -9,7 +9,7 @@ import ( ) // HeadSignalFn is used as callback function to accept head-signals -type HeadSignalFn func(sig L1BlockRef) +type HeadSignalFn func(ctx context.Context, sig L1BlockRef) type NewHeadSource interface { SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) @@ -27,7 +27,7 @@ func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) ( for { select { case header := <-headChanges: - fn(L1BlockRef{ + fn(ctx, L1BlockRef{ Hash: header.Hash(), Number: header.Number.Uint64(), ParentHash: header.ParentHash, diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go index 47b044f562b4..b1f0287ac18c 100644 --- a/opnode/flags/flags.go +++ b/opnode/flags/flags.go @@ -63,13 +63,6 @@ var ( EnvVar: prefixEnvVar("SEQUENCING_ENABLED"), } - // TODO: move batch submitter to stand-alone process - BatchSubmitterKeyFlag = cli.StringFlag{ - Name: "batchsubmitter.key", - Usage: "key for batch submitting", - EnvVar: prefixEnvVar("BATCHSUBMITTER_KEY"), - } - LogLevelFlag = cli.StringFlag{ Name: "log.level", Usage: "The lowest log level that will be output", @@ -101,7 +94,6 @@ var requiredFlags = []cli.Flag{ var optionalFlags = append([]cli.Flag{ L1TrustRPC, SequencingEnabledFlag, - BatchSubmitterKeyFlag, LogLevelFlag, LogFormatFlag, LogColorFlag, diff --git a/opnode/flags/p2p_flags.go b/opnode/flags/p2p_flags.go index fbf8d5def7de..3101fecd398a 100644 --- a/opnode/flags/p2p_flags.go +++ b/opnode/flags/p2p_flags.go @@ -192,6 +192,14 @@ var ( Value: "opnode_discovery_db", EnvVar: p2pEnv("DISCOVERY_PATH"), } + SequencerP2PKeyFlag = cli.StringFlag{ + Name: "p2p.sequencer.key", + Usage: "File path of hex-encoded private key for signing off on p2p application messages as sequencer.", + Required: false, + TakesFile: true, + Value: "", + EnvVar: p2pEnv("SEQUENCER_KEY"), + } ) // None of these flags are strictly required. @@ -221,4 +229,5 @@ var p2pFlags = []cli.Flag{ TimeoutDial, PeerstorePath, DiscoveryPath, + SequencerP2PKeyFlag, } diff --git a/opnode/node/config.go b/opnode/node/config.go index b586e6d7795b..0e7be0041e26 100644 --- a/opnode/node/config.go +++ b/opnode/node/config.go @@ -1,7 +1,6 @@ package node import ( - "crypto/ecdsa" "fmt" "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" @@ -25,8 +24,9 @@ type Config struct { // Sequencer flag, enables sequencing Sequencer bool - // SubmitterPrivKey, temporary config var while the batch-submitter is part of the rollup node - SubmitterPrivKey *ecdsa.PrivateKey + // P2PSigner will be used for signing off on published content + // if the node is sequencing and if the p2p stack is enabled + P2PSigner p2p.SignerSetup RPC RPCConfig diff --git a/opnode/node/node.go b/opnode/node/node.go index f4a560afb55f..dcaa0e07b12c 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -6,6 +6,8 @@ import ( "sync" "time" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" "github.com/ethereum/go-ethereum/p2p/discover" @@ -13,6 +15,8 @@ import ( "github.com/libp2p/go-libp2p-core/host" pubsub "github.com/libp2p/go-libp2p-pubsub" + multierror "github.com/hashicorp/go-multierror" + "github.com/ethereum-optimism/optimistic-specs/opnode/backoff" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -27,22 +31,30 @@ import ( ) type OpNode struct { - log log.Logger - l1Source *l1.Source // Source to fetch data from (also implements the Downloader interface) - l2Engines []*driver.Driver // engines to keep synced - l2Nodes []*rpc.Client // L2 Execution Engines to close at shutdown - server *rpcServer // RPC server hosting the rollup-node API - host host.Host // p2p host (optional, may be nil) - dv5Local *enode.LocalNode // p2p discovery identity (optional, may be nil) - dv5Udp *discover.UDPv5 // p2p discovery service (optional, may be nil) - p2pCtx context.Context // all p2p activity take this context so p2p can be shut down without stopping the node. - p2pClose context.CancelFunc - gs *pubsub.PubSub - blocks chan p2p.BlockMessage // incoming unsafe block messages - done chan struct{} - wg sync.WaitGroup + log log.Logger + appVersion string + l1HeadsSub ethereum.Subscription // Subscription to get L1 heads (automatically re-subscribes on error) + l1Source *l1.Source // Source to fetch data from (also implements the Downloader interface) + l2Lock sync.Mutex // Mutex to safely add and use different L2 resources in parallel + l2Engines []*driver.Driver // engines to keep synced + l2Nodes []*rpc.Client // L2 Execution Engines to close at shutdown + server *rpcServer // RPC server hosting the rollup-node API + host host.Host // p2p host (optional, may be nil) + dv5Local *enode.LocalNode // p2p discovery identity (optional, may be nil) + dv5Udp *discover.UDPv5 // p2p discovery service (optional, may be nil) + gs *pubsub.PubSub // p2p gossip router (optional, may be nil) + gsOut p2p.GossipOut // p2p gossip application interface for publishing (optional, may be nil) + p2pSigner p2p.Signer // p2p gogssip application messages will be signed with this signer + + // some resources cannot be stopped directly, like the p2p gossipsub router (not our design), + // and depend on this ctx to be closed. + resourcesCtx context.Context + resourcesClose context.CancelFunc } +// The OpNode handles incoming gossip +var _ p2p.GossipIn = (*OpNode)(nil) + func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) (*rpc.Client, error) { bOff := backoff.Exponential() var ret *rpc.Client @@ -68,141 +80,184 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* return nil, err } - l1Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L1NodeAddr) + n := &OpNode{ + log: log, + appVersion: appVersion, + } + // not a context leak, gossipsub is closed with a context. + n.resourcesCtx, n.resourcesClose = context.WithCancel(context.Background()) + + err := n.init(ctx, cfg) if err != nil { - return nil, fmt.Errorf("failed to dial L1 address (%s): %w", cfg.L1NodeAddr, err) + // ensure we always close the node resources if we fail to initialize the node. + if closeErr := n.Close(); closeErr != nil { + return nil, multierror.Append(err, closeErr) + } + return nil, err + } + return n, nil +} + +func (n *OpNode) init(ctx context.Context, cfg *Config) error { + + if err := n.initL1(ctx, cfg); err != nil { + return err + } + + if err := n.initL2(ctx, cfg); err != nil { + return err + } + + if err := n.initRPCServer(ctx, cfg); err != nil { + return err + } + + if err := n.initP2PSigner(ctx, cfg); err != nil { + return err + } + + if err := n.initP2P(ctx, cfg); err != nil { + return err + } + + return nil +} + +func (n *OpNode) initL1(ctx context.Context, cfg *Config) error { + l1Node, err := dialRPCClientWithBackoff(ctx, n.log, cfg.L1NodeAddr) + if err != nil { + return fmt.Errorf("failed to dial L1 address (%s): %w", cfg.L1NodeAddr, err) } // TODO: we may need to authenticate the connection with L1 // l1Node.SetHeader() - l1Source, err := l1.NewSource(l1Node, log, l1.DefaultConfig(&cfg.Rollup, cfg.L1TrustRPC)) + n.l1Source, err = l1.NewSource(l1Node, n.log, l1.DefaultConfig(&cfg.Rollup, cfg.L1TrustRPC)) if err != nil { - return nil, fmt.Errorf("failed to create L1 source: %v", err) + return fmt.Errorf("failed to create L1 source: %v", err) } - var l2Engines []*driver.Driver - genesis := cfg.Rollup.Genesis - var l2Nodes []*rpc.Client - closeNodes := func() { - for _, n := range l2Nodes { - n.Close() + // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync + n.l1HeadsSub = event.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (event.Subscription, error) { + if err != nil { + n.log.Warn("resubscribing after failed L1 subscription", "err", err) } + return eth.WatchHeadChanges(n.resourcesCtx, n.l1Source, n.OnNewL1Head) + }) + go func() { + err, ok := <-n.l1HeadsSub.Err() + if !ok { + return + } + n.log.Error("l1 heads subscription error", "err", err) + }() + return nil +} + +// AttachEngine attaches an engine to the rollup node. +func (n *OpNode) AttachEngine(ctx context.Context, cfg *Config, addr string) error { + n.l2Lock.Lock() + defer n.l2Lock.Unlock() + + l2Node, err := dialRPCClientWithBackoff(ctx, n.log, addr) + if err != nil { + return err } - for i, addr := range cfg.L2EngineAddrs { - l2Node, err := dialRPCClientWithBackoff(ctx, log, addr) - if err != nil { - closeNodes() - return nil, err - } - l2Nodes = append(l2Nodes, l2Node) + // TODO: we may need to authenticate the connection with L2 + // backend.SetHeader() + client, err := l2.NewSource(l2Node, &cfg.Rollup.Genesis, n.log.New("engine", addr)) + if err != nil { + l2Node.Close() + return err + } - // TODO: we may need to authenticate the connection with L2 - // backend.SetHeader() - client, err := l2.NewSource(l2Node, &genesis, log.New("engine_client", i)) - if err != nil { - closeNodes() - return nil, err - } + driverLog := log.New("engine", addr, "Sequencer", cfg.Sequencer) + engine := driver.NewDriver(cfg.Rollup, client, n.l1Source, n, driverLog, cfg.Sequencer) + + n.l2Nodes = append(n.l2Nodes, l2Node) + n.l2Engines = append(n.l2Engines, engine) + return nil +} - engine := driver.NewDriver(cfg.Rollup, client, l1Source, log.New("engine", i, "Sequencer", cfg.Sequencer), cfg.Sequencer) - l2Engines = append(l2Engines, engine) +func (n *OpNode) initL2(ctx context.Context, cfg *Config) error { + for i, addr := range cfg.L2EngineAddrs { + if err := n.AttachEngine(ctx, cfg, addr); err != nil { + return fmt.Errorf("failed to attach configured engine %d (%s): %v", i, addr, err) + } } + return nil +} - l2Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L2NodeAddr) +func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error { + l2Node, err := dialRPCClientWithBackoff(ctx, n.log, cfg.L2NodeAddr) if err != nil { - return nil, fmt.Errorf("failed to dial l2 address (%s): %w", cfg.L2NodeAddr, err) + return fmt.Errorf("failed to dial l2 address (%s): %w", cfg.L2NodeAddr, err) } - client, err := l2.NewReadOnlySource(l2Node, &genesis, log) + client, err := l2.NewReadOnlySource(l2Node, &cfg.Rollup.Genesis, n.log) if err != nil { - return nil, err + return err } - server, err := newRPCServer(ctx, &cfg.RPC, &cfg.Rollup, client, log, appVersion) + n.server, err = newRPCServer(ctx, &cfg.RPC, &cfg.Rollup, client, n.log, n.appVersion) if err != nil { - return nil, err + return err } + n.log.Info("Starting JSON-RPC server") + if err := n.server.Start(); err != nil { + return fmt.Errorf("unable to start RPC server: %w", err) + } + return nil +} - n := &OpNode{ - log: log, - l1Source: l1Source, - l2Engines: l2Engines, - server: server, - done: make(chan struct{}), - l2Nodes: l2Nodes, - blocks: make(chan p2p.BlockMessage, 10), - } - - if cfg.P2P != nil { - // All nil if disabled. - n.dv5Local, n.dv5Udp, err = cfg.P2P.Discovery(log.New("p2p", "discv5")) - if err != nil { - return nil, fmt.Errorf("failed to start discv5: %v", err) - } +func (n *OpNode) initP2P(ctx context.Context, cfg *Config) error { + // the p2p setup is optional + if cfg.P2P == nil { + return nil + } + var err error + // All nil if disabled. + n.dv5Local, n.dv5Udp, err = cfg.P2P.Discovery(log.New("p2p", "discv5")) + if err != nil { + return fmt.Errorf("failed to start discv5: %v", err) + } - // nil if disabled. - n.host, err = cfg.P2P.Host() + // nil if disabled. + n.host, err = cfg.P2P.Host() + if err != nil { + return fmt.Errorf("failed to start p2p host: %v", err) + } + if n.host != nil { + n.gs, err = p2p.NewGossipSub(n.resourcesCtx, n.host, &cfg.Rollup) if err != nil { - return nil, fmt.Errorf("failed to start p2p host: %v", err) + return fmt.Errorf("failed to start gossipsub router: %v", err) } - if n.host != nil { - // not a context leak, gossipsub is closed with a context. - // TODO: maybe we can improve this, or closing the Host is enough? - n.p2pCtx, n.p2pClose = context.WithCancel(context.Background()) - closeP2P := func() { - if n.dv5Udp != nil { - n.dv5Udp.Close() - } - _ = n.host.Close() - n.p2pClose() - } - gs, err := p2p.NewGossipSub(n.p2pCtx, n.host, &cfg.Rollup) - if err != nil { - closeP2P() - return nil, fmt.Errorf("failed to start gossipsub router: %v", err) - } - n.gs = gs - if err := p2p.JoinGossip(n.p2pCtx, n.gs, log, &cfg.Rollup, n.blocks); err != nil { - closeP2P() - return nil, fmt.Errorf("failed to join blocks gossip topic: %v", err) - } + n.gsOut, err = p2p.JoinGossip(n.resourcesCtx, n.gs, n.log, &cfg.Rollup, n) + if err != nil { + return fmt.Errorf("failed to join blocks gossip topic: %v", err) } } - - return n, nil + return nil } -func (c *OpNode) Start(ctx context.Context) error { - c.log.Info("Starting OpNode") - - var unsub []func() - handleUnsubscribe := func(sub ethereum.Subscription, errMsg string) { - unsub = append(unsub, sub.Unsubscribe) - go func() { - err, ok := <-sub.Err() - if !ok { - return - } - c.log.Error(errMsg, "err", err) - }() +func (n *OpNode) initP2PSigner(ctx context.Context, cfg *Config) error { + // the p2p signer setup is optional + if cfg.P2PSigner == nil { + return nil } + // p2pSigner may still be nil, the signer setup may not create any signer, the signer is optional + var err error + n.p2pSigner, err = cfg.P2PSigner.SetupSigner(ctx) + return err +} - c.log.Info("Fetching rollup starting point") - - // Feed of eth.L1BlockRef - var l1HeadsFeed event.Feed - - c.log.Info("Attaching execution engine(s)") +func (c *OpNode) Start(ctx context.Context) error { + c.log.Info("Starting execution engine driver(s)") for _, eng := range c.l2Engines { // Request initial head update, default to genesis otherwise reqCtx, reqCancel := context.WithTimeout(ctx, time.Second*10) - - // driver subscribes to L1 head changes - l1SubCh := make(chan eth.L1BlockRef, 10) - l1HeadsFeed.Subscribe(l1SubCh) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine - err := eng.Start(reqCtx, l1SubCh) + err := eng.Start(reqCtx) reqCancel() if err != nil { c.log.Error("Could not start a rollup node", "err", err) @@ -210,79 +265,103 @@ func (c *OpNode) Start(ctx context.Context) error { } } - // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync - l1HeadsSub := event.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (event.Subscription, error) { - if err != nil { - c.log.Warn("resubscribing after failed L1 subscription", "err", err) - } - return eth.WatchHeadChanges(context.Background(), c.l1Source, func(sig eth.L1BlockRef) { - l1HeadsFeed.Send(sig) - }) - }) - handleUnsubscribe(l1HeadsSub, "l1 heads subscription failed") + return nil +} - // subscribe to L1 heads for info - l1Heads := make(chan eth.L1BlockRef, 10) - l1HeadsFeed.Subscribe(l1Heads) +func (c *OpNode) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) { + c.l2Lock.Lock() + defer c.l2Lock.Unlock() - c.log.Info("Starting JSON-RPC server") - if err := c.server.Start(); err != nil { - return fmt.Errorf("unable to start RPC server: %w", err) - } + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() - c.log.Info("Start-up complete!") - c.wg.Add(1) - go func() { - defer c.wg.Done() - for { - select { - case l2Block := <-c.blocks: - c.log.Info("Received L2 unsafe block", "hash", l2Block.Block.BlockHash, "from", l2Block.ReceivedFrom) - // TODO: process unsafe block in all engines - case l1Head := <-l1Heads: - c.log.Info("New L1 head", "head", l1Head, "parent", l1Head.ParentHash) - // TODO: maybe log other info on interval or other chain events (individual engines also log things) - case <-c.done: - c.log.Info("Closing OpNode") - if c.dv5Udp != nil { - c.dv5Udp.Close() - } - if c.host != nil { - if err := c.host.Close(); err != nil { - c.log.Error("failed to close p2p host cleanly: %v", err) - } - } - if c.p2pClose != nil { - c.p2pClose() - } - // close all tasks - for _, f := range unsub { - f() - } - // close L2 engines - for _, eng := range c.l2Engines { - if err := eng.Close(); err != nil { - c.log.Error("failed to close L2 engine driver cleanly: %v", err) - } - } - // close L2 nodes - for _, n := range c.l2Nodes { - n.Close() - } - // close L1 data source - c.l1Source.Close() - - return + // fan-out to all engine drivers + for _, eng := range c.l2Engines { + go func(eng *driver.Driver) { + if err := eng.OnL1Head(ctx, sig); err != nil { + c.log.Warn("failed to notify engine driver of L1 head change", "err", err) } + }(eng) + } +} + +func (c *OpNode) PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error { + // publish to p2p, if we are running p2p at all + if c.gsOut != nil { + if c.p2pSigner == nil { + return fmt.Errorf("node has no p2p signer, payload %s cannot be published", payload.ID()) } - }() + return c.gsOut.PublishL2Payload(ctx, payload, c.p2pSigner) + } + // if p2p is not enabled then we just don't publish the payload return nil } -func (c *OpNode) Stop() { - if c.done != nil { - close(c.done) +func (c *OpNode) ReceiveL2Payload(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) error { + c.l2Lock.Lock() + defer c.l2Lock.Unlock() + + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() + + // fan-out to all engine drivers + for _, eng := range c.l2Engines { + go func(eng *driver.Driver) { + if err := eng.OnUnsafeL2Payload(ctx, payload); err != nil { + c.log.Warn("failed to notify engine driver of new L2 payload", "err", err, "id", payload.ID()) + } + }(eng) + } + return nil +} + +// Close closes all resources. +func (c *OpNode) Close() error { + var result *multierror.Error + + if c.server != nil { + c.server.Stop() + } + if c.dv5Udp != nil { + c.dv5Udp.Close() + } + if c.gsOut != nil { + if err := c.gsOut.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close gossip cleanly: %v", err)) + } + } + if c.p2pSigner != nil { + if err := c.p2pSigner.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close p2p signer: %v", err)) + } + } + if c.host != nil { + if err := c.host.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close p2p host cleanly: %v", err)) + } + } + if c.resourcesClose != nil { + c.resourcesClose() + } + + // stop L1 heads feed + if c.l1HeadsSub != nil { + c.l1HeadsSub.Unsubscribe() + } + + // close L2 engines + for _, eng := range c.l2Engines { + if err := eng.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close L2 engine driver cleanly: %v", err)) + } + } + // close L2 nodes + for _, n := range c.l2Nodes { + n.Close() + } + // close L1 data source + if c.l1Source != nil { + c.l1Source.Close() } - c.wg.Wait() - c.server.Stop() + return result.ErrorOrNil() } diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index 12fe925251f0..2f84eb67b709 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -6,11 +6,12 @@ import ( "crypto/sha256" "encoding/binary" "fmt" - "github.com/ethereum/go-ethereum/common" - lru "github.com/hashicorp/golang-lru" "sync" "time" + "github.com/ethereum/go-ethereum/common" + lru "github.com/hashicorp/golang-lru" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/crypto" @@ -24,6 +25,7 @@ import ( func init() { // TODO: a PR is open to make this configurable upstream as option instead of having to override a global + // https://github.com/libp2p/go-libp2p-pubsub/pull/484 pubsub.TimeCacheDuration = 80 * pubsub.GossipSubHeartbeatInterval } @@ -233,67 +235,89 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx } } -func BlockSigningHash(cfg *rollup.Config, payloadBytes []byte) common.Hash { - var msgInput [32 + 32 + 32]byte - // domain: first 32 bytes, always zero for now - // chain_id: second 32 bytes - cfg.L2ChainID.FillBytes(msgInput[32:64]) - // payload_hash: third 32 bytes, hash of encoded payload - copy(msgInput[32:], crypto.Keccak256(payloadBytes)) +type GossipIn interface { + ReceiveL2Payload(ctx context.Context, from peer.ID, msg *l2.ExecutionPayload) error +} - return crypto.Keccak256Hash(msgInput[:]) +type GossipOut interface { + PublishL2Payload(ctx context.Context, msg *l2.ExecutionPayload, signer Signer) error + BlocksTopicPeers() []peer.ID + Close() error } -type BlockMessage struct { - ReceivedFrom peer.ID - Block *l2.ExecutionPayload +type publisher struct { + cfg *rollup.Config + blocksTopic *pubsub.Topic } -func JoinGossip(p2pCtx context.Context, ps *pubsub.PubSub, log log.Logger, cfg *rollup.Config, blocks chan<- BlockMessage) error { +var _ GossipOut = (*publisher)(nil) + +func (p *publisher) BlocksTopicPeers() []peer.ID { + return p.blocksTopic.ListPeers() +} + +func (p *publisher) PublishL2Payload(ctx context.Context, msg *l2.ExecutionPayload, signer Signer) error { + var buf bytes.Buffer + buf.Write(make([]byte, 65)) + if _, err := msg.MarshalSSZ(&buf); err != nil { + return fmt.Errorf("failed to encoded execution payload to publish: %v", err) + } + data := buf.Bytes() + payloadData := data[65:] + sig, err := signer.Sign(ctx, SigningDomainBlocksV1, p.cfg.L2ChainID, payloadData) + if err != nil { + return fmt.Errorf("failed to sign execution payload with signer: %v", err) + } + copy(data[:65], sig[:]) + + return p.blocksTopic.Publish(ctx, data) +} + +func (p *publisher) Close() error { + return p.blocksTopic.Close() +} + +func JoinGossip(p2pCtx context.Context, ps *pubsub.PubSub, log log.Logger, cfg *rollup.Config, gossipIn GossipIn) (GossipOut, error) { val := BuildBlocksValidator(log, cfg) - topicName := blocksTopicV1(cfg) - err := ps.RegisterTopicValidator(topicName, + blocksTopicName := blocksTopicV1(cfg) + err := ps.RegisterTopicValidator(blocksTopicName, val, pubsub.WithValidatorTimeout(3*time.Second), pubsub.WithValidatorConcurrency(4)) if err != nil { - return fmt.Errorf("failed to register blocks gossip topic: %v", err) + return nil, fmt.Errorf("failed to register blocks gossip topic: %v", err) } - topic, err := ps.Join(topicName) + blocksTopic, err := ps.Join(blocksTopicName) if err != nil { - return fmt.Errorf("failed to join blocks gossip topic: %v", err) + return nil, fmt.Errorf("failed to join blocks gossip topic: %v", err) } // TODO: block topic scoring parameters // See prysm: https://github.com/prysmaticlabs/prysm/blob/develop/beacon-chain/p2p/gossip_scoring_params.go // And research from lighthouse: https://gist.github.com/blacktemplar/5c1862cb3f0e32a1a7fb0b25e79e6e2c // And docs: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#topic-parameter-calculation-and-decay - //err := topic.SetScoreParams(&pubsub.TopicScoreParams{......}) + //err := blocksTopic.SetScoreParams(&pubsub.TopicScoreParams{......}) - subscription, err := topic.Subscribe() + subscription, err := blocksTopic.Subscribe() if err != nil { - return fmt.Errorf("failed to subscribe to blocks gossip topic: %v", err) + return nil, fmt.Errorf("failed to subscribe to blocks gossip topic: %v", err) } - subscriber := MakeSubscriber(log, BlocksHandler(blocks)) + subscriber := MakeSubscriber(log, BlocksHandler(gossipIn.ReceiveL2Payload)) go subscriber(p2pCtx, subscription) - return nil + + return &publisher{cfg: cfg, blocksTopic: blocksTopic}, nil } type TopicSubscriber func(ctx context.Context, sub *pubsub.Subscription) type MessageHandler func(ctx context.Context, from peer.ID, msg interface{}) error -func BlocksHandler(out chan<- BlockMessage) MessageHandler { +func BlocksHandler(onBlock func(ctx context.Context, from peer.ID, msg *l2.ExecutionPayload) error) MessageHandler { return func(ctx context.Context, from peer.ID, msg interface{}) error { payload, ok := msg.(*l2.ExecutionPayload) if !ok { return fmt.Errorf("expected topic validator to parse and validate data into execution payload, but got %T", msg) } - select { - case <-ctx.Done(): - return ctx.Err() - case out <- BlockMessage{ReceivedFrom: from, Block: payload}: - return nil - } + return onBlock(ctx, from, payload) } } diff --git a/opnode/p2p/signer.go b/opnode/p2p/signer.go new file mode 100644 index 000000000000..e2a5cc2b53e3 --- /dev/null +++ b/opnode/p2p/signer.go @@ -0,0 +1,100 @@ +package p2p + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "io" + "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/urfave/cli" +) + +var SigningDomainBlocksV1 = [32]byte{} + +type Signer interface { + Sign(ctx context.Context, domain [32]byte, chainID *big.Int, encodedMsg []byte) (sig *[65]byte, err error) + io.Closer +} + +func SigningHash(domain [32]byte, chainID *big.Int, payloadBytes []byte) common.Hash { + var msgInput [32 + 32 + 32]byte + // domain: first 32 bytes + copy(msgInput[:32], domain[:]) + // chain_id: second 32 bytes + chainID.FillBytes(msgInput[32:64]) + // payload_hash: third 32 bytes, hash of encoded payload + copy(msgInput[32:], crypto.Keccak256(payloadBytes)) + + return crypto.Keccak256Hash(msgInput[:]) +} + +func BlockSigningHash(cfg *rollup.Config, payloadBytes []byte) common.Hash { + return SigningHash(SigningDomainBlocksV1, cfg.L2ChainID, payloadBytes) +} + +// LocalSigner is suitable for testing +type LocalSigner struct { + priv *ecdsa.PrivateKey +} + +func NewLocalSigner(priv *ecdsa.PrivateKey) *LocalSigner { + return &LocalSigner{priv: priv} +} + +func (s *LocalSigner) Sign(ctx context.Context, domain [32]byte, chainID *big.Int, encodedMsg []byte) (sig *[65]byte, err error) { + if s.priv == nil { + return nil, errors.New("signer is closed") + } + signingHash := SigningHash(domain, chainID, encodedMsg) + signature, err := crypto.Sign(signingHash[:], s.priv) + if err != nil { + return nil, err + } + return (*[65]byte)(signature), nil +} + +func (s *LocalSigner) Close() error { + s.priv = nil + return nil +} + +type PreparedSigner struct { + Signer +} + +func (p *PreparedSigner) SetupSigner(ctx context.Context) (Signer, error) { + return p.Signer, nil +} + +// TODO: implement remote signer setup (config to authenticated endpoint) +// and remote signer itself (e.g. a open http client to make signing requests) + +type SignerSetup interface { + SetupSigner(ctx context.Context) (Signer, error) +} + +// LoadSignerSetup loads a configuration for a Signer to be set up later +func LoadSignerSetup(ctx *cli.Context) (SignerSetup, error) { + keyFile := ctx.GlobalString(flags.SequencerP2PKeyFlag.Name) + if keyFile != "" { + // Mnemonics are bad because they leak *all* keys when they leak. + // Unencrypted keys from file are bad because they are easy to leak (and we are not checking file permissions). + // TODO: load from encrypted keystore + priv, err := crypto.LoadECDSA(keyFile) + if err != nil { + return nil, fmt.Errorf("failed to read batch submitter key: %v", err) + } + + return &PreparedSigner{Signer: NewLocalSigner(priv)}, nil + } + + // TODO: create remote signer + + return nil, nil +} diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index e2d7d3f98bc3..52d132569289 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -55,10 +55,15 @@ type outputInterface interface { insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) // createNewBlock builds a new block based on the L2 Head, L1 Origin, and the current mempool. - createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) + createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *l2.ExecutionPayload, error) } -func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, sequencer bool) *Driver { +type Network interface { + // PublishL2Payload is called by the driver whenever there is a new payload to publish, synchronously with the driver main loop. + PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error +} + +func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, network Network, log log.Logger, sequencer bool) *Driver { output := &outputImpl{ Config: cfg, dl: l1, @@ -66,12 +71,20 @@ func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, log log.Logger, log: log, } return &Driver{ - s: NewState(log, cfg, l1, l2, output, sequencer), + s: NewState(log, cfg, l1, l2, output, network, sequencer), } } -func (d *Driver) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error { - return d.s.Start(ctx, l1Heads) +func (d *Driver) OnL1Head(ctx context.Context, head eth.L1BlockRef) error { + return d.s.OnL1Head(ctx, head) +} + +func (d *Driver) OnUnsafeL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error { + return d.s.OnUnsafeL2Payload(ctx, payload) +} + +func (d *Driver) Start(ctx context.Context) error { + return d.s.Start(ctx) } func (d *Driver) Close() error { return d.s.Close() diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index e05ce3f0e58c..a952d891d259 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -26,10 +26,12 @@ type state struct { sequencer bool // Connections (in/out) - l1Heads <-chan eth.L1BlockRef - l1 L1Chain - l2 L2Chain - output outputInterface + l1Heads chan eth.L1BlockRef + unsafeL2Payloads chan *l2.ExecutionPayload + l1 L1Chain + l2 L2Chain + output outputInterface + network Network // may be nil, network for is optional log log.Logger done chan struct{} @@ -37,7 +39,9 @@ type state struct { wg gosync.WaitGroup } -func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, sequencer bool) *state { +// NewState creates a new driver state. State changes take effect though the given output. +// Optionally a network can be provided to publish things to other nodes than the engine of the driver. +func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, network Network, sequencer bool) *state { return &state{ Config: config, done: make(chan struct{}), @@ -45,13 +49,15 @@ func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, outp l1: l1, l2: l2, output: output, + network: network, sequencer: sequencer, + l1Heads: make(chan eth.L1BlockRef, 10), } } -// Start starts up the state loop. The context is only for initilization. +// Start starts up the state loop. The context is only for initialization. // The loop will have been started iff err is not nil. -func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error { +func (s *state) Start(ctx context.Context) error { l1Head, err := s.l1.L1HeadBlockRef(ctx) if err != nil { return err @@ -89,7 +95,6 @@ func (s *state) Start(ctx context.Context, l1Heads <-chan eth.L1BlockRef) error } s.l1Head = l1Head - s.l1Heads = l1Heads s.wg.Add(1) go s.loop() @@ -102,6 +107,24 @@ func (s *state) Close() error { return nil } +func (s *state) OnL1Head(ctx context.Context, head eth.L1BlockRef) error { + select { + case <-ctx.Done(): + return ctx.Err() + case s.l1Heads <- head: + return nil + } +} + +func (s *state) OnUnsafeL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error { + select { + case <-ctx.Done(): + return ctx.Err() + case s.unsafeL2Payloads <- payload: + return nil + } +} + // l1WindowBufEnd returns the last block that should be used as `base` to L1ChainWindow. // This is either the last block of the window, or the L1 base block if the window is not populated. func (s *state) l1WindowBufEnd() eth.BlockID { @@ -225,7 +248,7 @@ func (s *state) createNewL2Block(ctx context.Context) error { } // Actually create the new block. - newUnsafeL2Head, batch, err := s.output.createNewBlock(ctx, s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, l1Origin) + newUnsafeL2Head, payload, err := s.output.createNewBlock(ctx, s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, l1Origin) if err != nil { s.log.Error("Could not extend chain as sequencer", "err", err, "l2UnsafeHead", s.l2Head, "l1Origin", l1Origin) return err @@ -233,7 +256,14 @@ func (s *state) createNewL2Block(ctx context.Context) error { // Update our L2 head block based on the new unsafe block we just generated. s.l2Head = newUnsafeL2Head - s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin, "txs", len(batch.Transactions), "time", s.l2Head.Time) + s.log.Info("Sequenced new l2 block", "l2Head", s.l2Head, "l1Origin", s.l2Head.L1Origin, "txs", len(payload.Transactions), "time", s.l2Head.Time) + + if s.network != nil { + if err := s.network.PublishL2Payload(ctx, payload); err != nil { + s.log.Warn("failed to publish newly created block", "id", payload.ID(), "err", err) + return err + } + } return nil } @@ -354,6 +384,10 @@ func (s *state) loop() { time.AfterFunc(time.Millisecond*10, reqL2BlockCreation) } + case payload := <-s.unsafeL2Payloads: + s.log.Info("Optimistically processing unsafe L2 execution payload", "id", payload.ID()) + // TODO process the L2 payload + case newL1Head := <-s.l1Heads: ctx, cancel := context.WithTimeout(ctx, 10*time.Second) err := s.handleNewL1Block(ctx, newL1Head) diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index ced26036c0fd..1e78ff2a45a0 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -7,11 +7,13 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testutils" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" @@ -48,7 +50,7 @@ func (fn outputHandlerFn) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef return fn(ctx, l2Head, l2SafeHead, l2Finalized, l1Input) } -func (fn outputHandlerFn) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) { +func (fn outputHandlerFn) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *l2.ExecutionPayload, error) { panic("Unimplemented") } @@ -70,27 +72,27 @@ type stateTestCaseStep struct { window []testID // l1act and l2act are ran at each step - l1act func(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) + l1act func(t *testing.T, s *state, src *testutils.FakeChainSource) l2act func(t *testing.T, expectedWindow []testID, s *state, src *testutils.FakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) reorg bool } -func advanceL1(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) { - l1Heads <- src.AdvanceL1() +func advanceL1(t *testing.T, s *state, src *testutils.FakeChainSource) { + require.NoError(t, s.OnL1Head(context.Background(), src.AdvanceL1())) } -func stutterL1(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) { - l1Heads <- src.L1Head() +func stutterL1(t *testing.T, s *state, src *testutils.FakeChainSource) { + require.NoError(t, s.OnL1Head(context.Background(), src.L1Head())) } -func stutterAdvance(t *testing.T, s *state, src *testutils.FakeChainSource, l1Heads chan eth.L1BlockRef) { - l1Heads <- src.L1Head() - l1Heads <- src.L1Head() - l1Heads <- src.L1Head() - l1Heads <- src.AdvanceL1() - l1Heads <- src.L1Head() - l1Heads <- src.L1Head() - l1Heads <- src.L1Head() +func stutterAdvance(t *testing.T, s *state, src *testutils.FakeChainSource) { + stutterL1(t, s, src) + stutterL1(t, s, src) + stutterL1(t, s, src) + advanceL1(t, s, src) + stutterL1(t, s, src) + stutterL1(t, s, src) + stutterL1(t, s, src) } func stutterL2(t *testing.T, expectedWindow []testID, s *state, src *testutils.FakeChainSource, outputIn chan outputArgs, outputReturn chan outputReturnArgs) { @@ -134,7 +136,7 @@ type stateTestCase struct { func (tc *stateTestCase) Run(t *testing.T) { log := testlog.Logger(t, log.LvlError) chainSource := testutils.NewFakeChainSource(tc.l1Chains, tc.l2Chains, 0, log) - l1headsCh := make(chan eth.L1BlockRef, 10) + // Unbuffered channels to force a sync point between the test and the state loop. outputIn := make(chan outputArgs) outputReturn := make(chan outputReturnArgs) @@ -145,19 +147,19 @@ func (tc *stateTestCase) Run(t *testing.T) { return r.l2Head, r.l2Head, false, r.err } config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis, BlockTime: 2} - state := NewState(log, config, chainSource, chainSource, outputHandlerFn(outputHandler), false) + state := NewState(log, config, chainSource, chainSource, outputHandlerFn(outputHandler), nil, false) defer func() { assert.NoError(t, state.Close(), "Error closing state") }() - err := state.Start(context.Background(), l1headsCh) + err := state.Start(context.Background()) assert.NoError(t, err, "Error starting the state object") for _, step := range tc.steps { if step.reorg { chainSource.ReorgL1() } - step.l1act(t, state, chainSource, l1headsCh) + step.l1act(t, state, chainSource) <-time.After(5 * time.Millisecond) step.l2act(t, step.window, state, chainSource, outputIn, outputReturn) <-time.After(5 * time.Millisecond) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index d81bb2627610..6238b75fec58 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -54,7 +54,7 @@ func lastDeposit(txns []l2.Data) (int, error) { return lastDeposit, nil } -func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *derive.BatchData, error) { +func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *l2.ExecutionPayload, error) { d.log.Info("creating new block", "parent", l2Head, "l1Origin", l1Origin) fetchCtx, cancel := context.WithTimeout(ctx, time.Second*20) @@ -124,7 +124,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, } // Actually execute the block and add it to the head of the chain. - payload, lastDeposit, err := d.insertHeadBlock(ctx, fc, attrs, false) + payload, err := d.insertHeadBlock(ctx, fc, attrs, false) if err != nil { return l2Head, nil, fmt.Errorf("failed to extend L2 chain: %v", err) } @@ -132,17 +132,7 @@ func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, // Generate an L2 block ref from the payload. ref, err := l2.PayloadToBlockRef(payload, &d.Config.Genesis) - // Derive relevant batch data so we can submit this block to L1. - // TODO: Can this be removed when batch submission is separated? - batch := &derive.BatchData{ - BatchV1: derive.BatchV1{ - Epoch: rollup.Epoch(l1Info.NumberU64()), - Timestamp: uint64(payload.Timestamp), - Transactions: payload.Transactions[lastDeposit+1:], - }, - } - - return ref, batch, err + return ref, payload, err } // insertEpoch creates and inserts one epoch on top of the safe head. It prefers blocks it creates to what is recorded in the unsafe chain. @@ -243,7 +233,7 @@ func (d *outputImpl) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2S } else { d.log.Debug("inserting new batch after lastHead", "lastHead", lastHead.ID()) - payload, _, err = d.insertHeadBlock(ctx, fc, attrs, true) + payload, err = d.insertHeadBlock(ctx, fc, attrs, true) } if err != nil { return lastHead, lastSafeHead, didReorg, fmt.Errorf("failed to extend L2 chain at block %d/%d of epoch %d: %w", i, len(batches), epoch, err) @@ -310,7 +300,7 @@ func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, d.log.Warn("Detected L2 reorg when verifying L2 safe head", "parent", parent, "prev_block", payload.BlockHash, "mismatch", err) fc.HeadBlockHash = parent.Hash fc.SafeBlockHash = parent.Hash - payload, _, err := d.insertHeadBlock(ctx, fc, attrs, true) + payload, err := d.insertHeadBlock(ctx, fc, attrs, true) return payload, true, err } // If the attributes match, just bump the safe head @@ -328,41 +318,41 @@ func (d *outputImpl) verifySafeBlock(ctx context.Context, fc l2.ForkchoiceState, // sets the FC to the same safe and finalized hashes, but updates the head hash to the new block. // If updateSafe is true, the head block is considered to be the safe head as well as the head. // It returns the payload, the count of deposits, and an error. -func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, updateSafe bool) (*l2.ExecutionPayload, int, error) { +func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, attrs *l2.PayloadAttributes, updateSafe bool) (*l2.ExecutionPayload, error) { fcRes, err := d.l2.ForkchoiceUpdate(ctx, &fc, attrs) if err != nil { - return nil, 0, fmt.Errorf("failed to create new block via forkchoice: %w", err) + return nil, fmt.Errorf("failed to create new block via forkchoice: %w", err) } id := fcRes.PayloadID if id == nil { - return nil, 0, errors.New("nil id in forkchoice result when expecting a valid ID") + return nil, errors.New("nil id in forkchoice result when expecting a valid ID") } payload, err := d.l2.GetPayload(ctx, *id) if err != nil { - return nil, 0, fmt.Errorf("failed to get execution payload: %w", err) + return nil, fmt.Errorf("failed to get execution payload: %w", err) } // Sanity check payload before inserting it if len(payload.Transactions) == 0 { - return nil, 0, errors.New("no transactions in returned payload") + return nil, errors.New("no transactions in returned payload") } if payload.Transactions[0][0] != types.DepositTxType { - return nil, 0, fmt.Errorf("first transaction was not deposit tx. Got %v", payload.Transactions[0][0]) + return nil, fmt.Errorf("first transaction was not deposit tx. Got %v", payload.Transactions[0][0]) } // Ensure that the deposits are first lastDeposit, err := lastDeposit(payload.Transactions) if err != nil { - return nil, 0, fmt.Errorf("failed to find last deposit: %w", err) + return nil, fmt.Errorf("failed to find last deposit: %w", err) } // Ensure no deposits after last deposit for i := lastDeposit + 1; i < len(payload.Transactions); i++ { tx := payload.Transactions[i] deposit, err := isDepositTx(tx) if err != nil { - return nil, 0, fmt.Errorf("failed to decode transaction idx %d: %w", i, err) + return nil, fmt.Errorf("failed to decode transaction idx %d: %w", i, err) } if deposit { d.log.Error("Produced an invalid block where the deposit txns are not all at the start of the block", "tx_idx", i, "lastDeposit", lastDeposit) - return nil, 0, fmt.Errorf("deposit tx (%d) after other tx in l2 block with prev deposit at idx %d", i, lastDeposit) + return nil, fmt.Errorf("deposit tx (%d) after other tx in l2 block with prev deposit at idx %d", i, lastDeposit) } } // If this is an unsafe block, it has deposits & transactions included from L2. @@ -374,7 +364,7 @@ func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, err = d.l2.NewPayload(ctx, payload) if err != nil { - return nil, 0, fmt.Errorf("failed to insert execution payload: %w", err) + return nil, fmt.Errorf("failed to insert execution payload: %w", err) } fc.HeadBlockHash = payload.BlockHash if updateSafe { @@ -383,7 +373,7 @@ func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, d.log.Debug("Inserted L2 head block", "number", uint64(payload.BlockNumber), "hash", payload.BlockHash, "update_safe", updateSafe) _, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { - return nil, 0, fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", err) + return nil, fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", err) } - return payload, lastDeposit, nil + return payload, nil } diff --git a/opnode/service.go b/opnode/service.go index 08cfd552194d..5d272f5e1f90 100644 --- a/opnode/service.go +++ b/opnode/service.go @@ -1,16 +1,15 @@ package opnode import ( - "crypto/ecdsa" "encoding/json" - "errors" "fmt" "os" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum/go-ethereum/crypto" "github.com/urfave/cli" ) @@ -23,33 +22,29 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) { enableSequencing := ctx.GlobalBool(flags.SequencingEnabledFlag.Name) - var batchSubmitterKey *ecdsa.PrivateKey - if enableSequencing { - keyFile := ctx.GlobalString(flags.BatchSubmitterKeyFlag.Name) - if keyFile == "" { - return nil, errors.New("sequencer mode needs batch-submitter key") - } - // TODO we should be using encrypted keystores. - // Mnemonics are bad because they leak *all* keys when they leak - // Unencrypted keys from file are bad because they are easy to leak (and we are not checking file permissions) - batchSubmitterKey, err = crypto.LoadECDSA(keyFile) - if err != nil { - return nil, fmt.Errorf("failed to read batch submitter key: %v", err) - } + p2pSignerSetup, err := p2p.LoadSignerSetup(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load p2p signer: %v", err) + } + + p2pConfig, err := p2p.NewConfig(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load p2p config: %v", err) } cfg := &node.Config{ - L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), - L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), - L2NodeAddr: ctx.GlobalString(flags.L2EthNodeAddr.Name), - L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name), - Rollup: *rollupConfig, - Sequencer: enableSequencing, - SubmitterPrivKey: batchSubmitterKey, + L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), + L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name), + L2NodeAddr: ctx.GlobalString(flags.L2EthNodeAddr.Name), + L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name), + Rollup: *rollupConfig, + Sequencer: enableSequencing, RPC: node.RPCConfig{ ListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name), ListenPort: ctx.GlobalInt(flags.RPCListenPort.Name), }, + P2P: p2pConfig, + P2PSigner: p2pSignerSetup, } if err := cfg.Check(); err != nil { return nil, err diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 91470552f077..cea794aca63c 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -71,6 +71,7 @@ type SystemConfig struct { CliqueSignerDerivationPath string L2OutputHDPath string BatchSubmitterHDPath string + P2PSignerHDPath string DeployerHDPath string L1InfoPredeployAddress common.Address @@ -151,7 +152,7 @@ func (sys *System) Close() { } for _, node := range sys.rollupNodes { - node.Stop() + node.Close() } for _, node := range sys.nodes { node.Close() @@ -171,7 +172,7 @@ func (cfg SystemConfig) start() (*System, error) { defer func() { if didErrAfterStart { for _, node := range sys.rollupNodes { - node.Stop() + node.Close() } for _, node := range sys.nodes { node.Close() @@ -197,6 +198,16 @@ func (cfg SystemConfig) start() (*System, error) { } batchSubmitterAddr := crypto.PubkeyToAddress(bssPrivKey.PublicKey) + p2pSignerPrivKey, err := wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: cfg.P2PSignerHDPath, + }, + }) + if err != nil { + return nil, err + } + p2pSignerAddr := crypto.PubkeyToAddress(p2pSignerPrivKey.PublicKey) + // Create the L2 Outputsubmitter Address and set it here because it needs to be derived from the accounts l2OOSubmitter, err := wallet.PrivateKey(accounts.Account{ URL: accounts.URL{ @@ -353,6 +364,7 @@ func (cfg SystemConfig) start() (*System, error) { sys.cfg.RollupConfig.Genesis = sys.RolupGenesis sys.cfg.RollupConfig.BatchSenderAddress = batchSubmitterAddr + sys.cfg.RollupConfig.P2PSequencerAddress = p2pSignerAddr sys.cfg.L2OOCfg.L2StartTime = new(big.Int).SetUint64(l2GenesisTime) // Deploy Deposit Contract @@ -457,11 +469,13 @@ func (cfg SystemConfig) start() (*System, error) { c := nodeConfig c.Rollup = sys.cfg.RollupConfig c.Rollup.DepositContractAddress = sys.DepositContractAddr - if c.Sequencer { - c.SubmitterPrivKey = bssPrivKey - } + if p, ok := p2pNodes[name]; ok { c.P2P = p + + if c.Sequencer { + c.P2PSigner = &p2p.PreparedSigner{Signer: p2p.NewLocalSigner(p2pSignerPrivKey)} + } } node, err := rollupNode.New(context.Background(), &c, cfg.Loggers[name], "") diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 7cca9076f223..09606a2b0b45 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -51,6 +51,7 @@ const ( transactorHDPath = "m/44'/60'/0'/0/1" l2OutputHDPath = "m/44'/60'/0'/0/3" bssHDPath = "m/44'/60'/0'/0/4" + p2pSignerHDPath = "m/44'/60'/0'/0/5" ) var ( @@ -77,6 +78,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { }, L2OutputHDPath: l2OutputHDPath, BatchSubmitterHDPath: bssHDPath, + P2PSignerHDPath: p2pSignerHDPath, DeployerHDPath: l2OutputHDPath, CliqueSignerDerivationPath: cliqueSignerHDPath, L1InfoPredeployAddress: derive.L1InfoPredeployAddr, From 9d7b980b27da95c721fcb3242a0b24694d537eed Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 00:51:38 +0200 Subject: [PATCH 541/585] opnode/l2,opnode/rollup/driver: process incoming unsafe L2 blocks --- opnode/l2/api.go | 8 +++++++ opnode/rollup/driver/driver.go | 3 +++ opnode/rollup/driver/state.go | 38 +++++++++++++++++++++++++++++- opnode/rollup/driver/state_test.go | 5 ++++ opnode/rollup/driver/step.go | 29 ++++++++++++++++++++++- 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 74d7b094198f..94eb4962ccdc 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -115,6 +115,14 @@ func (payload *ExecutionPayload) ID() eth.BlockID { return eth.BlockID{Hash: payload.BlockHash, Number: uint64(payload.BlockNumber)} } +func (payload *ExecutionPayload) ParentID() eth.BlockID { + n := uint64(payload.BlockNumber) + if n > 0 { + n -= 1 + } + return eth.BlockID{Hash: payload.ParentHash, Number: n} +} + type rawTransactions []Data func (s rawTransactions) Len() int { return len(s) } diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index 52d132569289..e7e90c1ae6b2 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -56,6 +56,9 @@ type outputInterface interface { // createNewBlock builds a new block based on the L2 Head, L1 Origin, and the current mempool. createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *l2.ExecutionPayload, error) + + // processBlock simply tries to add the block to the chain, reorging if necessary, and updates the forkchoice of the engine. + processBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, payload *l2.ExecutionPayload) error } type Network interface { diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index a952d891d259..949edd1180ef 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -312,6 +312,39 @@ func (s *state) handleEpoch(ctx context.Context) (bool, error) { } +func (s *state) handleUnsafeL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error { + if s.l2SafeHead.Number > uint64(payload.BlockNumber) { + s.log.Info("ignoring unsafe L2 execution payload, already have safe payload", "id", payload.ID()) + return nil + } + + if uint64(payload.Timestamp) < s.l2SafeHead.Time { + s.log.Warn("received payload rewinds L2 chain beyond current L2 safe head") + } + + if uint64(payload.Timestamp) > s.l2Head.Time+s.Config.BlockTime { + return fmt.Errorf("payload is too new: %d, l2 head is at %d", payload.Timestamp, s.l2Head.Time) + } + + if uint64(payload.BlockNumber)+128 < s.l2Head.Number { + return fmt.Errorf("unsafe payload reorgs more than 128 blocks, ignoring it: %d, head at %d", payload.BlockNumber, s.l2Head.Number) + } + + l2Ref, err := l2.PayloadToBlockRef(payload, &s.Config.Genesis) + if err != nil { + return fmt.Errorf("failed to derive L2 block ref from payload: %v", err) + } + + if err := s.output.processBlock(ctx, s.l2Head, s.l2SafeHead.ID(), s.l2Finalized, payload); err != nil { + return fmt.Errorf("failed to process unsafe L2 payload: %v", err) + } + + // We successfully processed the block, so update the safe head, while leaving the safe head etc. the same. + s.l2Head = l2Ref + + return nil +} + // loop is the event loop that responds to L1 changes and internal timers to produce L2 blocks. func (s *state) loop() { defer s.wg.Done() @@ -386,7 +419,10 @@ func (s *state) loop() { case payload := <-s.unsafeL2Payloads: s.log.Info("Optimistically processing unsafe L2 execution payload", "id", payload.ID()) - // TODO process the L2 payload + err := s.handleUnsafeL2Payload(ctx, payload) + if err != nil { + s.log.Warn("Failed to process L2 execution payload received from p2p", "err", err) + } case newL1Head := <-s.l1Heads: ctx, cancel := context.WithTimeout(ctx, 10*time.Second) diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index 1e78ff2a45a0..f7c5c4070730 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -46,6 +46,11 @@ func (id testID) ID() eth.BlockID { type outputHandlerFn func(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) +func (fn outputHandlerFn) processBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, payload *l2.ExecutionPayload) error { + // TODO: maybe mock a failed block? + return nil +} + func (fn outputHandlerFn) insertEpoch(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.L2BlockRef, l2Finalized eth.BlockID, l1Input []eth.BlockID) (eth.L2BlockRef, eth.L2BlockRef, bool, error) { return fn(ctx, l2Head, l2SafeHead, l2Finalized, l1Input) } diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index 6238b75fec58..ca9bba78029b 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -54,6 +54,27 @@ func lastDeposit(txns []l2.Data) (int, error) { return lastDeposit, nil } +func (d *outputImpl) processBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, payload *l2.ExecutionPayload) error { + d.log.Info("processing new block", "parent", payload.ParentID(), "l2Head", l2Head, "id", payload.ID()) + if err := d.l2.NewPayload(ctx, payload); err != nil { + return fmt.Errorf("failed to insert new payload: %v", err) + } + // now try to persist a reorg to the new payload + fc := l2.ForkchoiceState{ + HeadBlockHash: payload.BlockHash, + SafeBlockHash: l2SafeHead.Hash, + FinalizedBlockHash: l2Finalized.Hash, + } + res, err := d.l2.ForkchoiceUpdate(ctx, &fc, nil) + if err != nil { + return fmt.Errorf("failed to update forkchoice to point to new payload: %v", err) + } + if res.PayloadStatus.Status != l2.ExecutionValid { + return fmt.Errorf("failed to persist forkchoice update: %v", err) + } + return nil +} + func (d *outputImpl) createNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *l2.ExecutionPayload, error) { d.log.Info("creating new block", "parent", l2Head, "l1Origin", l1Origin) @@ -323,6 +344,9 @@ func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, if err != nil { return nil, fmt.Errorf("failed to create new block via forkchoice: %w", err) } + if fcRes.PayloadStatus.Status != l2.ExecutionValid { + return nil, fmt.Errorf("engine not ready, forkchoice pre-state is not valid: %s", fcRes.PayloadStatus.Status) + } id := fcRes.PayloadID if id == nil { return nil, errors.New("nil id in forkchoice result when expecting a valid ID") @@ -371,9 +395,12 @@ func (d *outputImpl) insertHeadBlock(ctx context.Context, fc l2.ForkchoiceState, fc.SafeBlockHash = payload.BlockHash } d.log.Debug("Inserted L2 head block", "number", uint64(payload.BlockNumber), "hash", payload.BlockHash, "update_safe", updateSafe) - _, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) + fcRes, err = d.l2.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { return nil, fmt.Errorf("failed to make the new L2 block canonical via forkchoice: %w", err) } + if fcRes.PayloadStatus.Status != l2.ExecutionValid { + return nil, fmt.Errorf("failed to persist forkchoice change: %s", fcRes.PayloadStatus.Status) + } return payload, nil } From 7784b4c77c4962e4c861227df5a5199c71cc10a8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 00:54:10 +0200 Subject: [PATCH 542/585] specs/rollup-node-p2p: fix toc --- specs/rollup-node-p2p.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index 88c91f145134..998b89f82414 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -52,6 +52,7 @@ and are adopted by several other blockchains, most notably the [L1 consensus lay - [Gossip Topics](#gossip-topics) - [`blocks`](#blocks) - [Block encoding](#block-encoding) + - [Block signatures](#block-signatures) - [Block validation](#block-validation) - [Block processing](#block-processing) - [Block topic scoring parameters](#block-topic-scoring-parameters) From e9f243fb07b8208c73071873cd67ec67dac68bb7 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 01:09:52 +0200 Subject: [PATCH 543/585] opnode/p2p: compress published messages --- opnode/p2p/gossip.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index 2f84eb67b709..6a2462103f9c 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -257,9 +257,11 @@ func (p *publisher) BlocksTopicPeers() []peer.ID { } func (p *publisher) PublishL2Payload(ctx context.Context, msg *l2.ExecutionPayload, signer Signer) error { - var buf bytes.Buffer + res := msgBufPool.Get().(*[]byte) + defer msgBufPool.Put(res) + buf := bytes.NewBuffer(*res) buf.Write(make([]byte, 65)) - if _, err := msg.MarshalSSZ(&buf); err != nil { + if _, err := msg.MarshalSSZ(buf); err != nil { return fmt.Errorf("failed to encoded execution payload to publish: %v", err) } data := buf.Bytes() @@ -270,7 +272,10 @@ func (p *publisher) PublishL2Payload(ctx context.Context, msg *l2.ExecutionPaylo } copy(data[:65], sig[:]) - return p.blocksTopic.Publish(ctx, data) + // compress the full message + out := snappy.Encode(nil, data) + + return p.blocksTopic.Publish(ctx, out) } func (p *publisher) Close() error { From b2ab7a6abe59b7317d4a7b29040dc821e0e317f5 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 01:10:34 +0200 Subject: [PATCH 544/585] specs/rollup-node-p2p: clarify hardfork version start --- specs/rollup-node-p2p.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index 998b89f82414..d2a7783bd17c 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -226,7 +226,7 @@ Topics have string identifiers and are communicated with messages and subscripti `/optimism/chain_id/hardfork_version/Name` - `chain_id`: replace with decimal representation of chain ID -- `hardfork_version`: replace with decimal representation of hardfork +- `hardfork_version`: replace with decimal representation of hardfork, starting at `0` - `Name`: topic application-name Note that the topic encoding depends on the topic, unlike L1, From 702169c98297454855010ef884e248f7481ea347 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 01:17:29 +0200 Subject: [PATCH 545/585] opnode/node: fix l1 head notify timeout bug --- opnode/node/node.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/opnode/node/node.go b/opnode/node/node.go index dcaa0e07b12c..36509d4bf2c0 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -272,12 +272,11 @@ func (c *OpNode) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) { c.l2Lock.Lock() defer c.l2Lock.Unlock() - ctx, cancel := context.WithTimeout(ctx, time.Second*30) - defer cancel() - // fan-out to all engine drivers for _, eng := range c.l2Engines { go func(eng *driver.Driver) { + ctx, cancel := context.WithTimeout(ctx, time.Second*10) + defer cancel() if err := eng.OnL1Head(ctx, sig); err != nil { c.log.Warn("failed to notify engine driver of L1 head change", "err", err) } From 433c40d829a2ca4c8f10fe5d11e69e96e454a97d Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 02:26:35 +0200 Subject: [PATCH 546/585] opnode: fix receive p2p payload timeout bug, fix publishing buffer missing reset --- opnode/l2/api.go | 4 ++-- opnode/node/node.go | 5 ++--- opnode/p2p/gossip.go | 18 ++++++++++++------ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index 94eb4962ccdc..d9cb4afec0a4 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -131,7 +131,7 @@ func (s rawTransactions) EncodeIndex(i int, w *bytes.Buffer) { } // CheckBlockHash recomputes the block hash and returns if the embedded block hash matches. -func (payload *ExecutionPayload) CheckBlockHash() bool { +func (payload *ExecutionPayload) CheckBlockHash() (actual common.Hash, ok bool) { hasher := trie.NewStackTrie(nil) txHash := types.DeriveSha(rawTransactions(payload.Transactions), hasher) @@ -154,7 +154,7 @@ func (payload *ExecutionPayload) CheckBlockHash() bool { BaseFee: payload.BaseFeePerGas.ToBig(), } blockHash := header.Hash() - return blockHash == payload.BlockHash + return blockHash, blockHash == payload.BlockHash } func BlockAsPayload(bl *types.Block) (*ExecutionPayload, error) { diff --git a/opnode/node/node.go b/opnode/node/node.go index 36509d4bf2c0..3b80f020e621 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -300,12 +300,11 @@ func (c *OpNode) ReceiveL2Payload(ctx context.Context, from peer.ID, payload *l2 c.l2Lock.Lock() defer c.l2Lock.Unlock() - ctx, cancel := context.WithTimeout(ctx, time.Second*30) - defer cancel() - // fan-out to all engine drivers for _, eng := range c.l2Engines { go func(eng *driver.Driver) { + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() if err := eng.OnUnsafeL2Payload(ctx, payload); err != nil { c.log.Warn("failed to notify engine driver of new L2 payload", "err", err, "id", payload.ID()) } diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index 6a2462103f9c..007d04205ae7 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -188,8 +188,8 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx } // [REJECT] if the `block_hash` in the `payload` is not valid - if !payload.CheckBlockHash() { - log.Warn("payload has bad block hash", "bad_hash", payload.BlockHash) + if actual, ok := payload.CheckBlockHash(); !ok { + log.Warn("payload has bad block hash", "bad_hash", payload.BlockHash.String(), "actual", actual.String()) return pubsub.ValidationReject } @@ -230,7 +230,7 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx blockHeightLRU.Add(uint64(payload.BlockNumber), seen) // remember the decoded payload for later usage in topic subscriber. - message.ValidatorData = payload + message.ValidatorData = &payload return pubsub.ValidationAccept } } @@ -246,6 +246,7 @@ type GossipOut interface { } type publisher struct { + log log.Logger cfg *rollup.Config blocksTopic *pubsub.Topic } @@ -258,8 +259,12 @@ func (p *publisher) BlocksTopicPeers() []peer.ID { func (p *publisher) PublishL2Payload(ctx context.Context, msg *l2.ExecutionPayload, signer Signer) error { res := msgBufPool.Get().(*[]byte) - defer msgBufPool.Put(res) - buf := bytes.NewBuffer(*res) + buf := bytes.NewBuffer((*res)[:0]) + defer func() { + *res = buf.Bytes() + defer msgBufPool.Put(res) + }() + buf.Write(make([]byte, 65)) if _, err := msg.MarshalSSZ(buf); err != nil { return fmt.Errorf("failed to encoded execution payload to publish: %v", err) @@ -273,6 +278,7 @@ func (p *publisher) PublishL2Payload(ctx context.Context, msg *l2.ExecutionPaylo copy(data[:65], sig[:]) // compress the full message + // This also copies the data, freeing up the original buffer to go back into the pool out := snappy.Encode(nil, data) return p.blocksTopic.Publish(ctx, out) @@ -310,7 +316,7 @@ func JoinGossip(p2pCtx context.Context, ps *pubsub.PubSub, log log.Logger, cfg * subscriber := MakeSubscriber(log, BlocksHandler(gossipIn.ReceiveL2Payload)) go subscriber(p2pCtx, subscription) - return &publisher{cfg: cfg, blocksTopic: blocksTopic}, nil + return &publisher{log: log, cfg: cfg, blocksTopic: blocksTopic}, nil } type TopicSubscriber func(ctx context.Context, sub *pubsub.Subscription) From 4559e19d146126e75dc36abc006c05895f37cf4e Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 04:47:26 +0200 Subject: [PATCH 547/585] opnode: fix/improve new loggers --- opnode/l2/source.go | 2 +- opnode/node/node.go | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/opnode/l2/source.go b/opnode/l2/source.go index de1d0429dab5..76eb3e9e5dbc 100644 --- a/opnode/l2/source.go +++ b/opnode/l2/source.go @@ -143,7 +143,7 @@ func (s *Source) GetPayload(ctx context.Context, payloadId PayloadID) (*Executio var result ExecutionPayload err := s.rpc.CallContext(ctx, &result, "engine_getPayloadV1", payloadId) if err != nil { - e = log.New("payload_id", "err", err) + e = e.New("payload_id", "err", err) if rpcErr, ok := err.(rpc.Error); ok { code := ErrorCode(rpcErr.ErrorCode()) if code != UnavailablePayload { diff --git a/opnode/node/node.go b/opnode/node/node.go index 3b80f020e621..daffe11a933d 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -163,16 +163,17 @@ func (n *OpNode) AttachEngine(ctx context.Context, cfg *Config, addr string) err return err } + engLog := n.log.New("engine", addr) + // TODO: we may need to authenticate the connection with L2 // backend.SetHeader() - client, err := l2.NewSource(l2Node, &cfg.Rollup.Genesis, n.log.New("engine", addr)) + client, err := l2.NewSource(l2Node, &cfg.Rollup.Genesis, engLog) if err != nil { l2Node.Close() return err } - driverLog := log.New("engine", addr, "Sequencer", cfg.Sequencer) - engine := driver.NewDriver(cfg.Rollup, client, n.l1Source, n, driverLog, cfg.Sequencer) + engine := driver.NewDriver(cfg.Rollup, client, n.l1Source, n, engLog, cfg.Sequencer) n.l2Nodes = append(n.l2Nodes, l2Node) n.l2Engines = append(n.l2Engines, engine) @@ -216,7 +217,7 @@ func (n *OpNode) initP2P(ctx context.Context, cfg *Config) error { } var err error // All nil if disabled. - n.dv5Local, n.dv5Udp, err = cfg.P2P.Discovery(log.New("p2p", "discv5")) + n.dv5Local, n.dv5Udp, err = cfg.P2P.Discovery(n.log.New("p2p", "discv5")) if err != nil { return fmt.Errorf("failed to start discv5: %v", err) } @@ -226,16 +227,18 @@ func (n *OpNode) initP2P(ctx context.Context, cfg *Config) error { if err != nil { return fmt.Errorf("failed to start p2p host: %v", err) } + if n.host != nil { n.gs, err = p2p.NewGossipSub(n.resourcesCtx, n.host, &cfg.Rollup) if err != nil { return fmt.Errorf("failed to start gossipsub router: %v", err) } - n.gsOut, err = p2p.JoinGossip(n.resourcesCtx, n.gs, n.log, &cfg.Rollup, n) + n.gsOut, err = p2p.JoinGossip(n.resourcesCtx, n.host.ID(), n.gs, n.log, &cfg.Rollup, n) if err != nil { return fmt.Errorf("failed to join blocks gossip topic: %v", err) } + n.log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().Pretty()) } return nil } @@ -290,6 +293,7 @@ func (c *OpNode) PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayl if c.p2pSigner == nil { return fmt.Errorf("node has no p2p signer, payload %s cannot be published", payload.ID()) } + c.log.Info("Publishing signed execution payload on p2p", "id", payload.ID()) return c.gsOut.PublishL2Payload(ctx, payload, c.p2pSigner) } // if p2p is not enabled then we just don't publish the payload @@ -300,6 +304,13 @@ func (c *OpNode) ReceiveL2Payload(ctx context.Context, from peer.ID, payload *l2 c.l2Lock.Lock() defer c.l2Lock.Unlock() + // ignore if it's from ourselves + if from == c.host.ID() { + return nil + } + + c.log.Info("Received signed execution payload from p2p", "id", payload.ID(), "peer", from) + // fan-out to all engine drivers for _, eng := range c.l2Engines { go func(eng *driver.Driver) { From a664cc2a09da09b2ac155a3519db4b189f9afb71 Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 04:49:03 +0200 Subject: [PATCH 548/585] opnode: fix p2p block distribution --- opnode/p2p/gossip.go | 62 +++++++++++++++++++++++++++++++---- opnode/rollup/driver/state.go | 25 +++++++------- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index 007d04205ae7..d1ac6c6370ef 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -127,11 +127,37 @@ func NewGossipSub(p2pCtx context.Context, h host.Host, cfg *rollup.Config) (*pub pubsub.WithValidateThrottle(globalValidateThrottle), pubsub.WithPeerExchange(false), pubsub.WithBlacklist(denyList), - pubsub.WithGossipSubParams(BuildGlobalGossipParams(cfg))) - // TODO: pubsub.WithDiscovery(discover) to search for peers instead of randomly grabbing from open connections + pubsub.WithGossipSubParams(BuildGlobalGossipParams(cfg)), + ) // TODO: pubsub.WithPeerScoreInspect(inspect, InspectInterval) to update peerstore scores with gossip scores } +func validationResultString(v pubsub.ValidationResult) string { + switch v { + case pubsub.ValidationAccept: + return "ACCEPT" + case pubsub.ValidationIgnore: + return "IGNORE" + case pubsub.ValidationReject: + return "REJECT" + default: + return fmt.Sprintf("UNKNOWN_%d", v) + } +} + +func logValidationResult(self peer.ID, msg string, log log.Logger, fn pubsub.ValidatorEx) pubsub.ValidatorEx { + return func(ctx context.Context, id peer.ID, message *pubsub.Message) pubsub.ValidationResult { + res := fn(ctx, id, message) + var src interface{} + src = id + if id == self { + src = "self" + } + log.Debug(msg, "result", validationResultString(res), "from", src) + return res + } +} + func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx { // Seen block hashes per block height @@ -257,7 +283,7 @@ func (p *publisher) BlocksTopicPeers() []peer.ID { return p.blocksTopic.ListPeers() } -func (p *publisher) PublishL2Payload(ctx context.Context, msg *l2.ExecutionPayload, signer Signer) error { +func (p *publisher) PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload, signer Signer) error { res := msgBufPool.Get().(*[]byte) buf := bytes.NewBuffer((*res)[:0]) defer func() { @@ -266,7 +292,7 @@ func (p *publisher) PublishL2Payload(ctx context.Context, msg *l2.ExecutionPaylo }() buf.Write(make([]byte, 65)) - if _, err := msg.MarshalSSZ(buf); err != nil { + if _, err := payload.MarshalSSZ(buf); err != nil { return fmt.Errorf("failed to encoded execution payload to publish: %v", err) } data := buf.Bytes() @@ -288,8 +314,8 @@ func (p *publisher) Close() error { return p.blocksTopic.Close() } -func JoinGossip(p2pCtx context.Context, ps *pubsub.PubSub, log log.Logger, cfg *rollup.Config, gossipIn GossipIn) (GossipOut, error) { - val := BuildBlocksValidator(log, cfg) +func JoinGossip(p2pCtx context.Context, self peer.ID, ps *pubsub.PubSub, log log.Logger, cfg *rollup.Config, gossipIn GossipIn) (GossipOut, error) { + val := logValidationResult(self, "validated block", log, BuildBlocksValidator(log, cfg)) blocksTopicName := blocksTopicV1(cfg) err := ps.RegisterTopicValidator(blocksTopicName, val, @@ -302,6 +328,12 @@ func JoinGossip(p2pCtx context.Context, ps *pubsub.PubSub, log log.Logger, cfg * if err != nil { return nil, fmt.Errorf("failed to join blocks gossip topic: %v", err) } + blocksTopicEvents, err := blocksTopic.EventHandler() + if err != nil { + return nil, fmt.Errorf("failed to create blocks gossip topic handler: %v", err) + } + go LogTopicEvents(p2pCtx, log.New("topic", "blocks"), blocksTopicEvents) + // TODO: block topic scoring parameters // See prysm: https://github.com/prysmaticlabs/prysm/blob/develop/beacon-chain/p2p/gossip_scoring_params.go // And research from lighthouse: https://gist.github.com/blacktemplar/5c1862cb3f0e32a1a7fb0b25e79e6e2c @@ -351,3 +383,21 @@ func MakeSubscriber(log log.Logger, msgHandler MessageHandler) TopicSubscriber { } } } + +func LogTopicEvents(ctx context.Context, log log.Logger, evHandler *pubsub.TopicEventHandler) { + defer evHandler.Cancel() + for { + ev, err := evHandler.NextPeerEvent(ctx) + if err != nil { + return // ctx closed + } + switch ev.Type { + case pubsub.PeerJoin: + log.Debug("peer joined topic", "peer", ev.Peer) + case pubsub.PeerLeave: + log.Debug("peer left topic", "peer", ev.Peer) + default: + log.Warn("unrecognized topic event", "ev", ev) + } + } +} diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 949edd1180ef..a592cd71962f 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -41,17 +41,18 @@ type state struct { // NewState creates a new driver state. State changes take effect though the given output. // Optionally a network can be provided to publish things to other nodes than the engine of the driver. -func NewState(log log.Logger, config rollup.Config, l1 L1Chain, l2 L2Chain, output outputInterface, network Network, sequencer bool) *state { +func NewState(log log.Logger, config rollup.Config, l1Chain L1Chain, l2Chain L2Chain, output outputInterface, network Network, sequencer bool) *state { return &state{ - Config: config, - done: make(chan struct{}), - log: log, - l1: l1, - l2: l2, - output: output, - network: network, - sequencer: sequencer, - l1Heads: make(chan eth.L1BlockRef, 10), + Config: config, + done: make(chan struct{}), + log: log, + l1: l1Chain, + l2: l2Chain, + output: output, + network: network, + sequencer: sequencer, + l1Heads: make(chan eth.L1BlockRef, 10), + unsafeL2Payloads: make(chan *l2.ExecutionPayload, 10), } } @@ -233,8 +234,8 @@ func (s *state) createNewL2Block(ctx context.Context) error { // Rollup is configured to not start producing blocks until a specific L1 block has been // reached. Don't produce any blocks until we're at that genesis block. - if l1Origin.Number <= s.Config.Genesis.L1.Number { - s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis") + if l1Origin.Number < s.Config.Genesis.L1.Number { + s.log.Info("Skipping block production because the next L1 Origin is behind the L1 genesis", "next", l1Origin.ID(), "genesis", s.Config.Genesis.L1) return nil } From bf06074f99e4efcfea56c8d24c19414080a89c4c Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 04:51:09 +0200 Subject: [PATCH 549/585] opnode/test: connect peers only after starting p2p application-layer protocols --- opnode/test/setup.go | 31 +++++++++++++++++++-------- opnode/test/system_test.go | 43 ++++++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/opnode/test/setup.go b/opnode/test/setup.go index cea794aca63c..6b66e03fa2a1 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -445,10 +445,7 @@ func (cfg SystemConfig) start() (*System, error) { return nil, fmt.Errorf("failed to setup mocknet peer %s", k) } for _, v := range vs { - unconnected := strings.HasPrefix(v, "~") - if unconnected { - v = v[1:] - } + v = strings.TrimPrefix(v, "~") peerB, err := initHostMaybe(v) if err != nil { return nil, fmt.Errorf("failed to setup mocknet peer %s (peer of %s)", v, k) @@ -456,11 +453,7 @@ func (cfg SystemConfig) start() (*System, error) { if _, err := sys.Mocknet.LinkPeers(peerA.HostP2P.ID(), peerB.HostP2P.ID()); err != nil { return nil, fmt.Errorf("failed to setup mocknet link between %s and %s", k, v) } - if !unconnected { - if _, err := sys.Mocknet.ConnectPeers(peerA.HostP2P.ID(), peerB.HostP2P.ID()); err != nil { - return nil, fmt.Errorf("failed to setup mocknet connection between %s and %s", k, v) - } - } + // connect the peers after starting the full rollup node } } } @@ -489,7 +482,27 @@ func (cfg SystemConfig) start() (*System, error) { return nil, err } sys.rollupNodes[name] = node + } + if cfg.P2PTopology != nil { + // We only set up the connections after starting the actual nodes, + // so GossipSub and other p2p protocols can be started before the connections go live. + // This way protocol negotiation happens correctly. + for k, vs := range cfg.P2PTopology { + peerA := p2pNodes[k] + for _, v := range vs { + unconnected := strings.HasPrefix(v, "~") + if unconnected { + v = v[1:] + } + if !unconnected { + peerB := p2pNodes[v] + if _, err := sys.Mocknet.ConnectPeers(peerA.HostP2P.ID(), peerB.HostP2P.ID()); err != nil { + return nil, fmt.Errorf("failed to setup mocknet connection between %s and %s", k, v) + } + } + } + } } rollupEndpoint := fmt.Sprintf( diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 09606a2b0b45..8d9029757fdf 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -108,8 +108,8 @@ func defaultSystemConfig(t *testing.T) SystemConfig { }, }, Loggers: map[string]log.Logger{ - "verifier": testlog.Logger(t, log.LvlError), - "sequencer": testlog.Logger(t, log.LvlError), + "verifier": testlog.Logger(t, log.LvlError).New("role", "verifier"), + "sequencer": testlog.Logger(t, log.LvlError).New("role", "sequencer"), }, RollupConfig: rollup.Config{ BlockTime: 1, @@ -472,8 +472,10 @@ func TestSystemMockP2P(t *testing.T) { } cfg := defaultSystemConfig(t) - // slow down L1 blocks so we can see the L2 blocks arrive before the L1 blocks do. + // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. + // Keep the seq window small so the L2 chain is started quick cfg.L1BlockTime = 10 + // connect the nodes cfg.P2PTopology = map[string][]string{ "verifier": []string{"sequencer"}, @@ -485,7 +487,40 @@ func TestSystemMockP2P(t *testing.T) { t.Log("successfully set up network") - // TODO: await L2 blocks going from sequencer to verifier, ahead of L1 + l2Seq := sys.Clients["sequencer"] + l2Verif := sys.Clients["verifier"] + + // Transactor Account + ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: transactorHDPath, + }, + }) + require.Nil(t, err) + + // Submit TX to L2 sequencer node + toAddr := common.Address{0xff, 0xff} + tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainID, + Nonce: 0, + To: &toAddr, + Value: big.NewInt(1_000_000_000), + GasTipCap: big.NewInt(10), + GasFeeCap: big.NewInt(200), + Gas: 21000, + }) + err = l2Seq.SendTransaction(context.Background(), tx) + require.Nil(t, err, "Sending L2 tx to sequencer") + + // Wait for tx to be mined on the L2 sequencer chain + receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.RollupConfig.BlockTime)*time.Second) + require.Nil(t, err, "Waiting for L2 tx on sequencer") + + // Wait until the block it was first included in shows up in the safe chain on the verifier + receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.RollupConfig.BlockTime)*time.Second) + require.Nil(t, err, "Waiting for L2 tx on verifier") + + require.Equal(t, receiptSeq, receiptVerif) } func TestL1InfoContract(t *testing.T) { From 832eab901fa0c451e94b7db0fb2ea07b1e4017ac Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 05:46:57 +0200 Subject: [PATCH 550/585] ops,opnode/p2p: fix opnode start up in devnet --- opnode/p2p/config.go | 14 +++++++++++--- ops/bss-key.txt | 1 - ops/docker-compose.yml | 28 +++++++++++++++++----------- ops/p2p-node-key.txt | 1 + ops/p2p-sequencer-key.txt | 1 + ops/rollup.json | 2 +- 6 files changed, 31 insertions(+), 16 deletions(-) delete mode 100644 ops/bss-key.txt create mode 100644 ops/p2p-node-key.txt create mode 100644 ops/p2p-sequencer-key.txt diff --git a/opnode/p2p/config.go b/opnode/p2p/config.go index d44d5cb44cfc..90cfd4e2ba5a 100644 --- a/opnode/p2p/config.go +++ b/opnode/p2p/config.go @@ -207,7 +207,11 @@ func (conf *Config) loadDiscoveryOpts(ctx *cli.Context) error { records := strings.Split(ctx.GlobalString(flags.Bootnodes.Name), ",") for i, recordB64 := range records { - nodeRecord, err := enode.Parse(enode.ValidSchemes, strings.TrimSpace(recordB64)) + recordB64 = strings.TrimSpace(recordB64) + if recordB64 == "" { // ignore empty records + continue + } + nodeRecord, err := enode.Parse(enode.ValidSchemes, recordB64) if err != nil { return fmt.Errorf("bootnode record %d (of %d) is invalid: %q err: %v", i, len(records), recordB64, err) } @@ -253,6 +257,10 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { addrs := strings.Split(ctx.GlobalString(flags.StaticPeers.Name), ",") for i, addr := range addrs { + addr = strings.TrimSpace(addr) + if addr == "" { + continue // skip empty multi addrs + } a, err := multiaddr.NewMultiaddr(addr) if err != nil { return fmt.Errorf("failed to parse multi addr of static peer %d (out of %d): %q err: %v", i, len(addrs), addr, err) @@ -278,7 +286,7 @@ func (conf *Config) loadLibp2pOpts(ctx *cli.Context) error { conf.HostMux = append(conf.HostMux, mc) } - secArr := strings.Split(ctx.GlobalString(flags.HostMux.Name), ",") + secArr := strings.Split(ctx.GlobalString(flags.HostSecurity.Name), ",") for _, v := range secArr { v = strings.ToLower(strings.TrimSpace(v)) var sc lconf.MsSecC @@ -362,7 +370,7 @@ func loadNetworkPrivKey(ctx *cli.Context) (*ecdsa.PrivateKey, error) { if err != nil { return nil, fmt.Errorf("failed to read priv key file: %v", err) } - return parsePriv(string(data)) + return parsePriv(strings.TrimSpace(string(data))) } } diff --git a/ops/bss-key.txt b/ops/bss-key.txt deleted file mode 100644 index 0994f47ba01e..000000000000 --- a/ops/bss-key.txt +++ /dev/null @@ -1 +0,0 @@ -bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 \ No newline at end of file diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index ed986ec0979d..ba8069bae979 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -36,20 +36,26 @@ services: build: context: ../ dockerfile: ./ops/Dockerfile.opnode - command: - - op - - --l1=ws://l1:8546 - - --l2=ws://l2:8546 - - --sequencing.enabled - - --rollup.config=/rollup.json - - --batchsubmitter.key=/config/bss-key.txt - - --l2.eth=http://l2:8545 - - --rpc.addr=0.0.0.0 - - --rpc.port=8545 + command: > + op + --l1=ws://l1:8546 + --l2=ws://l2:8546 + --sequencing.enabled + --p2p.sequencer.key=/config/p2p-sequencer-key.txt + --rollup.config=/rollup.json + --l2.eth=http://l2:8545 + --rpc.addr=0.0.0.0 + --rpc.port=8545 + --p2p.listen.ip=0.0.0.0 + --p2p.listen.tcp=9003 + --p2p.listen.udp=9003 + --p2p.priv.path=/config/p2p-node-key.txt ports: - "7545:8545" + - "9003:9003" volumes: - - ${PWD}/bss-key.txt:/config/bss-key.txt + - ${PWD}/p2p-sequencer-key.txt:/config/p2p-sequencer-key.txt + - ${PWD}/p2p-node-key.txt:/config/p2p-node-key.txt - ${PWD}/../.devnet/rollup.json:/rollup.json l2os: diff --git a/ops/p2p-node-key.txt b/ops/p2p-node-key.txt new file mode 100644 index 000000000000..890c029bcda7 --- /dev/null +++ b/ops/p2p-node-key.txt @@ -0,0 +1 @@ +dae4671006c60a3619556ace98eca6f6e092948d05b13070a27ac492a4fba419 diff --git a/ops/p2p-sequencer-key.txt b/ops/p2p-sequencer-key.txt new file mode 100644 index 000000000000..12347b2e0b34 --- /dev/null +++ b/ops/p2p-sequencer-key.txt @@ -0,0 +1 @@ +8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba diff --git a/ops/rollup.json b/ops/rollup.json index 1ec6c9ddc621..da0f7d0fbb8c 100644 --- a/ops/rollup.json +++ b/ops/rollup.json @@ -21,7 +21,7 @@ "l2_chain_id": 901, - "p2p_sequencer_address": "TODOTODO", + "p2p_sequencer_address": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "fee_recipient_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", From 83a45ea392f138ac23091cf256d5e4859823c4bc Mon Sep 17 00:00:00 2001 From: protolambda Date: Mon, 9 May 2022 05:47:32 +0200 Subject: [PATCH 551/585] opnode/l2: use common.Big0 instead of big.NewInt(0), thx mark --- opnode/l2/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/l2/api.go b/opnode/l2/api.go index d9cb4afec0a4..d2fb9c389e21 100644 --- a/opnode/l2/api.go +++ b/opnode/l2/api.go @@ -143,7 +143,7 @@ func (payload *ExecutionPayload) CheckBlockHash() (actual common.Hash, ok bool) TxHash: txHash, ReceiptHash: common.Hash(payload.ReceiptsRoot), Bloom: types.Bloom(payload.LogsBloom), - Difficulty: big.NewInt(0), // zeroed, proof-of-work legacy + Difficulty: common.Big0, // zeroed, proof-of-work legacy Number: big.NewInt(int64(payload.BlockNumber)), GasLimit: uint64(payload.GasLimit), GasUsed: uint64(payload.GasUsed), From 5189b9a26831f0a3e51587e3ddb9aba65195fdaf Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Mon, 9 May 2022 08:25:28 -0700 Subject: [PATCH 552/585] opnode: Add debug tracer to geth in e2e test (#418) --- opnode/test/geth.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opnode/test/geth.go b/opnode/test/geth.go index cd5546be6194..31e4c1a67cf8 100644 --- a/opnode/test/geth.go +++ b/opnode/test/geth.go @@ -19,6 +19,7 @@ import ( "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/node" @@ -166,6 +167,8 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri } + n.RegisterAPIs(tracers.APIs(backend.APIBackend)) + // Enable catalyst if l2 if l2 { if err := catalyst.Register(n, backend); err != nil { From c3f5ec8e8c297f3ccb11efabf69e602a996e98e0 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Mon, 9 May 2022 12:56:01 -0400 Subject: [PATCH 553/585] Update reference geth entrypoint with variable parameters --- ops/entrypoint.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ops/entrypoint.sh b/ops/entrypoint.sh index 17cc66fdc82d..29b4b65ddb8e 100644 --- a/ops/entrypoint.sh +++ b/ops/entrypoint.sh @@ -5,9 +5,12 @@ VERBOSITY=${GETH_VERBOSITY:-3} GETH_DATA_DIR=/db GETH_CHAINDATA_DIR="$GETH_DATA_DIR/geth/chaindata" GETH_KEYSTORE_DIR="$GETH_DATA_DIR/keystore" -CHAIN_ID=$(cat /genesis.json | jq -r .config.chainId) +GENESIS_FILE_PATH="${GENESIS_FILE_PATH:-/genesis.json}" +CHAIN_ID=$(cat "$GENESIS_FILE_PATH" | jq -r .config.chainId) BLOCK_SIGNER_PRIVATE_KEY="3e4bde571b86929bf08e2aaad9a6a1882664cd5e65b96fff7d03e1c4e6dfa15c" BLOCK_SIGNER_ADDRESS="0xca062b0fd91172d89bcd4bb084ac4e21972cc467" +RPC_PORT="${RPC_PORT:-8545}" +WS_PORT="${WS_PORT:-8546}" if [ ! -d "$GETH_KEYSTORE_DIR" ]; then echo "$GETH_KEYSTORE_DIR missing, running account import" @@ -26,7 +29,7 @@ if [ ! -d "$GETH_CHAINDATA_DIR" ]; then echo "Initializing genesis." geth --verbosity="$VERBOSITY" init \ --datadir="$GETH_DATA_DIR" \ - "/genesis.json" + "$GENESIS_FILE_PATH" else echo "$GETH_CHAINDATA_DIR exists." fi @@ -41,11 +44,11 @@ exec geth \ --http.corsdomain="*" \ --http.vhosts="*" \ --http.addr=0.0.0.0 \ - --http.port=8545 \ + --http.port="$RPC_PORT" \ --http.api=web3,debug,eth,txpool,net,engine \ --ws \ --ws.addr=0.0.0.0 \ - --ws.port=8546 \ + --ws.port="$WS_PORT" \ --ws.origins="*" \ --ws.api=debug,eth,txpool,net,engine \ --syncmode=full \ From 36536fd3f77a44bd1856997636ff8cf774c31bc4 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 May 2022 01:34:39 +0200 Subject: [PATCH 554/585] opnode: fix imports and code newlines style --- opnode/node/api.go | 3 +-- opnode/node/node.go | 6 ------ opnode/rollup/driver/state_test.go | 5 ++--- opnode/service.go | 3 +-- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/opnode/node/api.go b/opnode/node/api.go index c2229f8c0a86..3c9658d77854 100644 --- a/opnode/node/api.go +++ b/opnode/node/api.go @@ -8,11 +8,10 @@ import ( "math/big" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" - - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/opnode/node/node.go b/opnode/node/node.go index daffe11a933d..4688227f3db9 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -99,27 +99,21 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* } func (n *OpNode) init(ctx context.Context, cfg *Config) error { - if err := n.initL1(ctx, cfg); err != nil { return err } - if err := n.initL2(ctx, cfg); err != nil { return err } - if err := n.initRPCServer(ctx, cfg); err != nil { return err } - if err := n.initP2PSigner(ctx, cfg); err != nil { return err } - if err := n.initP2P(ctx, cfg); err != nil { return err } - return nil } diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index f7c5c4070730..f7527d242621 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -7,16 +7,15 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/stretchr/testify/require" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testutils" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var _ L1Chain = (*testutils.FakeChainSource)(nil) diff --git a/opnode/service.go b/opnode/service.go index 5d272f5e1f90..9459d36e7542 100644 --- a/opnode/service.go +++ b/opnode/service.go @@ -5,10 +5,9 @@ import ( "fmt" "os" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" - "github.com/ethereum-optimism/optimistic-specs/opnode/flags" "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/urfave/cli" ) From 0fca7248b28f90350bfe99d45ab3ae3e4fbc72ed Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 May 2022 16:59:25 +0200 Subject: [PATCH 555/585] opnode,specs: gossip blocks validation seen cache fixes --- opnode/p2p/gossip.go | 48 ++++++++++++++++++++++++++++++---------- specs/rollup-node-p2p.md | 19 +++++++++++----- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index d1ac6c6370ef..0f3ebc75c839 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -158,10 +158,34 @@ func logValidationResult(self peer.ID, msg string, log log.Logger, fn pubsub.Val } } +type seenBlocks struct { + sync.Mutex + blockHashes []common.Hash +} + +// hasSeen checks if the hash has been marked as seen, and how many have been seen. +func (sb *seenBlocks) hasSeen(h common.Hash) (count int, hasSeen bool) { + sb.Lock() + defer sb.Unlock() + for _, prev := range sb.blockHashes { + if prev == h { + return len(sb.blockHashes), true + } + } + return len(sb.blockHashes), false +} + +// markSeen marks the block hash as seen +func (sb *seenBlocks) markSeen(h common.Hash) { + sb.Lock() + defer sb.Unlock() + sb.blockHashes = append(sb.blockHashes, h) +} + func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx { // Seen block hashes per block height - // uint64 -> []common.Hash + // uint64 -> *seenBlocks blockHeightLRU, err := lru.New(100) if err != nil { panic(fmt.Errorf("failed to set up block height LRU cache: %v", err)) @@ -219,21 +243,20 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx return pubsub.ValidationReject } - // [REJECT] if more than 5 blocks have been seen with the same block height seen, ok := blockHeightLRU.Get(uint64(payload.BlockNumber)) if !ok { - seen = []common.Hash{} + seen = new(seenBlocks) + blockHeightLRU.Add(uint64(payload.BlockNumber), seen) } - if len(seen.([]common.Hash)) > 5 { + + if count, hasSeen := seen.(*seenBlocks).hasSeen(payload.BlockHash); count > 5 { + // [REJECT] if more than 5 blocks have been seen with the same block height log.Warn("seen too many different blocks at same height", "height", payload.BlockNumber) return pubsub.ValidationReject - } - for _, prev := range seen.([]common.Hash) { + } else if hasSeen { // [IGNORE] if the block has already been seen - if prev == payload.BlockHash { - log.Warn("validated already seen message again") - return pubsub.ValidationIgnore - } + log.Warn("validated already seen message again") + return pubsub.ValidationIgnore } // [REJECT] if the signature by the sequencer is not valid @@ -252,8 +275,9 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx return pubsub.ValidationReject } - seen = append(seen.([]common.Hash), payload.BlockHash) - blockHeightLRU.Add(uint64(payload.BlockNumber), seen) + // mark it as seen. (note: with concurrent validation more than 5 blocks may be marked as seen still, + // but validator concurrency is limited anyway) + seen.(*seenBlocks).markSeen(payload.BlockHash) // remember the decoded payload for later usage in topic subscriber. message.ValidatorData = &payload diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index d2a7783bd17c..b0d9aa2f5f9d 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -49,6 +49,7 @@ and are adopted by several other blockchains, most notably the [L1 consensus lay - [Message ID computation](#message-id-computation) - [Heartbeat and parameters](#heartbeat-and-parameters) - [Topic configuration](#topic-configuration) + - [Topic validation](#topic-validation) - [Gossip Topics](#gossip-topics) - [`blocks`](#blocks) - [Block encoding](#block-encoding) @@ -232,6 +233,16 @@ Topics have string identifiers and are communicated with messages and subscripti Note that the topic encoding depends on the topic, unlike L1, since there are less topics, and all are snappy-compressed. +#### Topic validation + +To ensure only valid messages are relayed, and malicious peers get scored based on application behavior, +an [extended validator][extended-validator] checks the message before it is relayed or processed. +The extended validator emits one of the following validation signals: + +- `ACCEPT` valid, relayed to other peers and passed to local topic subscriber +- `IGNORE` scored like inactivity, message is dropped and not processed +- `REJECT` score penalties, message is dropped + ## Gossip Topics ### `blocks` @@ -261,10 +272,7 @@ The `secp256k1` signature must have `y_parity = 1 or 0`, the `chain_id` is alrea #### Block validation -To ensure malicious peers get scored based on application behavior the validation signals -`ACCEPT` (valid), `IGNORE` (like inactivity) or `REJECT` (score penalties). - -In order of operation: +An [extended-validator] checks the incoming messages as follows, in order of operation: - `[REJECT]` if the compression is not valid - `[REJECT]` if the block encoding is not valid @@ -273,7 +281,7 @@ In order of operation: - `[REJECT]` if the `payload.timestamp` is more than 5 seconds into the future - `[REJECT]` if the `block_hash` in the `payload` is not valid - `[REJECT]` if more than 5 different blocks have been seen with the same block height - - `[IGNORE]` if the block has already been seen +- `[IGNORE]` if the block has already been seen - `[REJECT]` if the signature by the sequencer is not valid - Mark the block as seen for the given block height @@ -312,3 +320,4 @@ TODO: GossipSub per-topic scoring to fine-tune incentives for ideal propagation [snappy]: https://github.com/google/snappy [l1-message-id]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#topics-and-messages [gossip-parameters]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.0.md#parameters +[extended-validator]: https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#extended-validators From a069290a999cea7290ce35aad32d3fd200cffcd6 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 May 2022 17:05:35 +0200 Subject: [PATCH 556/585] opnode/rollup/driver: no heuristics in driver, rely more on engine to handle reorgs --- opnode/rollup/driver/state.go | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index a592cd71962f..065b9c7bc9c7 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -319,17 +319,9 @@ func (s *state) handleUnsafeL2Payload(ctx context.Context, payload *l2.Execution return nil } - if uint64(payload.Timestamp) < s.l2SafeHead.Time { - s.log.Warn("received payload rewinds L2 chain beyond current L2 safe head") - } - - if uint64(payload.Timestamp) > s.l2Head.Time+s.Config.BlockTime { - return fmt.Errorf("payload is too new: %d, l2 head is at %d", payload.Timestamp, s.l2Head.Time) - } - - if uint64(payload.BlockNumber)+128 < s.l2Head.Number { - return fmt.Errorf("unsafe payload reorgs more than 128 blocks, ignoring it: %d, head at %d", payload.BlockNumber, s.l2Head.Number) - } + // Not that the payload may cause reorgs. The l2SafeHead may get out of sync because of this. + // The engine should never reorg past the finalized block hash however. + // The engine may attempt syncing via p2p if there is a larger gap in the L2 chain. l2Ref, err := l2.PayloadToBlockRef(payload, &s.Config.Genesis) if err != nil { From 4b5301e8935a76df33e3adbc72ea46dc58bd62fc Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 May 2022 18:11:38 +0200 Subject: [PATCH 557/585] opnode: tracer to watch node events during testing --- opnode/node/comms.go | 27 +++++++++++ opnode/node/config.go | 3 ++ opnode/node/node.go | 99 +++++++++++++++++++++++--------------- opnode/p2p/gossip.go | 4 +- opnode/test/setup.go | 4 +- opnode/test/system_test.go | 24 +++++++-- opnode/test/tracer.go | 36 ++++++++++++++ 7 files changed, 150 insertions(+), 47 deletions(-) create mode 100644 opnode/node/comms.go create mode 100644 opnode/test/tracer.go diff --git a/opnode/node/comms.go b/opnode/node/comms.go new file mode 100644 index 000000000000..dbd9995500d6 --- /dev/null +++ b/opnode/node/comms.go @@ -0,0 +1,27 @@ +package node + +import ( + "context" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/libp2p/go-libp2p-core/peer" +) + +// Tracer configures the OpNode to share events +type Tracer interface { + OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) + OnUnsafeL2Payload(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) + OnPublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) +} + +type noOpTracer struct{} + +func (n noOpTracer) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) {} + +func (n noOpTracer) OnUnsafeL2Payload(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) { +} + +func (n noOpTracer) OnPublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) {} + +var _ Tracer = (*noOpTracer)(nil) diff --git a/opnode/node/config.go b/opnode/node/config.go index 0e7be0041e26..f541284d1d98 100644 --- a/opnode/node/config.go +++ b/opnode/node/config.go @@ -31,6 +31,9 @@ type Config struct { RPC RPCConfig P2P p2p.SetupP2P + + // Optional + Tracer Tracer } type RPCConfig struct { diff --git a/opnode/node/node.go b/opnode/node/node.go index 4688227f3db9..489038a31f8e 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -45,6 +45,7 @@ type OpNode struct { gs *pubsub.PubSub // p2p gossip router (optional, may be nil) gsOut p2p.GossipOut // p2p gossip application interface for publishing (optional, may be nil) p2pSigner p2p.Signer // p2p gogssip application messages will be signed with this signer + tracer Tracer // tracer to get events for testing/debugging // some resources cannot be stopped directly, like the p2p gossipsub router (not our design), // and depend on this ctx to be closed. @@ -99,6 +100,9 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* } func (n *OpNode) init(ctx context.Context, cfg *Config) error { + if err := n.initTracer(ctx, cfg); err != nil { + return err + } if err := n.initL1(ctx, cfg); err != nil { return err } @@ -117,6 +121,15 @@ func (n *OpNode) init(ctx context.Context, cfg *Config) error { return nil } +func (n *OpNode) initTracer(ctx context.Context, cfg *Config) error { + if cfg.Tracer != nil { + n.tracer = cfg.Tracer + } else { + n.tracer = new(noOpTracer) + } + return nil +} + func (n *OpNode) initL1(ctx context.Context, cfg *Config) error { l1Node, err := dialRPCClientWithBackoff(ctx, n.log, cfg.L1NodeAddr) if err != nil { @@ -248,16 +261,16 @@ func (n *OpNode) initP2PSigner(ctx context.Context, cfg *Config) error { return err } -func (c *OpNode) Start(ctx context.Context) error { - c.log.Info("Starting execution engine driver(s)") - for _, eng := range c.l2Engines { +func (n *OpNode) Start(ctx context.Context) error { + n.log.Info("Starting execution engine driver(s)") + for _, eng := range n.l2Engines { // Request initial head update, default to genesis otherwise reqCtx, reqCancel := context.WithTimeout(ctx, time.Second*10) // start driving engine: sync blocks by deriving them from L1 and driving them into the engine err := eng.Start(reqCtx) reqCancel() if err != nil { - c.log.Error("Could not start a rollup node", "err", err) + n.log.Error("Could not start a rollup node", "err", err) return err } } @@ -265,53 +278,59 @@ func (c *OpNode) Start(ctx context.Context) error { return nil } -func (c *OpNode) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) { - c.l2Lock.Lock() - defer c.l2Lock.Unlock() +func (n *OpNode) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) { + n.l2Lock.Lock() + defer n.l2Lock.Unlock() + + n.tracer.OnNewL1Head(ctx, sig) // fan-out to all engine drivers - for _, eng := range c.l2Engines { + for _, eng := range n.l2Engines { go func(eng *driver.Driver) { ctx, cancel := context.WithTimeout(ctx, time.Second*10) defer cancel() if err := eng.OnL1Head(ctx, sig); err != nil { - c.log.Warn("failed to notify engine driver of L1 head change", "err", err) + n.log.Warn("failed to notify engine driver of L1 head change", "err", err) } }(eng) } } -func (c *OpNode) PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error { +func (n *OpNode) PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error { + n.tracer.OnPublishL2Payload(ctx, payload) + // publish to p2p, if we are running p2p at all - if c.gsOut != nil { - if c.p2pSigner == nil { + if n.gsOut != nil { + if n.p2pSigner == nil { return fmt.Errorf("node has no p2p signer, payload %s cannot be published", payload.ID()) } - c.log.Info("Publishing signed execution payload on p2p", "id", payload.ID()) - return c.gsOut.PublishL2Payload(ctx, payload, c.p2pSigner) + n.log.Info("Publishing signed execution payload on p2p", "id", payload.ID()) + return n.gsOut.PublishL2Payload(ctx, payload, n.p2pSigner) } // if p2p is not enabled then we just don't publish the payload return nil } -func (c *OpNode) ReceiveL2Payload(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) error { - c.l2Lock.Lock() - defer c.l2Lock.Unlock() +func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) error { + n.l2Lock.Lock() + defer n.l2Lock.Unlock() // ignore if it's from ourselves - if from == c.host.ID() { + if from == n.host.ID() { return nil } - c.log.Info("Received signed execution payload from p2p", "id", payload.ID(), "peer", from) + n.tracer.OnUnsafeL2Payload(ctx, from, payload) + + n.log.Info("Received signed execution payload from p2p", "id", payload.ID(), "peer", from) // fan-out to all engine drivers - for _, eng := range c.l2Engines { + for _, eng := range n.l2Engines { go func(eng *driver.Driver) { ctx, cancel := context.WithTimeout(ctx, time.Second*30) defer cancel() if err := eng.OnUnsafeL2Payload(ctx, payload); err != nil { - c.log.Warn("failed to notify engine driver of new L2 payload", "err", err, "id", payload.ID()) + n.log.Warn("failed to notify engine driver of new L2 payload", "err", err, "id", payload.ID()) } }(eng) } @@ -319,52 +338,52 @@ func (c *OpNode) ReceiveL2Payload(ctx context.Context, from peer.ID, payload *l2 } // Close closes all resources. -func (c *OpNode) Close() error { +func (n *OpNode) Close() error { var result *multierror.Error - if c.server != nil { - c.server.Stop() + if n.server != nil { + n.server.Stop() } - if c.dv5Udp != nil { - c.dv5Udp.Close() + if n.dv5Udp != nil { + n.dv5Udp.Close() } - if c.gsOut != nil { - if err := c.gsOut.Close(); err != nil { + if n.gsOut != nil { + if err := n.gsOut.Close(); err != nil { result = multierror.Append(result, fmt.Errorf("failed to close gossip cleanly: %v", err)) } } - if c.p2pSigner != nil { - if err := c.p2pSigner.Close(); err != nil { + if n.p2pSigner != nil { + if err := n.p2pSigner.Close(); err != nil { result = multierror.Append(result, fmt.Errorf("failed to close p2p signer: %v", err)) } } - if c.host != nil { - if err := c.host.Close(); err != nil { + if n.host != nil { + if err := n.host.Close(); err != nil { result = multierror.Append(result, fmt.Errorf("failed to close p2p host cleanly: %v", err)) } } - if c.resourcesClose != nil { - c.resourcesClose() + if n.resourcesClose != nil { + n.resourcesClose() } // stop L1 heads feed - if c.l1HeadsSub != nil { - c.l1HeadsSub.Unsubscribe() + if n.l1HeadsSub != nil { + n.l1HeadsSub.Unsubscribe() } // close L2 engines - for _, eng := range c.l2Engines { + for _, eng := range n.l2Engines { if err := eng.Close(); err != nil { result = multierror.Append(result, fmt.Errorf("failed to close L2 engine driver cleanly: %v", err)) } } // close L2 nodes - for _, n := range c.l2Nodes { + for _, n := range n.l2Nodes { n.Close() } // close L1 data source - if c.l1Source != nil { - c.l1Source.Close() + if n.l1Source != nil { + n.l1Source.Close() } return result.ErrorOrNil() } diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index 0f3ebc75c839..de40fceb6196 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -286,7 +286,7 @@ func BuildBlocksValidator(log log.Logger, cfg *rollup.Config) pubsub.ValidatorEx } type GossipIn interface { - ReceiveL2Payload(ctx context.Context, from peer.ID, msg *l2.ExecutionPayload) error + OnUnsafeL2Payload(ctx context.Context, from peer.ID, msg *l2.ExecutionPayload) error } type GossipOut interface { @@ -369,7 +369,7 @@ func JoinGossip(p2pCtx context.Context, self peer.ID, ps *pubsub.PubSub, log log return nil, fmt.Errorf("failed to subscribe to blocks gossip topic: %v", err) } - subscriber := MakeSubscriber(log, BlocksHandler(gossipIn.ReceiveL2Payload)) + subscriber := MakeSubscriber(log, BlocksHandler(gossipIn.OnUnsafeL2Payload)) go subscriber(p2pCtx, subscription) return &publisher{log: log, cfg: cfg, blocksTopic: blocksTopic}, nil diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 6b66e03fa2a1..88b58aa4815f 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -82,7 +82,7 @@ type SystemConfig struct { L1WsPort int L1ChainID *big.Int L2ChainID *big.Int - Nodes map[string]rollupNode.Config // Per node config. Don't use populate rollup.Config + Nodes map[string]*rollupNode.Config // Per node config. Don't use populate rollup.Config Loggers map[string]log.Logger RollupConfig rollup.Config // Shared rollup configs @@ -459,7 +459,7 @@ func (cfg SystemConfig) start() (*System, error) { } // Rollup nodes for name, nodeConfig := range cfg.Nodes { - c := nodeConfig + c := *nodeConfig // copy c.Rollup = sys.cfg.RollupConfig c.Rollup.DepositContractAddress = sys.DepositContractAddr diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 8d9029757fdf..debff989b9fc 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -8,6 +8,9 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" @@ -87,7 +90,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { L1WsPort: 9090, L1ChainID: big.NewInt(900), L2ChainID: big.NewInt(901), - Nodes: map[string]rollupNode.Config{ + Nodes: map[string]*rollupNode.Config{ "verifier": { L1NodeAddr: "ws://127.0.0.1:9090", L2EngineAddrs: []string{"ws://127.0.0.1:9091"}, @@ -481,12 +484,21 @@ func TestSystemMockP2P(t *testing.T) { "verifier": []string{"sequencer"}, } + var published, received []common.Hash + seqTracer, verifTracer := new(FnTracer), new(FnTracer) + seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *l2.ExecutionPayload) { + published = append(published, payload.BlockHash) + } + verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) { + received = append(received, payload.BlockHash) + } + cfg.Nodes["sequencer"].Tracer = seqTracer + cfg.Nodes["verifier"].Tracer = verifTracer + sys, err := cfg.start() require.Nil(t, err, "Error starting up system") defer sys.Close() - t.Log("successfully set up network") - l2Seq := sys.Clients["sequencer"] l2Verif := sys.Clients["verifier"] @@ -521,6 +533,12 @@ func TestSystemMockP2P(t *testing.T) { require.Nil(t, err, "Waiting for L2 tx on verifier") require.Equal(t, receiptSeq, receiptVerif) + + // Verify that everything that was published was received + require.Equal(t, published, received) + + // Verify that the tx was received via p2p + require.Contains(t, published, receiptVerif.BlockHash) } func TestL1InfoContract(t *testing.T) { diff --git a/opnode/test/tracer.go b/opnode/test/tracer.go new file mode 100644 index 000000000000..e1a81a1154c8 --- /dev/null +++ b/opnode/test/tracer.go @@ -0,0 +1,36 @@ +package test + +import ( + "context" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/libp2p/go-libp2p-core/peer" +) + +type FnTracer struct { + OnNewL1HeadFn func(ctx context.Context, sig eth.L1BlockRef) + OnUnsafeL2PayloadFn func(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) + OnPublishL2PayloadFn func(ctx context.Context, payload *l2.ExecutionPayload) +} + +func (n *FnTracer) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) { + if n.OnNewL1HeadFn != nil { + n.OnNewL1HeadFn(ctx, sig) + } +} + +func (n *FnTracer) OnUnsafeL2Payload(ctx context.Context, from peer.ID, payload *l2.ExecutionPayload) { + if n.OnUnsafeL2PayloadFn != nil { + n.OnUnsafeL2PayloadFn(ctx, from, payload) + } +} + +func (n *FnTracer) OnPublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) { + if n.OnPublishL2PayloadFn != nil { + n.OnPublishL2PayloadFn(ctx, payload) + } +} + +var _ node.Tracer = (*FnTracer)(nil) From b93c6419afeed3e9424ea2e23695fc1c897258b5 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 May 2022 21:36:57 +0200 Subject: [PATCH 558/585] opnode,specs: clarify gossip params --- opnode/p2p/gossip.go | 4 ++-- specs/rollup-node-p2p.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index de40fceb6196..1cc3aed4a6e3 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -103,8 +103,8 @@ func BuildGlobalGossipParams(cfg *rollup.Config) pubsub.GossipSubParams { params.Dlo = 6 // topic stable mesh low watermark params.Dhi = 12 // topic stable mesh high watermark params.Dlazy = 6 // gossip target - params.HeartbeatInterval = 500 * time.Millisecond // frequency of heartbeat, seconds - params.FanoutTTL = 24 * time.Second // ttl for fanout maps for topics we are not subscribed to but have published to, seconds + params.HeartbeatInterval = 500 * time.Millisecond // interval of heartbeat + params.FanoutTTL = 24 * time.Second // ttl for fanout maps for topics we are not subscribed to but have published to params.HistoryLength = 12 // number of windows to retain full messages in cache for IWANT responses params.HistoryGossip = 3 // number of windows to gossip about diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index b0d9aa2f5f9d..97c94f4d67b7 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -207,8 +207,8 @@ GossipSub [parameters][gossip-parameters]: - `D_low` (topic stable mesh low watermark): 6 - `D_high` (topic stable mesh high watermark): 12 - `D_lazy` (gossip target): 6 -- `heartbeat_interval` (frequency of heartbeat, seconds): 0.5 -- `fanout_ttl` (ttl for fanout maps for topics we are not subscribed to but have published to, seconds): 24 +- `heartbeat_interval` (interval of heartbeat, in seconds): 0.5 +- `fanout_ttl` (ttl for fanout maps for topics we are not subscribed to but have published to, in seconds): 24 - `mcache_len` (number of windows to retain full messages in cache for `IWANT` responses): 12 - `mcache_gossip` (number of windows to gossip about): 3 - `seen_ttl` (number of heartbeat intervals to retain message IDs): 80 (= 40 seconds) From 20a0a57f4132e4855f24855deaa7be508c6f9ab6 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 10 May 2022 21:38:21 +0200 Subject: [PATCH 559/585] opnode/l2/ssz: fix lousy copy range --- opnode/l2/ssz.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/l2/ssz.go b/opnode/l2/ssz.go index 7a0aa4fae351..38a8e54bcea0 100644 --- a/opnode/l2/ssz.go +++ b/opnode/l2/ssz.go @@ -67,7 +67,7 @@ func (payload *ExecutionPayload) MarshalSSZ(w io.Writer) (n int, err error) { offset := uint32(0) copy(buf[offset:offset+32], payload.ParentHash[:]) offset += 32 - copy(buf[offset:offset+32], payload.FeeRecipient[:]) + copy(buf[offset:offset+20], payload.FeeRecipient[:]) offset += 20 copy(buf[offset:offset+32], payload.StateRoot[:]) offset += 32 From c1ac67834d0c3ff85c97246344e2576d85a5e82b Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Tue, 10 May 2022 21:39:41 +0200 Subject: [PATCH 560/585] opnode/rollup/driver/state: fix doc typo Co-authored-by: Joshua Gutow --- opnode/rollup/driver/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index 065b9c7bc9c7..c5599ace9c22 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -319,7 +319,7 @@ func (s *state) handleUnsafeL2Payload(ctx context.Context, payload *l2.Execution return nil } - // Not that the payload may cause reorgs. The l2SafeHead may get out of sync because of this. + // Note that the payload may cause reorgs. The l2SafeHead may get out of sync because of this. // The engine should never reorg past the finalized block hash however. // The engine may attempt syncing via p2p if there is a larger gap in the L2 chain. From 5142a1e585526f4c140b5549df61f462065ec811 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Thu, 12 May 2022 08:36:56 -0600 Subject: [PATCH 561/585] Add version RPC (#432) Meta: - Fixes ENG-2200 --- opnode/Makefile | 3 ++- opnode/cmd/main.go | 14 +++++++------- opnode/node/api.go | 6 ++++++ opnode/node/server_test.go | 27 +++++++++++++++++++++++++++ opnode/version/version.go | 6 ++++++ 5 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 opnode/version/version.go diff --git a/opnode/Makefile b/opnode/Makefile index 923684723ae3..996dbf6821ab 100644 --- a/opnode/Makefile +++ b/opnode/Makefile @@ -4,7 +4,8 @@ VERSION := v0.0.0 LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) -LDFLAGSSTRING +=-X main.Version=$(VERSION) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimistic-specs/opnode/version.Version=$(VERSION) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimistic-specs/opnode/version.Meta=$(VERSION_META) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" opnode: diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index fbcd2fb97bb4..760b20cd96fb 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -6,6 +6,8 @@ import ( "os/signal" "syscall" + "github.com/ethereum-optimism/optimistic-specs/opnode/version" + "github.com/ethereum-optimism/optimistic-specs/opnode" "github.com/ethereum-optimism/optimistic-specs/opnode/flags" @@ -15,23 +17,21 @@ import ( ) var ( - Version = "0.0.0" - GitCommit = "" - GitDate = "" - VersionMeta = "dev" + GitCommit = "" + GitDate = "" ) // VersionWithMeta holds the textual version string including the metadata. var VersionWithMeta = func() string { - v := Version + v := version.Version if GitCommit != "" { v += "-" + GitCommit[:8] } if GitDate != "" { v += "-" + GitDate } - if VersionMeta != "" { - v += "-" + VersionMeta + if version.Meta != "" { + v += "-" + version.Meta } return v }() diff --git a/opnode/node/api.go b/opnode/node/api.go index 3c9658d77854..1c7fcbd76237 100644 --- a/opnode/node/api.go +++ b/opnode/node/api.go @@ -7,6 +7,8 @@ import ( "fmt" "math/big" + "github.com/ethereum-optimism/optimistic-specs/opnode/version" + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" @@ -80,6 +82,10 @@ func (n *nodeAPI) OutputAtBlock(ctx context.Context, number rpc.BlockNumber) ([] return []l2.Bytes32{l2OutputRootVersion, l2OutputRoot}, nil } +func (n *nodeAPI) Version(ctx context.Context) (string, error) { + return version.Version + "-" + version.Meta, nil +} + func toBlockNumArg(number rpc.BlockNumber) string { if number == rpc.LatestBlockNumber { return "latest" diff --git a/opnode/node/server_test.go b/opnode/node/server_test.go index 57e75c6544d3..cae68c396f8b 100644 --- a/opnode/node/server_test.go +++ b/opnode/node/server_test.go @@ -4,6 +4,9 @@ import ( "context" "encoding/json" "math/big" + + "github.com/ethereum-optimism/optimistic-specs/opnode/version" + "testing" "github.com/ethereum-optimism/optimistic-specs/opnode/eth" @@ -96,6 +99,30 @@ func TestOutputAtBlock(t *testing.T) { l2Client.mock.AssertExpectations(t) } +func TestVersion(t *testing.T) { + log := testlog.Logger(t, log.LvlError) + l2Client := &mockL2Client{} + rpcCfg := &RPCConfig{ + ListenAddr: "localhost", + ListenPort: 0, + } + rollupCfg := &rollup.Config{ + // ignore other rollup config info in this test + } + server, err := newRPCServer(context.Background(), rpcCfg, rollupCfg, l2Client, log, "0.0") + assert.NoError(t, err) + assert.NoError(t, server.Start()) + defer server.Stop() + + client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String()) + assert.NoError(t, err) + + var out string + err = client.CallContext(context.Background(), &out, "optimism_version") + assert.NoError(t, err) + assert.Equal(t, version.Version+"-"+version.Meta, out) +} + type mockL2Client struct { mock mock.Mock } diff --git a/opnode/version/version.go b/opnode/version/version.go new file mode 100644 index 000000000000..f98d13bb5281 --- /dev/null +++ b/opnode/version/version.go @@ -0,0 +1,6 @@ +package version + +var ( + Version = "0.0.0" + Meta = "dev" +) From 55db896914e43d0efd2ec5e0fc5654ba6da82356 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Thu, 12 May 2022 13:09:02 -0400 Subject: [PATCH 562/585] refactor: new messengers (#421) * contracts: consolidate OptimismPortal Co-authored-by: smartcontracts * contracts: delete abstracts Co-authored-by: smartcontracts * contracts: base `CrossDomainMessenger` + L1 and L2 Implement the `L1CrossDomainMessenger` and `L2CrossDomainMessenger` based on the base `CrossDomainMessenger`. This makes the interfaces the same on both sides. Co-authored-by: smartcontracts * contracts: `StandardBridge` Also implement the `L1StandardBridge` and `L2StandardBridge` based off of the base `StandardBridge` Co-authored-by: smartcontracts * contracts: L2OutputOracle Co-authored-by: smartcontracts * contracts: standard bridge tests Co-authored-by: smartcontracts * contracts: cross domain hashing lib + tests Co-authored-by: smartcontracts * contracts: tests for cross domain messengers Co-authored-by: smartcontracts * contracts: L2ToL1MessagePasser Co-authored-by: smartcontracts * contracts: safe call lib Co-authored-by: smartcontracts * contracts: optimism mintable erc20 Co-authored-by: smartcontracts * contracts: common test setup Co-authored-by: smartcontracts * contracts: optimism mintable token factory Co-authored-by: smartcontracts * contracts: update forge-std Co-authored-by: smartcontracts * contracts: test OptimismPortal Co-authored-by: smartcontracts * contracts: L1Block attributes Co-authored-by: smartcontracts * contracts: update libraries Co-authored-by: smartcontracts * contracts: update foundry.toml Co-authored-by: smartcontracts * contracts: Burner Co-authored-by: smartcontracts * contracts: delete dead code Co-authored-by: smartcontracts * contracts: update hh deploy scripts Co-authored-by: smartcontracts * contracts: update gas snapshot Co-authored-by: smartcontracts * integration-tests: update for new messengers Co-authored-by: smartcontracts * ops: devnet up script new genesis Co-authored-by: smartcontracts * opnode: new bindings Co-authored-by: smartcontracts * l2os: new bindings Co-authored-by: smartcontracts * contracts: update gas snapshot Co-authored-by: smartcontracts * specs: L2ToL1MessagePasser * specs: messengers * specs: bridges * specs: fix linting issues * contracts: better contract for is optimism mintable * contracts: fix some comments * contracts: assert finalization window has passed * bindings: regenerate * contracts: address comments Co-authored-by: Mark Tyneway --- l2os/bindings/l2oo/l2_output_oracle.go | 108 +++-- l2os/drivers/l2output/driver.go | 1 + opnode/contracts/Makefile | 4 - opnode/contracts/deposit/deposit_feed_raw.go | 39 +- .../deposit/optimism_portal_deployed.go | 2 +- opnode/test/system_test.go | 2 +- ops/devnet-up.sh | 22 +- packages/contracts/.gas-snapshot | 145 ++++--- .../contracts/L1/L1CrossDomainMessenger.sol | 67 +++ .../contracts/L1/L1StandardBridge.sol | 212 +++++++++ .../contracts/contracts/L1/L2OutputOracle.sol | 69 ++- .../contracts/contracts/L1/OptimismPortal.sol | 239 +++++++++- .../contracts/L1/abstracts/DepositFeed.sol | 73 ---- .../contracts/L1/abstracts/IDepositFeed.sol | 11 - .../L1/abstracts/WithdrawalsRelay.sol | 154 ------- .../L1/messaging/IL1CrossDomainMessenger.sol | 45 -- .../L1/messaging/L1CrossDomainMessenger.sol | 262 ----------- .../L1/messaging/L1StandardBridge.sol | 272 ------------ packages/contracts/contracts/L2/Burner.sol | 5 + .../contracts/contracts/L2/IWithdrawer.sol | 25 -- packages/contracts/contracts/L2/L1Block.sol | 37 +- .../contracts/L2/L2CrossDomainMessenger.sol | 54 +++ .../contracts/L2/L2StandardBridge.sol | 186 ++++++++ ...Withdrawer.sol => L2ToL1MessagePasser.sol} | 65 +-- .../contracts/L2/messaging/IL2ERC20Bridge.sol | 108 ----- .../L2/messaging/IL2StandardTokenFactory.sol | 11 - .../L2/messaging/L2CrossDomainMessenger.sol | 175 -------- .../L2/messaging/L2StandardBridge.sol | 191 -------- .../L2/messaging/L2StandardTokenFactory.sol | 40 -- .../contracts/L2/tokens/IL2StandardERC20.sol | 18 - .../contracts/L2/tokens/L2StandardERC20.sol | 56 --- .../libraries/ExcessivelySafeCall.sol | 60 +++ .../Lib_BedrockPredeployAddresses.sol | 2 +- .../libraries/Lib_CrossDomainHashing.sol | 249 +++++++++++ .../libraries/Lib_WithdrawalVerifier.sol | 13 +- .../contracts/contracts/test/CommonTest.t.sol | 294 ++++++++++++- .../contracts/test/CrossDomainHashing.t.sol | 71 +++ .../contracts/test/DepositFeed.t.sol | 218 ---------- .../contracts/contracts/test/L1Block.t.sol | 16 +- .../test/L1CrossDomainMessenger.t.sol | 339 ++++++--------- .../contracts/test/L1StandardBridge.t.sol | 408 +++++++++++++++--- .../test/L2CrossDomainMessenger.t.sol | 270 ++++++------ .../contracts/test/L2OutputOracle.t.sol | 130 +++--- .../contracts/test/L2StandardBridge.t.sol | 138 +++--- .../contracts/test/L2ToL1MessagePasser.t.sol | 104 +++++ .../test/OptimismMintableERC20.t.sol | 67 +++ .../test/OptimismMintableTokenFactory.t.sol | 79 ++++ .../contracts/test/OptimismPortal.t.sol | 276 +++++++++++- .../contracts/test/WithdrawalsRelay.t.sol | 174 -------- .../contracts/contracts/test/Withdrawer.t.sol | 111 ----- .../universal/CrossDomainMessenger.sol | 246 +++++++++++ .../universal/OptimismMintableERC20.sol | 100 +++++ .../OptimismMintableTokenFactory.sol | 68 +++ .../contracts/universal/StandardBridge.sol | 309 +++++++++++++ .../deploy/002-L1CrossDomainMessenger.ts | 34 ++ .../contracts/deploy/003-L1StandardBridge.ts | 31 ++ .../004-OptimismMintableTokenFactory.ts | 35 ++ packages/contracts/foundry.toml | 3 +- packages/contracts/lib/forge-std | 2 +- .../test/000_withdrawals.spec.ts | 21 +- .../test/shared/constants.ts | 1 - packages/integration-tests/test/shared/env.ts | 2 +- specs/bridges.md | 51 +++ specs/messengers.md | 113 +++++ specs/proposals.md | 8 +- specs/withdrawals.md | 40 +- 66 files changed, 4043 insertions(+), 2738 deletions(-) create mode 100644 packages/contracts/contracts/L1/L1CrossDomainMessenger.sol create mode 100644 packages/contracts/contracts/L1/L1StandardBridge.sol delete mode 100644 packages/contracts/contracts/L1/abstracts/DepositFeed.sol delete mode 100644 packages/contracts/contracts/L1/abstracts/IDepositFeed.sol delete mode 100644 packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol delete mode 100644 packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol delete mode 100644 packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol delete mode 100644 packages/contracts/contracts/L1/messaging/L1StandardBridge.sol delete mode 100644 packages/contracts/contracts/L2/IWithdrawer.sol create mode 100644 packages/contracts/contracts/L2/L2CrossDomainMessenger.sol create mode 100644 packages/contracts/contracts/L2/L2StandardBridge.sol rename packages/contracts/contracts/L2/{Withdrawer.sol => L2ToL1MessagePasser.sol} (62%) delete mode 100644 packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol delete mode 100644 packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol delete mode 100644 packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol delete mode 100644 packages/contracts/contracts/L2/messaging/L2StandardBridge.sol delete mode 100644 packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol delete mode 100644 packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol delete mode 100644 packages/contracts/contracts/L2/tokens/L2StandardERC20.sol create mode 100644 packages/contracts/contracts/libraries/ExcessivelySafeCall.sol create mode 100644 packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol create mode 100644 packages/contracts/contracts/test/CrossDomainHashing.t.sol delete mode 100644 packages/contracts/contracts/test/DepositFeed.t.sol create mode 100644 packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol create mode 100644 packages/contracts/contracts/test/OptimismMintableERC20.t.sol create mode 100644 packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol delete mode 100644 packages/contracts/contracts/test/WithdrawalsRelay.t.sol delete mode 100644 packages/contracts/contracts/test/Withdrawer.t.sol create mode 100644 packages/contracts/contracts/universal/CrossDomainMessenger.sol create mode 100644 packages/contracts/contracts/universal/OptimismMintableERC20.sol create mode 100644 packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol create mode 100644 packages/contracts/contracts/universal/StandardBridge.sol create mode 100644 packages/contracts/deploy/002-L1CrossDomainMessenger.ts create mode 100644 packages/contracts/deploy/003-L1StandardBridge.ts create mode 100644 packages/contracts/deploy/004-OptimismMintableTokenFactory.ts delete mode 100644 packages/integration-tests/test/shared/constants.ts create mode 100644 specs/bridges.md create mode 100644 specs/messengers.md diff --git a/l2os/bindings/l2oo/l2_output_oracle.go b/l2os/bindings/l2oo/l2_output_oracle.go index 932bb9f5e18a..d2d9386b688a 100644 --- a/l2os/bindings/l2oo/l2_output_oracle.go +++ b/l2os/bindings/l2oo/l2_output_oracle.go @@ -28,10 +28,16 @@ var ( _ = event.NewSubscription ) +// L2OutputOracleOutputProposal is an auto generated low-level Go binding around an user-defined struct. +type L2OutputOracleOutputProposal struct { + OutputRoot [32]byte + Timestamp *big.Int +} + // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x61010060405234801561001157600080fd5b50604051610e3d380380610e3d83398101604081905261003091610148565b610039336100f8565b61004385876101ac565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052600082815260026020526040902084905560c0839052600182905560e08290526100ed816100f8565b5050505050506101ce565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561016157600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b038116811461019e57600080fd5b809150509295509295509295565b6000826101c957634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610c0d610230600039600081816101af015281816102d401526103aa01526000818161028e01526103db01526000818160e801526103890152600081816101e30152818161085801526108880152610c0d6000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad1461027c578063f2fde38b146102b057600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b806325188104116100b057806325188104146101535780632b5d15d914610168578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d5780630c1952d31461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610aeb565b6102d0565b34801561014957600080fd5b5061010a60015481565b610166610161366004610b04565b610405565b005b34801561017457600080fd5b50610166610183366004610aeb565b6106ee565b34801561019457600080fd5b5061010a610884565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b506101666108b9565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b5061010a61026a366004610aeb565b60009081526002602052604090205490565b34801561028857600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102bc57600080fd5b506101666102cb366004610b36565b610946565b60007f0000000000000000000000000000000000000000000000000000000000000000821015610387576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008303816103d8576103d8610b73565b047f0000000000000000000000000000000000000000000000000000000000000000600101019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b428310610515576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f6500000000000000000000000000000000000000000000000000000000000000606482015260840161037e565b61051d610884565b83146105ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d70000000000000000000000000000000000000606482015260840161037e565b83610612576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f7574707574000000604482015260640161037e565b81156106a857818140146106a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e00000000000000606482015260840161037e565b600083815260026020526040808220869055600185905551849186917f92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b9190a350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b600154600090815260026020526040902054818114610810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e00000000000000000000000000000000000000000000000000606482015260840161037e565b60015460405182907f36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f26690600090a3600180546000908152600260205260408120555461087d907f000000000000000000000000000000000000000000000000000000000000000090610bd1565b6001555050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546108b49190610be8565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331461093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b6109446000610a76565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161037e565b73ffffffffffffffffffffffffffffffffffffffff8116610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161037e565b610a7381610a76565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610afd57600080fd5b5035919050565b60008060008060808587031215610b1a57600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610b4857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610b6c57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610be357610be3610ba2565b500390565b60008219821115610bfb57610bfb610ba2565b50019056fea164736f6c634300080a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"_proposal\",\"type\":\"tuple\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x61010060405234801561001157600080fd5b50604051610fa1380380610fa183398101604081905261003091610164565b61003933610114565b61004385876101c8565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052604080518082018252858152426020808301918252600086815260029091529290922090518155905160019182015560c084905282905560e082905261010981610114565b5050505050506101ea565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561017d57600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ba57600080fd5b809150509295509295509295565b6000826101e557634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610d5561024c600039600081816101af0152818161031b01526103f10152600081816102d5015261042201526000818160e801526103d00152600081816101e301528181610625015261095a0152610d556000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad146102c3578063f2fde38b146102f757600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b80630c1952d3116100b05780630c1952d31461015f5780632518810414610175578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d578063093b3d901461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610bbd565b610317565b34801561014957600080fd5b5061015d610158366004610bd6565b61044c565b005b34801561016b57600080fd5b5061010a60015481565b61015d610183366004610c4c565b610651565b34801561019457600080fd5b5061010a610956565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b5061015d61098b565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b506102a861026a366004610bbd565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b60408051825181526020928301519281019290925201610114565b3480156102cf57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561030357600080fd5b5061015d610312366004610c7e565b610a18565b60007f00000000000000000000000000000000000000000000000000000000000000008210156103ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161041f5761041f610cbb565b047f0000000000000000000000000000000000000000000000000000000000000000600101019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b6001805460009081526002602090815260409182902082518084019093528054808452930154908201528251909114610588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e0000000000000000000000000000000000000000000000000060648201526084016103c5565b80602001518260200151146105d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044016103c5565b600154602082015182516040517f6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c700990600090a46001805460009081526002602052604081208181558201555461064a907f000000000000000000000000000000000000000000000000000000000000000090610d19565b6001555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b428310610761576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016103c5565b610769610956565b83146107f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d7000000000000000000000000000000000000060648201526084016103c5565b8361085e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f757470757400000060448201526064016103c5565b81156108f457818140146108f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e0000000000000060648201526084016103c5565b60408051808201825285815242602080830182815260008881526002909252848220935184555160019384015591869055915185929187917f54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba9190a450505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546109869190610d30565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b610a166000610b48565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b73ffffffffffffffffffffffffffffffffffffffff8116610b3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103c5565b610b4581610b48565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610bcf57600080fd5b5035919050565b600060408284031215610be857600080fd5b6040516040810181811067ffffffffffffffff82111715610c32577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b60008060008060808587031215610c6257600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610c9057600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610cb457600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610d2b57610d2b610cea565b500390565b60008219821115610d4357610d43610cea565b50019056fea164736f6c634300080a000a", } // L2OutputOracleABI is the input ABI used to generate the binding from. @@ -358,16 +364,16 @@ func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2time // GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) ([32]byte, error) { +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns((bytes32,uint256)) +func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) (L2OutputOracleOutputProposal, error) { var out []interface{} err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp) if err != nil { - return *new([32]byte), err + return *new(L2OutputOracleOutputProposal), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(L2OutputOracleOutputProposal)).(*L2OutputOracleOutputProposal) return out0, err @@ -375,15 +381,15 @@ func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l // GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns((bytes32,uint256)) +func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) (L2OutputOracleOutputProposal, error) { return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) } // GetL2Output is a free data retrieval call binding the contract method 0xa25ae557. // -// Solidity: function getL2Output(uint256 _l2Timestamp) view returns(bytes32) -func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) ([32]byte, error) { +// Solidity: function getL2Output(uint256 _l2Timestamp) view returns((bytes32,uint256)) +func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) (L2OutputOracleOutputProposal, error) { return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp) } @@ -501,25 +507,25 @@ func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber) } -// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// DeleteL2Output is a paid mutator transaction binding the contract method 0x093b3d90. // -// Solidity: function deleteL2Output(bytes32 _l2Output) returns() -func (_L2OutputOracle *L2OutputOracleTransactor) DeleteL2Output(opts *bind.TransactOpts, _l2Output [32]byte) (*types.Transaction, error) { - return _L2OutputOracle.contract.Transact(opts, "deleteL2Output", _l2Output) +// Solidity: function deleteL2Output((bytes32,uint256) _proposal) returns() +func (_L2OutputOracle *L2OutputOracleTransactor) DeleteL2Output(opts *bind.TransactOpts, _proposal L2OutputOracleOutputProposal) (*types.Transaction, error) { + return _L2OutputOracle.contract.Transact(opts, "deleteL2Output", _proposal) } -// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// DeleteL2Output is a paid mutator transaction binding the contract method 0x093b3d90. // -// Solidity: function deleteL2Output(bytes32 _l2Output) returns() -func (_L2OutputOracle *L2OutputOracleSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { - return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) +// Solidity: function deleteL2Output((bytes32,uint256) _proposal) returns() +func (_L2OutputOracle *L2OutputOracleSession) DeleteL2Output(_proposal L2OutputOracleOutputProposal) (*types.Transaction, error) { + return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _proposal) } -// DeleteL2Output is a paid mutator transaction binding the contract method 0x2b5d15d9. +// DeleteL2Output is a paid mutator transaction binding the contract method 0x093b3d90. // -// Solidity: function deleteL2Output(bytes32 _l2Output) returns() -func (_L2OutputOracle *L2OutputOracleTransactorSession) DeleteL2Output(_l2Output [32]byte) (*types.Transaction, error) { - return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _l2Output) +// Solidity: function deleteL2Output((bytes32,uint256) _proposal) returns() +func (_L2OutputOracle *L2OutputOracleTransactorSession) DeleteL2Output(_proposal L2OutputOracleOutputProposal) (*types.Transaction, error) { + return _L2OutputOracle.Contract.DeleteL2Output(&_L2OutputOracle.TransactOpts, _proposal) } // RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. @@ -787,46 +793,55 @@ func (it *L2OutputOracleL2OutputAppendedIterator) Close() error { // L2OutputOracleL2OutputAppended represents a L2OutputAppended event raised by the L2OutputOracle contract. type L2OutputOracleL2OutputAppended struct { L2Output [32]byte + L1Timestamp *big.Int L2timestamp *big.Int Raw types.Log // Blockchain specific contextual infos } -// FilterL2OutputAppended is a free log retrieval operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// FilterL2OutputAppended is a free log retrieval operation binding the contract event 0x54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba. // -// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputAppendedIterator, error) { +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind.FilterOpts, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputAppendedIterator, error) { var _l2OutputRule []interface{} for _, _l2OutputItem := range _l2Output { _l2OutputRule = append(_l2OutputRule, _l2OutputItem) } + var _l1TimestampRule []interface{} + for _, _l1TimestampItem := range _l1Timestamp { + _l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem) + } var _l2timestampRule []interface{} for _, _l2timestampItem := range _l2timestamp { _l2timestampRule = append(_l2timestampRule, _l2timestampItem) } - logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputAppended", _l2OutputRule, _l1TimestampRule, _l2timestampRule) if err != nil { return nil, err } return &L2OutputOracleL2OutputAppendedIterator{contract: _L2OutputOracle.contract, event: "l2OutputAppended", logs: logs, sub: sub}, nil } -// WatchL2OutputAppended is a free log subscription operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// WatchL2OutputAppended is a free log subscription operation binding the contract event 0x54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba. // -// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputAppended, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputAppended, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (event.Subscription, error) { var _l2OutputRule []interface{} for _, _l2OutputItem := range _l2Output { _l2OutputRule = append(_l2OutputRule, _l2OutputItem) } + var _l1TimestampRule []interface{} + for _, _l1TimestampItem := range _l1Timestamp { + _l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem) + } var _l2timestampRule []interface{} for _, _l2timestampItem := range _l2timestamp { _l2timestampRule = append(_l2timestampRule, _l2timestampItem) } - logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputAppended", _l2OutputRule, _l2timestampRule) + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputAppended", _l2OutputRule, _l1TimestampRule, _l2timestampRule) if err != nil { return nil, err } @@ -858,9 +873,9 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind. }), nil } -// ParseL2OutputAppended is a log parse operation binding the contract event 0x92701dc658a5d84c16077ea6de344b9995e21a96a05d45e4cd22f37a3d266f8b. +// ParseL2OutputAppended is a log parse operation binding the contract event 0x54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba. // -// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp) func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.Log) (*L2OutputOracleL2OutputAppended, error) { event := new(L2OutputOracleL2OutputAppended) if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", log); err != nil { @@ -940,46 +955,55 @@ func (it *L2OutputOracleL2OutputDeletedIterator) Close() error { // L2OutputOracleL2OutputDeleted represents a L2OutputDeleted event raised by the L2OutputOracle contract. type L2OutputOracleL2OutputDeleted struct { L2Output [32]byte + L1Timestamp *big.Int L2timestamp *big.Int Raw types.Log // Blockchain specific contextual infos } -// FilterL2OutputDeleted is a free log retrieval operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// FilterL2OutputDeleted is a free log retrieval operation binding the contract event 0x6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c7009. // -// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputDeleted(opts *bind.FilterOpts, _l2Output [][32]byte, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputDeletedIterator, error) { +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputDeleted(opts *bind.FilterOpts, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputDeletedIterator, error) { var _l2OutputRule []interface{} for _, _l2OutputItem := range _l2Output { _l2OutputRule = append(_l2OutputRule, _l2OutputItem) } + var _l1TimestampRule []interface{} + for _, _l1TimestampItem := range _l1Timestamp { + _l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem) + } var _l2timestampRule []interface{} for _, _l2timestampItem := range _l2timestamp { _l2timestampRule = append(_l2timestampRule, _l2timestampItem) } - logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) + logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputDeleted", _l2OutputRule, _l1TimestampRule, _l2timestampRule) if err != nil { return nil, err } return &L2OutputOracleL2OutputDeletedIterator{contract: _L2OutputOracle.contract, event: "l2OutputDeleted", logs: logs, sub: sub}, nil } -// WatchL2OutputDeleted is a free log subscription operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// WatchL2OutputDeleted is a free log subscription operation binding the contract event 0x6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c7009. // -// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) -func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputDeleted, _l2Output [][32]byte, _l2timestamp []*big.Int) (event.Subscription, error) { +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp) +func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputDeleted, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (event.Subscription, error) { var _l2OutputRule []interface{} for _, _l2OutputItem := range _l2Output { _l2OutputRule = append(_l2OutputRule, _l2OutputItem) } + var _l1TimestampRule []interface{} + for _, _l1TimestampItem := range _l1Timestamp { + _l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem) + } var _l2timestampRule []interface{} for _, _l2timestampItem := range _l2timestamp { _l2timestampRule = append(_l2timestampRule, _l2timestampItem) } - logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputDeleted", _l2OutputRule, _l2timestampRule) + logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputDeleted", _l2OutputRule, _l1TimestampRule, _l2timestampRule) if err != nil { return nil, err } @@ -1011,9 +1035,9 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.W }), nil } -// ParseL2OutputDeleted is a log parse operation binding the contract event 0x36160157c233b38fe28ace444408a0db0f7b3d02e652bb27ea9604cbd2a3f266. +// ParseL2OutputDeleted is a log parse operation binding the contract event 0x6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c7009. // -// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp) +// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp) func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputDeleted(log types.Log) (*L2OutputOracleL2OutputDeleted, error) { event := new(L2OutputOracleL2OutputDeleted) if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", log); err != nil { diff --git a/l2os/drivers/l2output/driver.go b/l2os/drivers/l2output/driver.go index 9db818580566..350d103a09ce 100644 --- a/l2os/drivers/l2output/driver.go +++ b/l2os/drivers/l2output/driver.go @@ -61,6 +61,7 @@ func NewDriver(cfg Config) (*Driver, error) { ) walletAddr := crypto.PubkeyToAddress(cfg.PrivKey.PublicKey) + log.Info("Configured driver", "wallet", walletAddr, "l2-output-contract", cfg.L2OOAddr) return &Driver{ cfg: cfg, diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index 20dfa49c0b7e..7b9e9becf4c5 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -1,13 +1,9 @@ SHELL := /bin/bash CONTRACTS_PATH := "../../packages/contracts/" -OPTIMISM_PORTAL := ../../packages/contracts/contracts/L1/OptimismPortal.sol -L1_BLOCK_INFO := ../../packages/contracts/contracts/L2/L1Block.sol - bindings: bindings-l1-block-info bindings-optimism-portal deployed-bin-l1-block-info deployed-bin-optimism-portal - # Split up b/c I don't know how to include this step in the L1 Block Info Bindings # What is occuring is that the `temp` variable is hard to pull into the `eval` deployed-bin-l1-block-info: bindings-l1-block-info diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/opnode/contracts/deposit/deposit_feed_raw.go index fa5b453b607c..58e512d9f75a 100644 --- a/opnode/contracts/deposit/deposit_feed_raw.go +++ b/opnode/contracts/deposit/deposit_feed_raw.go @@ -38,8 +38,8 @@ type WithdrawalVerifierOutputRootProof struct { // OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. var OptimismPortalMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYetFinal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60c0604052600080546001600160a01b03191661dead17905534801561002457600080fd5b50604051620022f9380380620022f98339810160408190526100459161005b565b6001600160a01b0390911660a052608052610095565b6000806040838503121561006e57600080fd5b82516001600160a01b038116811461008557600080fd5b6020939093015192949293505050565b60805160a051612231620000c86000396000818160a501526103500152600081816101a301526102c401526122316000f3fe6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015e578063eecf1c3614610171578063ff61cc931461019157600080fd5b80621c2ff6146100935780639bf62d82146100f1578063a14238e71461011e57600080fd5b3661008e5761008c33346175306000604051806020016040528060008152506101d3565b005b600080fd5b34801561009f57600080fd5b506100c77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fd57600080fd5b506000546100c79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012a57600080fd5b5061014e610139366004611c41565b60016020526000908152604090205460ff1681565b60405190151581526020016100e8565b61008c61016c366004611cb2565b6101d3565b34801561017d57600080fd5b5061008c61018c366004611e18565b6102c2565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e8565b8180156101f5575073ffffffffffffffffffffffffffffffffffffffff851615155b1561022c576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3332811461024d575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102b2959493929190611f18565b60405180910390a3505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000840142101561031e576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401602060405180830381865afa1580156103ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d09190611fb4565b9050610424846040805182356020828101919091528301358183015290820135606082810191909152820135608082015260009060a001604051602081830303815290604052805190602001209050919050565b811461045c576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046d8d8d8d8d8d8d8d610648565b905061047f818660400135868661068a565b6104b5576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff1615151415610504576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161059b929190611fcd565b600060405180830381858888f193505050503d80600081146105d9576040519150601f19603f3d011682016040523d82523d6000602084013e6105de565b606091505b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17815560405191925083917f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f9190a25050505050505050505050505050565b6000878787878787876040516020016106679796959493929190611fdd565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016106aa929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052925061077091016040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061077a915050565b9695505050505050565b60008061078686610794565b9050610770818686866107c6565b606081805190602001206040516020016107b091815260200190565b6040516020818303038152906040529050919050565b60008060006107d68786866107f7565b915091508180156107ec57506107ec86826108f1565b979650505050505050565b6000606060006108068561090d565b90506000806000610818848a89610a08565b8151929550909350915015808061082c5750815b610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064015b60405180910390fd5b6000816108b357604051806020016040528060008152506108df565b6108df866108c2600188612099565b815181106108d2576108d26120b0565b6020026020010151610f25565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b6060600061091a83610f4f565b90506000815167ffffffffffffffff81111561093857610938611c83565b60405190808252806020026020018201604052801561097d57816020015b60408051808201909152606080825260208201528152602001906001900390816109565790505b50905060005b8251811015610a005760006109b08483815181106109a3576109a36120b0565b6020026020010151610f82565b905060405180604001604052808281526020016109cc83610f4f565b8152508383815181106109e1576109e16120b0565b60200260200101819052505080806109f8906120df565b915050610983565b509392505050565b60006060818080610a188761102c565b90506000869050600080610a3f604051806040016040528060608152602001606081525090565b60005b8c51811015610ee1578c8181518110610a5d57610a5d6120b0565b602002602001015191508284610a739190612118565b9350610a80600188612118565b965083610afe57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f742068617368000000000000000000000000000000604482015260640161088e565b610bef565b815151602011610b7a57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161088e565b84610b8883600001516111af565b14610bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161088e565b610bfb60106001612118565b8260200151511415610c74578551841415610c1557610ee1565b6000868581518110610c2957610c296120b0565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c5457610c546120b0565b60200260200101519050610c67816111d7565b9650600194505050610ecf565b60028260200151511415610e6d576000610c8d83611214565b9050600081600081518110610ca457610ca46120b0565b016020015160f81c90506000610cbb60028361215f565b610cc6906002612181565b90506000610cd7848360ff16611238565b90506000610ce58b8a611238565b90506000610cf3838361126e565b905060ff851660021480610d0a575060ff85166003145b15610d6057808351148015610d1f5750808251145b15610d3157610d2e818b612118565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b60ff85161580610d73575060ff85166001145b15610de55782518114610daf57507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b610dd68860200151600181518110610dc957610dc96120b0565b60200260200101516111d7565b9a509750610ecf945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f7072656669780000000000000000000000000000000000000000000000000000606482015260840161088e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161088e565b80610ed9816120df565b915050610a42565b507f8000000000000000000000000000000000000000000000000000000000000000841486610f108786611238565b909e909d50909b509950505050505050505050565b6020810151805160609161090791610f3f90600190612099565b815181106109a3576109a36120b0565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906109079061131a565b60606000806000610f928561154d565b919450925090506000816001811115610fad57610fad6121a4565b14611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161088e565b61102385602001518484611954565b95945050505050565b606060008251600261103e91906121d3565b67ffffffffffffffff81111561105657611056611c83565b6040519080825280601f01601f191660200182016040528015611080576020820181803683370190505b50905060005b83518110156111a85760048482815181106110a3576110a36120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826110d88360026121d3565b815181106110e8576110e86120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061112b5761112b6120b0565b016020015161113d919060f81c61215f565b60f81b8261114c8360026121d3565b611157906001612118565b81518110611167576111676120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111a0816120df565b915050611086565b5092915050565b60006020825110156111c357506020015190565b818060200190518101906109079190611fb4565b600060606020836000015110156111f8576111f183611a33565b9050611204565b61120183610f82565b90505b61120d816111af565b9392505050565b606061090761123383602001516000815181106109a3576109a36120b0565b61102c565b6060825182106112575750604080516020810190915260008152610907565b61120d83838486516112699190612099565b611a3e565b6000805b8084511180156112825750808351115b8015611303575082818151811061129b5761129b6120b0565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112da576112da6120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561120d5780611312816120df565b915050611272565b60606000806113288461154d565b91935090915060019050816001811115611344576113446121a4565b146113ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161088e565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816113c45790505090506000835b8651811015611542576020821061148a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161088e565b6000806114c76040518060400160405280858c600001516114ab9190612099565b8152602001858c602001516114c09190612118565b905261154d565b5091509150604051806040016040528083836114e39190612118565b8152602001848b602001516114f89190612118565b81525085858151811061150d5761150d6120b0565b6020908102919091010152611523600185612118565b935061152f8183612118565b6115399084612118565b925050506113f1565b508152949350505050565b6000806000808460000151116115bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161088e565b6020840151805160001a607f81116115e457600060016000945094509450505061194d565b60b7811161167a5760006115f9608083612099565b905080876000015111611668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161088e565b6001955093506000925061194d915050565b60bf811161179d57600061168f60b783612099565b9050808760000151116116fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161088e565b600183015160208290036101000a90046117188183612118565b885111611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161088e565b61178c826001612118565b965094506000935061194d92505050565b60f781116118325760006117b260c083612099565b905080876000015111611821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161088e565b60019550935084925061194d915050565b600061183f60f783612099565b9050808760000151116118ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161088e565b600183015160208290036101000a90046118c88183612118565b885111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161088e565b61193c826001612118565b965094506001935061194d92505050565b9193909250565b606060008267ffffffffffffffff81111561197157611971611c83565b6040519080825280601f01601f19166020018201604052801561199b576020820181803683370190505b5090508051600014156119af57905061120d565b60006119bb8587612118565b90506020820160005b6119cf602087612210565b811015611a0657825182526119e5602084612118565b92506119f2602083612118565b9150806119fe816120df565b9150506119c4565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061090782611c2b565b606081611a4c81601f612118565b1015611ab4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b82611abf8382612118565b1015611b27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b611b318284612118565b84511015611b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161088e565b606082158015611bba5760405191506000825260208201604052611c22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bf3578051835260209283019201611bdb565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610907826020015160008460000151611954565b600060208284031215611c5357600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c7e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a08688031215611cca57600080fd5b611cd386611c5a565b945060208601359350604086013567ffffffffffffffff8082168214611cf857600080fd5b9093506060870135908115158214611d0f57600080fd5b90925060808701359080821115611d2557600080fd5b818801915088601f830112611d3957600080fd5b813581811115611d4b57611d4b611c83565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611d9157611d91611c83565b816040528281528b6020848701011115611daa57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b60008083601f840112611de157600080fd5b50813567ffffffffffffffff811115611df957600080fd5b602083019150836020828501011115611e1157600080fd5b9250929050565b60008060008060008060008060008060006101808c8e031215611e3a57600080fd5b8b359a50611e4a60208d01611c5a565b9950611e5860408d01611c5a565b985060608c0135975060808c0135965067ffffffffffffffff60a08d01351115611e8157600080fd5b611e918d60a08e01358e01611dcf565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215611ecf57600080fd5b60e08c01925067ffffffffffffffff6101608d01351115611eef57600080fd5b611f008d6101608e01358e01611dcf565b81935080925050509295989b509295989b9093969950565b85815260006020868184015267ffffffffffffffff86166040840152841515606084015260a0608084015283518060a085015260005b81811015611f6a5785810183015185820160c001528201611f4e565b81811115611f7c57600060c083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160c001979650505050505050565b600060208284031215611fc657600080fd5b5051919050565b8183823760009101908152919050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015284608083015260c060a08301528260c0830152828460e0840137600060e0848401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121115761211161206a565b5060010190565b6000821982111561212b5761212b61206a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061217257612172612130565b8060ff84160691505092915050565b600060ff821660ff84168082101561219b5761219b61206a565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561220b5761220b61206a565b500290565b60008261221f5761221f612130565b50049056fea164736f6c634300080a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriod\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawalInclusionProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroCreationTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawalAlreadyFinalized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60c0604052600080546001600160a01b03191661dead1790553480156200002557600080fd5b50604051620025da380380620025da83398101604081905262000048916200005f565b6001600160a01b0390911660a0526080526200009b565b600080604083850312156200007357600080fd5b82516001600160a01b03811681146200008b57600080fd5b6020939093015192949293505050565b60805160a05161250c620000ce6000396000818160a6015261036d01526000818161019701526103f0015261250c6000f3fe6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015f578063eecf1c3614610172578063ff61cc931461018557600080fd5b80621c2ff6146100945780639bf62d82146100f2578063a14238e71461011f57600080fd5b3661008f5761008d3334620186a06000604051806020016040528060008152506101c7565b005b600080fd5b3480156100a057600080fd5b506100c87f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fe57600080fd5b506000546100c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012b57600080fd5b5061014f61013a366004611e74565b60016020526000908152604090205460ff1681565b60405190151581526020016100e9565b61008d61016d366004611f34565b6101c7565b61008d61018036600461207e565b6102b6565b34801561019157600080fd5b506101b97f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e9565b8180156101e9575073ffffffffffffffffffffffffffffffffffffffff851615155b15610220576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114610241575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102a69594939291906121e9565b60405180910390a3505050505050565b73ffffffffffffffffffffffffffffffffffffffff891630141561033b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f742073656e64206d65737361676520746f2073656c662e0000000060448201526064015b60405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa1580156103c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ec9190612220565b90507f0000000000000000000000000000000000000000000000000000000000000000816020015161041e919061229e565b4211610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f706f73616c206973206e6f74207965742066696e616c697a65642e00006044820152606401610332565b61049d610498368690038601866122b6565b6107c0565b8151146104d6576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061051c8d8d8d8d8d8d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061081c92505050565b905061056381866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061085b92505050565b610599576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff16151514156105e8576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260016020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905561062e89614e2061229e565b5a10156106bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f496e73756666696369656e742067617320746f2066696e616c697a652077697460448201527f6864726177616c2e0000000000000000000000000000000000000000000000006064820152608401610332565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8e16178155604080516020601f8b01819004810282018101909252898152610742918e918d918f9186918f908f908190840183828082843760009201919091525061092492505050565b50600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906107a890841515815260200190565b60405180910390a25050505050505050505050505050565b600081600001518260200151836040015184606001516040516020016107ff949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60008686868686866040516020016108399695949392919061231c565b6040516020818303038152906040528051906020012090509695505050505050565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506109199101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529085876109af565b9150505b9392505050565b6000606060008060008661ffff1667ffffffffffffffff81111561094a5761094a611eb6565b6040519080825280601f01601f191660200182016040528015610974576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115610995578692505b828152826000602083013e90999098509650505050505050565b6000806109bb866109d3565b90506109c981868686610a05565b9695505050505050565b606081805190602001206040516020016109ef91815260200190565b6040516020818303038152906040529050919050565b6000806000610a15878686610a36565b91509150818015610a2b5750610a2b8682610b2b565b979650505050505050565b600060606000610a4585610b47565b90506000806000610a57848a89610c42565b81519295509093509150158080610a6b5750815b610ad1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610332565b600081610aed5760405180602001604052806000815250610b19565b610b1986610afc600188612373565b81518110610b0c57610b0c61238a565b602002602001015161115f565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b60606000610b5483611189565b90506000815167ffffffffffffffff811115610b7257610b72611eb6565b604051908082528060200260200182016040528015610bb757816020015b6040805180820190915260608082526020820152815260200190600190039081610b905790505b50905060005b8251811015610c3a576000610bea848381518110610bdd57610bdd61238a565b60200260200101516111bc565b90506040518060400160405280828152602001610c0683611189565b815250838381518110610c1b57610c1b61238a565b6020026020010181905250508080610c32906123b9565b915050610bbd565b509392505050565b60006060818080610c5287611266565b90506000869050600080610c79604051806040016040528060608152602001606081525090565b60005b8c5181101561111b578c8181518110610c9757610c9761238a565b602002602001015191508284610cad919061229e565b9350610cba60018861229e565b965083610d3857815180516020909101208514610d33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610332565b610e29565b815151602011610db457815180516020909101208514610d33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610332565b84610dc283600001516113e9565b14610e29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610332565b610e356010600161229e565b8260200151511415610eae578551841415610e4f5761111b565b6000868581518110610e6357610e6361238a565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610e8e57610e8e61238a565b60200260200101519050610ea181611411565b9650600194505050611109565b600282602001515114156110a7576000610ec783611447565b9050600081600081518110610ede57610ede61238a565b016020015160f81c90506000610ef5600283612421565b610f00906002612443565b90506000610f11848360ff1661146b565b90506000610f1f8b8a61146b565b90506000610f2d83836114a1565b905060ff851660021480610f44575060ff85166003145b15610f9a57808351148015610f595750808251145b15610f6b57610f68818b61229e565b99505b507f8000000000000000000000000000000000000000000000000000000000000000995061111b945050505050565b60ff85161580610fad575060ff85166001145b1561101f5782518114610fe957507f8000000000000000000000000000000000000000000000000000000000000000995061111b945050505050565b61101088602001516001815181106110035761100361238a565b6020026020010151611411565b9a509750611109945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610332565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610332565b80611113816123b9565b915050610c7c565b507f800000000000000000000000000000000000000000000000000000000000000084148661114a878661146b565b909e909d50909b509950505050505050505050565b60208101518051606091610b419161117990600190612373565b81518110610bdd57610bdd61238a565b604080518082018252600080825260209182015281518083019092528251825280830190820152606090610b419061154d565b606060008060006111cc85611780565b9194509250905060008160018111156111e7576111e7612466565b1461124e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610332565b61125d85602001518484611b87565b95945050505050565b60606000825160026112789190612495565b67ffffffffffffffff81111561129057611290611eb6565b6040519080825280601f01601f1916602001820160405280156112ba576020820181803683370190505b50905060005b83518110156113e25760048482815181106112dd576112dd61238a565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c82611312836002612495565b815181106113225761132261238a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106113655761136561238a565b0160200151611377919060f81c612421565b60f81b82611386836002612495565b61139190600161229e565b815181106113a1576113a161238a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806113da816123b9565b9150506112c0565b5092915050565b60006020825110156113fd57506020015190565b81806020019051810190610b4191906124d2565b600060606020836000015110156114325761142b83611c66565b905061143e565b61143b836111bc565b90505b61091d816113e9565b6060610b416114668360200151600081518110610bdd57610bdd61238a565b611266565b60608251821061148a5750604080516020810190915260008152610b41565b61091d838384865161149c9190612373565b611c71565b6000805b8084511180156114b55750808351115b801561153657508281815181106114ce576114ce61238a565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061150d5761150d61238a565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561091d5780611545816123b9565b9150506114a5565b606060008061155b84611780565b9193509091506001905081600181111561157757611577612466565b146115de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610332565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816115f75790505090506000835b865181101561177557602082106116bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610332565b6000806116fa6040518060400160405280858c600001516116de9190612373565b8152602001858c602001516116f3919061229e565b9052611780565b509150915060405180604001604052808383611716919061229e565b8152602001848b6020015161172b919061229e565b8152508585815181106117405761174061238a565b602090810291909101015261175660018561229e565b9350611762818361229e565b61176c908461229e565b92505050611624565b508152949350505050565b6000806000808460000151116117f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610332565b6020840151805160001a607f8111611817576000600160009450945094505050611b80565b60b781116118ad57600061182c608083612373565b90508087600001511161189b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610332565b60019550935060009250611b80915050565b60bf81116119d05760006118c260b783612373565b905080876000015111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610332565b600183015160208290036101000a900461194b818361229e565b8851116119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610332565b6119bf82600161229e565b9650945060009350611b8092505050565b60f78111611a655760006119e560c083612373565b905080876000015111611a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610332565b600195509350849250611b80915050565b6000611a7260f783612373565b905080876000015111611ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610332565b600183015160208290036101000a9004611afb818361229e565b885111611b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610332565b611b6f82600161229e565b9650945060019350611b8092505050565b9193909250565b606060008267ffffffffffffffff811115611ba457611ba4611eb6565b6040519080825280601f01601f191660200182016040528015611bce576020820181803683370190505b509050805160001415611be257905061091d565b6000611bee858761229e565b90506020820160005b611c026020876124eb565b811015611c395782518252611c1860208461229e565b9250611c2560208361229e565b915080611c31816123b9565b915050611bf7565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b6060610b4182611e5e565b606081611c7f81601f61229e565b1015611ce7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610332565b82611cf2838261229e565b1015611d5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610332565b611d64828461229e565b84511015611dce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610332565b606082158015611ded5760405191506000825260208201604052611e55565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611e26578051835260209283019201611e0e565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610b41826020015160008460000151611b87565b600060208284031215611e8657600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611eb157600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611f2c57611f2c611eb6565b604052919050565b600080600080600060a08688031215611f4c57600080fd5b611f5586611e8d565b94506020808701359450604087013567ffffffffffffffff8082168214611f7b57600080fd5b9094506060880135908115158214611f9257600080fd5b90935060808801359080821115611fa857600080fd5b818901915089601f830112611fbc57600080fd5b813581811115611fce57611fce611eb6565b611ffe847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ee5565b91508082528a8482850101111561201457600080fd5b80848401858401376000848284010152508093505050509295509295909350565b60008083601f84011261204757600080fd5b50813567ffffffffffffffff81111561205f57600080fd5b60208301915083602082850101111561207757600080fd5b9250929050565b60008060008060008060008060008060006101808c8e0312156120a057600080fd5b8b359a506120b060208d01611e8d565b99506120be60408d01611e8d565b985060608c0135975060808c0135965067ffffffffffffffff60a08d013511156120e757600080fd5b6120f78d60a08e01358e01612035565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2001121561213557600080fd5b60e08c01925067ffffffffffffffff6101608d0135111561215557600080fd5b6121668d6101608e01358e01612035565b81935080925050509295989b509295989b9093969950565b6000815180845260005b818110156121a457602081850181015186830182015201612188565b818111156121b6576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000610a2b60a083018461217e565b60006040828403121561223257600080fd5b6040516040810181811067ffffffffffffffff8211171561225557612255611eb6565b604052825181526020928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156122b1576122b161226f565b500190565b6000608082840312156122c857600080fd5b6040516080810181811067ffffffffffffffff821117156122eb576122eb611eb6565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261236760c083018461217e565b98975050505050505050565b6000828210156123855761238561226f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156123eb576123eb61226f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff831680612434576124346123f2565b8060ff84160691505092915050565b600060ff821660ff84168082101561245d5761245d61226f565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156124cd576124cd61226f565b500290565b6000602082840312156124e457600080fd5b5051919050565b6000826124fa576124fa6123f2565b50049056fea164736f6c634300080a000a", } // OptimismPortalABI is the input ABI used to generate the binding from. @@ -356,23 +356,23 @@ func (_OptimismPortal *OptimismPortalTransactorSession) DepositTransaction(_to c // FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. // -// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2Timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns() +func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2Timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _l2Timestamp, _outputRootProof, _withdrawalProof) } // FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. // -// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2Timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns() +func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2Timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _l2Timestamp, _outputRootProof, _withdrawalProof) } // FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36. // -// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _timestamp, _outputRootProof, _withdrawalProof) +// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2Timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns() +func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2Timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _l2Timestamp, _outputRootProof, _withdrawalProof) } // Receive is a paid mutator transaction binding the contract receive function. @@ -623,13 +623,14 @@ func (it *OptimismPortalWithdrawalFinalizedIterator) Close() error { // OptimismPortalWithdrawalFinalized represents a WithdrawalFinalized event raised by the OptimismPortal contract. type OptimismPortalWithdrawalFinalized struct { - Arg0 [32]byte - Raw types.Log // Blockchain specific contextual infos + Arg0 [32]byte + Success bool + Raw types.Log // Blockchain specific contextual infos } -// FilterWithdrawalFinalized is a free log retrieval operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// FilterWithdrawalFinalized is a free log retrieval operation binding the contract event 0xdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b. // -// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0, bool success) func (_OptimismPortal *OptimismPortalFilterer) FilterWithdrawalFinalized(opts *bind.FilterOpts, arg0 [][32]byte) (*OptimismPortalWithdrawalFinalizedIterator, error) { var arg0Rule []interface{} @@ -644,9 +645,9 @@ func (_OptimismPortal *OptimismPortalFilterer) FilterWithdrawalFinalized(opts *b return &OptimismPortalWithdrawalFinalizedIterator{contract: _OptimismPortal.contract, event: "WithdrawalFinalized", logs: logs, sub: sub}, nil } -// WatchWithdrawalFinalized is a free log subscription operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// WatchWithdrawalFinalized is a free log subscription operation binding the contract event 0xdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b. // -// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0, bool success) func (_OptimismPortal *OptimismPortalFilterer) WatchWithdrawalFinalized(opts *bind.WatchOpts, sink chan<- *OptimismPortalWithdrawalFinalized, arg0 [][32]byte) (event.Subscription, error) { var arg0Rule []interface{} @@ -686,9 +687,9 @@ func (_OptimismPortal *OptimismPortalFilterer) WatchWithdrawalFinalized(opts *bi }), nil } -// ParseWithdrawalFinalized is a log parse operation binding the contract event 0x894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f. +// ParseWithdrawalFinalized is a log parse operation binding the contract event 0xdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b. // -// Solidity: event WithdrawalFinalized(bytes32 indexed arg0) +// Solidity: event WithdrawalFinalized(bytes32 indexed arg0, bool success) func (_OptimismPortal *OptimismPortalFilterer) ParseWithdrawalFinalized(log types.Log) (*OptimismPortalWithdrawalFinalized, error) { event := new(OptimismPortalWithdrawalFinalized) if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { diff --git a/opnode/contracts/deposit/optimism_portal_deployed.go b/opnode/contracts/deposit/optimism_portal_deployed.go index 4f695d309cff..a1cad53d199c 100644 --- a/opnode/contracts/deposit/optimism_portal_deployed.go +++ b/opnode/contracts/deposit/optimism_portal_deployed.go @@ -2,4 +2,4 @@ // This file is a generated binding and any manual changes will be lost. package deposit -var OptimismPortalDeployedBin = "0x6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015e578063eecf1c3614610171578063ff61cc931461019157600080fd5b80621c2ff6146100935780639bf62d82146100f1578063a14238e71461011e57600080fd5b3661008e5761008c33346175306000604051806020016040528060008152506101d3565b005b600080fd5b34801561009f57600080fd5b506100c77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fd57600080fd5b506000546100c79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012a57600080fd5b5061014e610139366004611c41565b60016020526000908152604090205460ff1681565b60405190151581526020016100e8565b61008c61016c366004611cb2565b6101d3565b34801561017d57600080fd5b5061008c61018c366004611e18565b6102c2565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e8565b8180156101f5575073ffffffffffffffffffffffffffffffffffffffff851615155b1561022c576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3332811461024d575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102b2959493929190611f18565b60405180910390a3505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000840142101561031e576040517fe4750a3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401602060405180830381865afa1580156103ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d09190611fb4565b9050610424846040805182356020828101919091528301358183015290820135606082810191909152820135608082015260009060a001604051602081830303815290604052805190602001209050919050565b811461045c576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046d8d8d8d8d8d8d8d610648565b905061047f818660400135868661068a565b6104b5576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff1615151415610504576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508b6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008b73ffffffffffffffffffffffffffffffffffffffff168b8b908b8b60405161059b929190611fcd565b600060405180830381858888f193505050503d80600081146105d9576040519150601f19603f3d011682016040523d82523d6000602084013e6105de565b606091505b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17815560405191925083917f894485e328061b8d209b7dd043d2f613fc2892260497cadefac9a183962a990f9190a25050505050505050505050505050565b6000878787878787876040516020016106679796959493929190611fdd565b604051602081830303815290604052805190602001209050979650505050505050565b6000808560016040516020016106aa929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052925061077091016040516020818303038152906040526040518060400160405280600181526020017f010000000000000000000000000000000000000000000000000000000000000081525086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925061077a915050565b9695505050505050565b60008061078686610794565b9050610770818686866107c6565b606081805190602001206040516020016107b091815260200190565b6040516020818303038152906040529050919050565b60008060006107d68786866107f7565b915091508180156107ec57506107ec86826108f1565b979650505050505050565b6000606060006108068561090d565b90506000806000610818848a89610a08565b8151929550909350915015808061082c5750815b610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064015b60405180910390fd5b6000816108b357604051806020016040528060008152506108df565b6108df866108c2600188612099565b815181106108d2576108d26120b0565b6020026020010151610f25565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b6060600061091a83610f4f565b90506000815167ffffffffffffffff81111561093857610938611c83565b60405190808252806020026020018201604052801561097d57816020015b60408051808201909152606080825260208201528152602001906001900390816109565790505b50905060005b8251811015610a005760006109b08483815181106109a3576109a36120b0565b6020026020010151610f82565b905060405180604001604052808281526020016109cc83610f4f565b8152508383815181106109e1576109e16120b0565b60200260200101819052505080806109f8906120df565b915050610983565b509392505050565b60006060818080610a188761102c565b90506000869050600080610a3f604051806040016040528060608152602001606081525090565b60005b8c51811015610ee1578c8181518110610a5d57610a5d6120b0565b602002602001015191508284610a739190612118565b9350610a80600188612118565b965083610afe57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f742068617368000000000000000000000000000000604482015260640161088e565b610bef565b815151602011610b7a57815180516020909101208514610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c20686173680000000000604482015260640161088e565b84610b8883600001516111af565b14610bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f64652068617368000000000000604482015260640161088e565b610bfb60106001612118565b8260200151511415610c74578551841415610c1557610ee1565b6000868581518110610c2957610c296120b0565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610c5457610c546120b0565b60200260200101519050610c67816111d7565b9650600194505050610ecf565b60028260200151511415610e6d576000610c8d83611214565b9050600081600081518110610ca457610ca46120b0565b016020015160f81c90506000610cbb60028361215f565b610cc6906002612181565b90506000610cd7848360ff16611238565b90506000610ce58b8a611238565b90506000610cf3838361126e565b905060ff851660021480610d0a575060ff85166003145b15610d6057808351148015610d1f5750808251145b15610d3157610d2e818b612118565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b60ff85161580610d73575060ff85166001145b15610de55782518114610daf57507f80000000000000000000000000000000000000000000000000000000000000009950610ee1945050505050565b610dd68860200151600181518110610dc957610dc96120b0565b60200260200101516111d7565b9a509750610ecf945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f7072656669780000000000000000000000000000000000000000000000000000606482015260840161088e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e000000604482015260640161088e565b80610ed9816120df565b915050610a42565b507f8000000000000000000000000000000000000000000000000000000000000000841486610f108786611238565b909e909d50909b509950505050505050505050565b6020810151805160609161090791610f3f90600190612099565b815181106109a3576109a36120b0565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906109079061131a565b60606000806000610f928561154d565b919450925090506000816001811115610fad57610fad6121a4565b14611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161088e565b61102385602001518484611954565b95945050505050565b606060008251600261103e91906121d3565b67ffffffffffffffff81111561105657611056611c83565b6040519080825280601f01601f191660200182016040528015611080576020820181803683370190505b50905060005b83518110156111a85760048482815181106110a3576110a36120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826110d88360026121d3565b815181106110e8576110e86120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061112b5761112b6120b0565b016020015161113d919060f81c61215f565b60f81b8261114c8360026121d3565b611157906001612118565b81518110611167576111676120b0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806111a0816120df565b915050611086565b5092915050565b60006020825110156111c357506020015190565b818060200190518101906109079190611fb4565b600060606020836000015110156111f8576111f183611a33565b9050611204565b61120183610f82565b90505b61120d816111af565b9392505050565b606061090761123383602001516000815181106109a3576109a36120b0565b61102c565b6060825182106112575750604080516020810190915260008152610907565b61120d83838486516112699190612099565b611a3e565b6000805b8084511180156112825750808351115b8015611303575082818151811061129b5761129b6120b0565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106112da576112da6120b0565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561120d5780611312816120df565b915050611272565b60606000806113288461154d565b91935090915060019050816001811115611344576113446121a4565b146113ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161088e565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816113c45790505090506000835b8651811015611542576020821061148a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161088e565b6000806114c76040518060400160405280858c600001516114ab9190612099565b8152602001858c602001516114c09190612118565b905261154d565b5091509150604051806040016040528083836114e39190612118565b8152602001848b602001516114f89190612118565b81525085858151811061150d5761150d6120b0565b6020908102919091010152611523600185612118565b935061152f8183612118565b6115399084612118565b925050506113f1565b508152949350505050565b6000806000808460000151116115bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161088e565b6020840151805160001a607f81116115e457600060016000945094509450505061194d565b60b7811161167a5760006115f9608083612099565b905080876000015111611668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161088e565b6001955093506000925061194d915050565b60bf811161179d57600061168f60b783612099565b9050808760000151116116fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161088e565b600183015160208290036101000a90046117188183612118565b885111611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161088e565b61178c826001612118565b965094506000935061194d92505050565b60f781116118325760006117b260c083612099565b905080876000015111611821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161088e565b60019550935084925061194d915050565b600061183f60f783612099565b9050808760000151116118ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161088e565b600183015160208290036101000a90046118c88183612118565b885111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161088e565b61193c826001612118565b965094506001935061194d92505050565b9193909250565b606060008267ffffffffffffffff81111561197157611971611c83565b6040519080825280601f01601f19166020018201604052801561199b576020820181803683370190505b5090508051600014156119af57905061120d565b60006119bb8587612118565b90506020820160005b6119cf602087612210565b811015611a0657825182526119e5602084612118565b92506119f2602083612118565b9150806119fe816120df565b9150506119c4565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061090782611c2b565b606081611a4c81601f612118565b1015611ab4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b82611abf8382612118565b1015611b27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161088e565b611b318284612118565b84511015611b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161088e565b606082158015611bba5760405191506000825260208201604052611c22565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bf3578051835260209283019201611bdb565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610907826020015160008460000151611954565b600060208284031215611c5357600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c7e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a08688031215611cca57600080fd5b611cd386611c5a565b945060208601359350604086013567ffffffffffffffff8082168214611cf857600080fd5b9093506060870135908115158214611d0f57600080fd5b90925060808701359080821115611d2557600080fd5b818801915088601f830112611d3957600080fd5b813581811115611d4b57611d4b611c83565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611d9157611d91611c83565b816040528281528b6020848701011115611daa57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b60008083601f840112611de157600080fd5b50813567ffffffffffffffff811115611df957600080fd5b602083019150836020828501011115611e1157600080fd5b9250929050565b60008060008060008060008060008060006101808c8e031215611e3a57600080fd5b8b359a50611e4a60208d01611c5a565b9950611e5860408d01611c5a565b985060608c0135975060808c0135965067ffffffffffffffff60a08d01351115611e8157600080fd5b611e918d60a08e01358e01611dcf565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215611ecf57600080fd5b60e08c01925067ffffffffffffffff6101608d01351115611eef57600080fd5b611f008d6101608e01358e01611dcf565b81935080925050509295989b509295989b9093969950565b85815260006020868184015267ffffffffffffffff86166040840152841515606084015260a0608084015283518060a085015260005b81811015611f6a5785810183015185820160c001528201611f4e565b81811115611f7c57600060c083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160c001979650505050505050565b600060208284031215611fc657600080fd5b5051919050565b8183823760009101908152919050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015284608083015260c060a08301528260c0830152828460e0840137600060e0848401015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121115761211161206a565b5060010190565b6000821982111561212b5761212b61206a565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061217257612172612130565b8060ff84160691505092915050565b600060ff821660ff84168082101561219b5761219b61206a565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561220b5761220b61206a565b500290565b60008261221f5761221f612130565b50049056fea164736f6c634300080a000a" +var OptimismPortalDeployedBin = "0x6080604052600436106100685760003560e01c8063e9e05c4211610043578063e9e05c421461015f578063eecf1c3614610172578063ff61cc931461018557600080fd5b80621c2ff6146100945780639bf62d82146100f2578063a14238e71461011f57600080fd5b3661008f5761008d3334620186a06000604051806020016040528060008152506101c7565b005b600080fd5b3480156100a057600080fd5b506100c87f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100fe57600080fd5b506000546100c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561012b57600080fd5b5061014f61013a366004611e74565b60016020526000908152604090205460ff1681565b60405190151581526020016100e9565b61008d61016d366004611f34565b6101c7565b61008d61018036600461207e565b6102b6565b34801561019157600080fd5b506101b97f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e9565b8180156101e9575073ffffffffffffffffffffffffffffffffffffffff851615155b15610220576040517ff98844ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114610241575033731111000000000000000000000000000000001111015b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f019534888888886040516102a69594939291906121e9565b60405180910390a3505050505050565b73ffffffffffffffffffffffffffffffffffffffff891630141561033b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f742073656e64206d65737361676520746f2073656c662e0000000060448201526064015b60405180910390fd5b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa1580156103c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ec9190612220565b90507f0000000000000000000000000000000000000000000000000000000000000000816020015161041e919061229e565b4211610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f706f73616c206973206e6f74207965742066696e616c697a65642e00006044820152606401610332565b61049d610498368690038601866122b6565b6107c0565b8151146104d6576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061051c8d8d8d8d8d8d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061081c92505050565b905061056381866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061085b92505050565b610599576040517feb00eb2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001602081905260409091205460ff16151514156105e8576040517fae89945400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260016020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905561062e89614e2061229e565b5a10156106bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f496e73756666696369656e742067617320746f2066696e616c697a652077697460448201527f6864726177616c2e0000000000000000000000000000000000000000000000006064820152608401610332565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8e16178155604080516020601f8b01819004810282018101909252898152610742918e918d918f9186918f908f908190840183828082843760009201919091525061092492505050565b50600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906107a890841515815260200190565b60405180910390a25050505050505050505050505050565b600081600001518260200151836040015184606001516040516020016107ff949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60008686868686866040516020016108399695949392919061231c565b6040516020818303038152906040528051906020012090509695505050505050565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506109199101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529085876109af565b9150505b9392505050565b6000606060008060008661ffff1667ffffffffffffffff81111561094a5761094a611eb6565b6040519080825280601f01601f191660200182016040528015610974576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115610995578692505b828152826000602083013e90999098509650505050505050565b6000806109bb866109d3565b90506109c981868686610a05565b9695505050505050565b606081805190602001206040516020016109ef91815260200190565b6040516020818303038152906040529050919050565b6000806000610a15878686610a36565b91509150818015610a2b5750610a2b8682610b2b565b979650505050505050565b600060606000610a4585610b47565b90506000806000610a57848a89610c42565b81519295509093509150158080610a6b5750815b610ad1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610332565b600081610aed5760405180602001604052806000815250610b19565b610b1986610afc600188612373565b81518110610b0c57610b0c61238a565b602002602001015161115f565b919b919a509098505050505050505050565b6000818051906020012083805190602001201490505b92915050565b60606000610b5483611189565b90506000815167ffffffffffffffff811115610b7257610b72611eb6565b604051908082528060200260200182016040528015610bb757816020015b6040805180820190915260608082526020820152815260200190600190039081610b905790505b50905060005b8251811015610c3a576000610bea848381518110610bdd57610bdd61238a565b60200260200101516111bc565b90506040518060400160405280828152602001610c0683611189565b815250838381518110610c1b57610c1b61238a565b6020026020010181905250508080610c32906123b9565b915050610bbd565b509392505050565b60006060818080610c5287611266565b90506000869050600080610c79604051806040016040528060608152602001606081525090565b60005b8c5181101561111b578c8181518110610c9757610c9761238a565b602002602001015191508284610cad919061229e565b9350610cba60018861229e565b965083610d3857815180516020909101208514610d33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610332565b610e29565b815151602011610db457815180516020909101208514610d33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610332565b84610dc283600001516113e9565b14610e29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610332565b610e356010600161229e565b8260200151511415610eae578551841415610e4f5761111b565b6000868581518110610e6357610e6361238a565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610e8e57610e8e61238a565b60200260200101519050610ea181611411565b9650600194505050611109565b600282602001515114156110a7576000610ec783611447565b9050600081600081518110610ede57610ede61238a565b016020015160f81c90506000610ef5600283612421565b610f00906002612443565b90506000610f11848360ff1661146b565b90506000610f1f8b8a61146b565b90506000610f2d83836114a1565b905060ff851660021480610f44575060ff85166003145b15610f9a57808351148015610f595750808251145b15610f6b57610f68818b61229e565b99505b507f8000000000000000000000000000000000000000000000000000000000000000995061111b945050505050565b60ff85161580610fad575060ff85166001145b1561101f5782518114610fe957507f8000000000000000000000000000000000000000000000000000000000000000995061111b945050505050565b61101088602001516001815181106110035761100361238a565b6020026020010151611411565b9a509750611109945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610332565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610332565b80611113816123b9565b915050610c7c565b507f800000000000000000000000000000000000000000000000000000000000000084148661114a878661146b565b909e909d50909b509950505050505050505050565b60208101518051606091610b419161117990600190612373565b81518110610bdd57610bdd61238a565b604080518082018252600080825260209182015281518083019092528251825280830190820152606090610b419061154d565b606060008060006111cc85611780565b9194509250905060008160018111156111e7576111e7612466565b1461124e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610332565b61125d85602001518484611b87565b95945050505050565b60606000825160026112789190612495565b67ffffffffffffffff81111561129057611290611eb6565b6040519080825280601f01601f1916602001820160405280156112ba576020820181803683370190505b50905060005b83518110156113e25760048482815181106112dd576112dd61238a565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c82611312836002612495565b815181106113225761132261238a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106113655761136561238a565b0160200151611377919060f81c612421565b60f81b82611386836002612495565b61139190600161229e565b815181106113a1576113a161238a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806113da816123b9565b9150506112c0565b5092915050565b60006020825110156113fd57506020015190565b81806020019051810190610b4191906124d2565b600060606020836000015110156114325761142b83611c66565b905061143e565b61143b836111bc565b90505b61091d816113e9565b6060610b416114668360200151600081518110610bdd57610bdd61238a565b611266565b60608251821061148a5750604080516020810190915260008152610b41565b61091d838384865161149c9190612373565b611c71565b6000805b8084511180156114b55750808351115b801561153657508281815181106114ce576114ce61238a565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061150d5761150d61238a565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561091d5780611545816123b9565b9150506114a5565b606060008061155b84611780565b9193509091506001905081600181111561157757611577612466565b146115de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610332565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816115f75790505090506000835b865181101561177557602082106116bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610332565b6000806116fa6040518060400160405280858c600001516116de9190612373565b8152602001858c602001516116f3919061229e565b9052611780565b509150915060405180604001604052808383611716919061229e565b8152602001848b6020015161172b919061229e565b8152508585815181106117405761174061238a565b602090810291909101015261175660018561229e565b9350611762818361229e565b61176c908461229e565b92505050611624565b508152949350505050565b6000806000808460000151116117f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610332565b6020840151805160001a607f8111611817576000600160009450945094505050611b80565b60b781116118ad57600061182c608083612373565b90508087600001511161189b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610332565b60019550935060009250611b80915050565b60bf81116119d05760006118c260b783612373565b905080876000015111611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610332565b600183015160208290036101000a900461194b818361229e565b8851116119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610332565b6119bf82600161229e565b9650945060009350611b8092505050565b60f78111611a655760006119e560c083612373565b905080876000015111611a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610332565b600195509350849250611b80915050565b6000611a7260f783612373565b905080876000015111611ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610332565b600183015160208290036101000a9004611afb818361229e565b885111611b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610332565b611b6f82600161229e565b9650945060019350611b8092505050565b9193909250565b606060008267ffffffffffffffff811115611ba457611ba4611eb6565b6040519080825280601f01601f191660200182016040528015611bce576020820181803683370190505b509050805160001415611be257905061091d565b6000611bee858761229e565b90506020820160005b611c026020876124eb565b811015611c395782518252611c1860208461229e565b9250611c2560208361229e565b915080611c31816123b9565b915050611bf7565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b6060610b4182611e5e565b606081611c7f81601f61229e565b1015611ce7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610332565b82611cf2838261229e565b1015611d5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610332565b611d64828461229e565b84511015611dce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610332565b606082158015611ded5760405191506000825260208201604052611e55565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611e26578051835260209283019201611e0e565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610b41826020015160008460000151611b87565b600060208284031215611e8657600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611eb157600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611f2c57611f2c611eb6565b604052919050565b600080600080600060a08688031215611f4c57600080fd5b611f5586611e8d565b94506020808701359450604087013567ffffffffffffffff8082168214611f7b57600080fd5b9094506060880135908115158214611f9257600080fd5b90935060808801359080821115611fa857600080fd5b818901915089601f830112611fbc57600080fd5b813581811115611fce57611fce611eb6565b611ffe847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ee5565b91508082528a8482850101111561201457600080fd5b80848401858401376000848284010152508093505050509295509295909350565b60008083601f84011261204757600080fd5b50813567ffffffffffffffff81111561205f57600080fd5b60208301915083602082850101111561207757600080fd5b9250929050565b60008060008060008060008060008060006101808c8e0312156120a057600080fd5b8b359a506120b060208d01611e8d565b99506120be60408d01611e8d565b985060608c0135975060808c0135965067ffffffffffffffff60a08d013511156120e757600080fd5b6120f78d60a08e01358e01612035565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2001121561213557600080fd5b60e08c01925067ffffffffffffffff6101608d0135111561215557600080fd5b6121668d6101608e01358e01612035565b81935080925050509295989b509295989b9093969950565b6000815180845260005b818110156121a457602081850181015186830182015201612188565b818111156121b6576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000610a2b60a083018461217e565b60006040828403121561223257600080fd5b6040516040810181811067ffffffffffffffff8211171561225557612255611eb6565b604052825181526020928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156122b1576122b161226f565b500190565b6000608082840312156122c857600080fd5b6040516080810181811067ffffffffffffffff821117156122eb576122eb611eb6565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261236760c083018461217e565b98975050505050505050565b6000828210156123855761238561226f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156123eb576123eb61226f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff831680612434576124346123f2565b8060ff84160691505092915050565b600060ff821660ff84168082101561245d5761245d61226f565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156124cd576124cd61226f565b500290565b6000602082840312156124e457600080fd5b5051919050565b6000826124fa576124fa6123f2565b50049056fea164736f6c634300080a000a" diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index debff989b9fc..0a8488b7eaf5 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -185,7 +185,7 @@ func TestL2OutputSubmitter(t *testing.T) { require.Nil(t, err) require.Len(t, l2Output, 2) - require.Equal(t, l2Output[1][:], committedL2Output[:]) + require.Equal(t, l2Output[1][:], committedL2Output.OutputRoot[:]) break } diff --git a/ops/devnet-up.sh b/ops/devnet-up.sh index 6e59fa459804..5d83c9b7273b 100755 --- a/ops/devnet-up.sh +++ b/ops/devnet-up.sh @@ -81,9 +81,17 @@ else echo "Contracts already deployed, skipping." fi +function get_deployed_bytecode() { + echo $(jq -r .deployedBytecode ./packages/contracts/artifacts/contracts/$1) +} + # Pull out the necessary bytecode/addresses from the artifacts/deployments. -WITHDRAWER_BYTECODE=$(jq -r .deployedBytecode < ./packages/contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json) -L1_BLOCK_INFO_BYTECODE=$(jq -r .deployedBytecode < ./packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json) +L2_TO_L1_MESSAGE_PASSER_BYTECODE=$(get_deployed_bytecode L2/L2ToL1MessagePasser.sol/L2ToL1MessagePasser.json) +L2_CROSS_DOMAIN_MESSENGER_BYTECODE=$(get_deployed_bytecode L2/L2CrossDomainMessenger.sol/L2CrossDomainMessenger.json) +OPTIMISM_MINTABLE_TOKEN_FACTORY_BYTECODE=$(get_deployed_bytecode universal/OptimismMintableTokenFactory.sol/OptimismMintableTokenFactory.json) +L2_STANDARD_BRIDGE_BYTECODE=$(get_deployed_bytecode L2/L2StandardBridge.sol/L2StandardBridge.json) +L1_BLOCK_INFO_BYTECODE=$(get_deployed_bytecode L2/L1Block.sol/L1Block.json) + DEPOSIT_CONTRACT_ADDRESS=$(jq -r .address < ./packages/contracts/deployments/devnetL1/OptimismPortal.json) L2OO_ADDRESS=$(jq -r .address < ./packages/contracts/deployments/devnetL1/L2OutputOracle.json) @@ -91,8 +99,14 @@ L2OO_ADDRESS=$(jq -r .address < ./packages/contracts/deployments/devnetL1/L2Outp # since the replaced values will be the same. jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$L1_BLOCK_INFO_BYTECODE\"" < ./ops/genesis-l2.json | \ jq ". | .alloc.\"4200000000000000000000000000000000000015\".balance = \"0x0\"" | \ - jq ". | .alloc.\"4200000000000000000000000000000000000016\".code = \"$WITHDRAWER_BYTECODE\"" | \ - jq ". | .alloc.\"4200000000000000000000000000000000000016\".balance = \"0x0\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000000\".code = \"$L2_TO_L1_MESSAGE_PASSER_BYTECODE\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000000\".balance = \"0x0\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000007\".code = \"$L2_CROSS_DOMAIN_MESSENGER_BYTECODE\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000007\".balance = \"0x0\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000012\".code = \"$OPTIMISM_MINTABLE_TOKEN_FACTORY_BYTECODE\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000012\".balance = \"0x0\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000010\".code = \"$L2_STANDARD_BRIDGE_BYTECODE\"" | \ + jq ". | .alloc.\"4200000000000000000000000000000000000010\".balance = \"0x0\"" | \ jq ". | .timestamp = \"$GENESIS_TIMESTAMP\" " > ./.devnet/genesis-l2.json # Bring up L2. diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 8a288b6ac693..efc7704651ef 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,61 +1,88 @@ -DepositFeedTest:test_depositTransaction_ContractCreationReverts() (gas: 9290) -DepositFeedTest:test_depositTransaction_NoValueContract() (gas: 24388) -DepositFeedTest:test_depositTransaction_NoValueEOA() (gas: 24734) -DepositFeedTest:test_depositTransaction_createWithZeroValueForContract() (gas: 24451) -DepositFeedTest:test_depositTransaction_createWithZeroValueForEOA() (gas: 24707) -DepositFeedTest:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 31429) -DepositFeedTest:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 22859) -DepositFeedTest:test_depositTransaction_withEthValueFromContract() (gas: 31098) -DepositFeedTest:test_depositTransaction_withEthValueFromEOA() (gas: 31713) -L1BLockTest:test_basefee() (gas: 7531) -L1BLockTest:test_hash() (gas: 7530) -L1BLockTest:test_number() (gas: 7555) -L1BLockTest:test_sequenceNumber() (gas: 7577) -L1BLockTest:test_timestamp() (gas: 7587) -L1CrossDomainMessenger_Test:testCannot_pause() (gas: 10843) -L1CrossDomainMessenger_Test:test_blockAndUnblockSuccessfulMessage() (gas: 105412) -L1CrossDomainMessenger_Test:test_pause() (gas: 31793) -L1CrossDomainMessenger_Test:test_relayMessageBlockingAuth() (gas: 18542) -L1CrossDomainMessenger_Test:test_relayMessageInsideFraudProofWindow() (gas: 12305) -L1CrossDomainMessenger_Test:test_relayMessageSucceeds() (gas: 82425) -L1CrossDomainMessenger_Test:test_relayMessageToSystemContract() (gas: 30160) -L1CrossDomainMessenger_Test:test_relayRevertOnBlockedMessage() (gas: 55761) -L1CrossDomainMessenger_Test:test_relayShouldRevertIfPaused() (gas: 41560) -L1CrossDomainMessenger_Test:test_relayShouldRevertSendingSameMessageTwice() (gas: 188) -L1CrossDomainMessenger_Test:test_revertOnInvalidOutputRootProof() (gas: 16067) -L1CrossDomainMessenger_Test:test_sendMessage() (gas: 44041) -L1CrossDomainMessenger_Test:test_sendMessageTwice() (gas: 49061) -L1CrossDomainMessenger_Test:test_xDomainMessageSenderResets() (gas: 81565) -L1StandardBridge_Test:test_L1BridgeSetsPortalAndL2Bridge() (gas: 14825) -L2CrossDomainMessenger_Test:test_L2MessengerCallsTarget() (gas: 64095) -L2CrossDomainMessenger_Test:test_L2MessengerCannotCallL2MessagePasser() (gas: 42128) -L2CrossDomainMessenger_Test:test_L2MessengerCannotRelaySameMessageTwice() (gas: 67491) -L2CrossDomainMessenger_Test:test_L2MessengerCorrectL1Messenger() (gas: 9762) -L2CrossDomainMessenger_Test:test_L2MessengerRevertInvalidL1XDomainMessenger() (gas: 11535) -L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122584) -L2CrossDomainMessenger_Test:test_L2MessengerSendSameMessageTwice() (gas: 162903) -L2CrossDomainMessenger_Test:test_L2MessengerXDomainMessageSenderReset() (gas: 69285) -L2CrossDomainMessenger_Test:test_L2MessengerxDomainMsgSender() (gas: 11159) -L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 18605) -L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 16724) -L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 18642) -L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 16088) +CrossDomainHashing_Test:test_l2TransactionHash() (gas: 78639) +L1BLockTest:test_basefee() (gas: 7575) +L1BLockTest:test_hash() (gas: 7552) +L1BLockTest:test_number() (gas: 7651) +L1BLockTest:test_sequenceNumber() (gas: 7585) +L1BLockTest:test_timestamp() (gas: 7661) +L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 10909) +L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 8343) +L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 31882) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 61062) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 44727) +L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 41564) +L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 74867) +L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 66341) +L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 10565) +L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 58335) +L1StandardBridge_Test:test_depositERC20() (gas: 373162) +L1StandardBridge_Test:test_depositERC20To() (gas: 374939) +L1StandardBridge_Test:test_depositETH() (gas: 106067) +L1StandardBridge_Test:test_depositETHTo() (gas: 112908) +L1StandardBridge_Test:test_donateETH() (gas: 17500) +L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 438858) +L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 47952) +L1StandardBridge_Test:test_initialize() (gas: 14863) +L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 12085) +L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 30637) +L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 23521) +L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 22853) +L1StandardBridge_Test:test_receive() (gas: 100261) +L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10865) +L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8387) +L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31792) +L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57407) +L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 24523) +L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41511) +L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 116411) +L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133114) +L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10587) +L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54749) +L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 18627) +L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 16734) +L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 18708) +L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 16458) L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 18893) -L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 11048) -L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 16287) -L2OutputOracleTest:testCannot_deleteL2Output_ifWrongOutput() (gas: 23243) -L2OutputOracleTest:test_appendingAnotherOutput() (gas: 47332) +L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 11093) +L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18793) +L2OutputOracleTest:testCannot_deleteWrongL2Output() (gas: 77307) +L2OutputOracleTest:test_appendingAnotherOutput() (gas: 68605) L2OutputOracleTest:test_computeL2BlockNumber() (gas: 15003) -L2OutputOracleTest:test_deleteL2Output() (gas: 30647) -L2OutputOracleTest:test_getL2Output() (gas: 15071) -L2OutputOracleTest:test_latestBlockTimestamp() (gas: 9699) -L2OutputOracleTest:test_nextTimestamp() (gas: 12031) -L2OutputOracleTest_Constructor:test_constructor() (gas: 29173) -L2StandardBridge_Test:test_L2BridgeCorrectL1Bridge() (gas: 9726) -OptimismPortal_Test:test_receive_withEthValueFromEOA() (gas: 21979) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyInvalidProof() (gas: 37418) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_cannotVerifyRecentWithdrawal() (gas: 33219) -WithdrawalsRelay_finalizeWithdrawalTransaction_Test:test_verifyWithdrawal() (gas: 190048) -WithdawerBurnTest:test_burn() (gas: 50276) -WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromContract() (gas: 71990) -WithdrawerTestInitiateWithdrawal:test_initiateWithdrawal_fromEOA() (gas: 72475) +L2OutputOracleTest:test_constructor() (gas: 33752) +L2OutputOracleTest:test_deleteL2Output() (gas: 64320) +L2OutputOracleTest:test_getL2Output() (gas: 74601) +L2OutputOracleTest:test_latestBlockTimestamp() (gas: 68377) +L2OutputOracleTest:test_nextTimestamp() (gas: 9236) +L2StandardBridge_Test:test_finalizeDeposit() (gas: 97520) +L2StandardBridge_Test:test_initialize() (gas: 14812) +L2StandardBridge_Test:test_receive() (gas: 137222) +L2StandardBridge_Test:test_withdraw() (gas: 353410) +L2StandardBridge_Test:test_withdrawTo() (gas: 354225) +L2ToL1MessagePasserTest:test_burn() (gas: 112001) +L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67935) +L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74851) +OptimismMintableTokenFactory_Test:test_bridge() (gas: 9850) +OptimismMintableTokenFactory_Test:test_burn() (gas: 52791) +OptimismMintableTokenFactory_Test:test_burnRevertsFromNotBridge() (gas: 13211) +OptimismMintableTokenFactory_Test:test_l1Token() (gas: 9779) +OptimismMintableTokenFactory_Test:test_l2Bridge() (gas: 9768) +OptimismMintableTokenFactory_Test:test_mint() (gas: 65732) +OptimismMintableTokenFactory_Test:test_mintRevertsFromNotBridge() (gas: 13213) +OptimismMintableTokenFactory_Test:test_remoteToken() (gas: 9762) +OptimismMintableTokenFactory_Test:test_bridge() (gas: 9772) +OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1106538) +OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2193987) +OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9374) +OptimismMintableTokenFactory_Test:test_initializeShouldRevert() (gas: 12696) +OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 11302) +OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 9399) +OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 24797) +OptimismPortal_Test:test_cannotVerifyRecentWithdrawal() (gas: 19657) +OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 24478) +OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 24824) +OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 24497) +OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 24841) +OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 31519) +OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 22949) +OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 31188) +OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 31804) +OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 26565) diff --git a/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol b/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol new file mode 100644 index 000000000000..78634938bd30 --- /dev/null +++ b/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { OptimismPortal } from "./OptimismPortal.sol"; +import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol"; + +/** + * @title L1CrossDomainMessenger + * @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages + * from L2 onto L1. + * This contract should be deployed behind an upgradable proxy + */ +contract L1CrossDomainMessenger is CrossDomainMessenger { + /************* + * Variables * + *************/ + + /** + * @notice Address of the OptimismPortal. + */ + OptimismPortal public portal; + + /******************** + * Public Functions * + ********************/ + + /** + * @notice Initialize the L1CrossDomainMessenger + * @param _portal The OptimismPortal + */ + function initialize(OptimismPortal _portal) external { + portal = _portal; + + address[] memory blockedSystemAddresses = new address[](1); + blockedSystemAddresses[0] = address(this); + + _initialize(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, blockedSystemAddresses); + } + + /********************** + * Internal Functions * + **********************/ + + /** + * @notice Ensure that the L1CrossDomainMessenger can only be called + * by the OptimismPortal and the L2 sender is the L2CrossDomainMessenger. + */ + function _isSystemMessageSender() internal view override returns (bool) { + return msg.sender == address(portal) && portal.l2Sender() == otherMessenger; + } + + /** + * @notice Sending a message in the L1CrossDomainMessenger involves + * depositing through the OptimismPortal. + */ + function _sendMessage( + address _to, + uint64 _gasLimit, + uint256 _value, + bytes memory _data + ) internal override { + portal.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data); + } +} diff --git a/packages/contracts/contracts/L1/L1StandardBridge.sol b/packages/contracts/contracts/L1/L1StandardBridge.sol new file mode 100644 index 000000000000..7ac3b80b1e58 --- /dev/null +++ b/packages/contracts/contracts/L1/L1StandardBridge.sol @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { StandardBridge } from "../universal/StandardBridge.sol"; + +/** + * @title L1StandardBridge + * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard + * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits + * and listening to it for newly finalized withdrawals. + */ +contract L1StandardBridge is StandardBridge { + /********** + * Events * + **********/ + + event ETHDepositInitiated( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ETHWithdrawalFinalized( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ERC20DepositInitiated( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event ERC20WithdrawalFinalized( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + /******************** + * Public Functions * + ********************/ + + /** + * @dev initialize the L1StandardBridge with the address of the + * messenger in the same domain + */ + function initialize(address payable _messenger) public { + _initialize(_messenger, payable(Lib_PredeployAddresses.L2_STANDARD_BRIDGE)); + } + + /** + * @dev Get the address of the corresponding L2 bridge contract. + * This is a legacy getter, provided for backwards compatibility. + * @return Address of the corresponding L2 bridge contract. + */ + function l2TokenBridge() external returns (address) { + return address(otherBridge); + } + + /** + * @dev Deposit an amount of the ETH to the caller's balance on L2. + * @param _minGasLimit limit required to complete the deposit on L2. + * @param _data Optional data to forward to L2. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function depositETH(uint32 _minGasLimit, bytes calldata _data) external payable onlyEOA { + _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _data); + } + + /** + * @dev Deposit an amount of ETH to a recipient's balance on L2. + * @param _to L2 address to credit the withdrawal to. + * @param _minGasLimit Gas limit required to complete the deposit on L2. + * @param _data Optional data to forward to L2. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function depositETHTo( + address _to, + uint32 _minGasLimit, + bytes calldata _data + ) external payable { + _initiateETHDeposit(msg.sender, _to, _minGasLimit, _data); + } + + /** + * @dev deposit an amount of the ERC20 to the caller's balance on L2. + * @param _l1Token Address of the L1 ERC20 we are depositing + * @param _l2Token Address of the L1 respective L2 ERC20 + * @param _amount Amount of the ERC20 to deposit + * @param _minGasLimit limit required to complete the deposit on L2. + * @param _data Optional data to forward to L2. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function depositERC20( + address _l1Token, + address _l2Token, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) external virtual onlyEOA { + _initiateERC20Deposit( + _l1Token, + _l2Token, + msg.sender, + msg.sender, + _amount, + _minGasLimit, + _data + ); + } + + /** + * @dev deposit an amount of ERC20 to a recipient's balance on L2. + * @param _l1Token Address of the L1 ERC20 we are depositing + * @param _l2Token Address of the L1 respective L2 ERC20 + * @param _to L2 address to credit the withdrawal to. + * @param _amount Amount of the ERC20 to deposit. + * @param _minGasLimit Gas limit required to complete the deposit on L2. + * @param _data Optional data to forward to L2. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function depositERC20To( + address _l1Token, + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) external virtual { + _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _minGasLimit, _data); + } + + function finalizeETHWithdrawal( + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external payable onlyOtherBridge { + emit ETHWithdrawalFinalized(_from, _to, _amount, _data); + finalizeBridgeETH(_from, _to, _amount, _data); + } + + /** + * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the + * L1 ERC20 token. + * This call will fail if the initialized withdrawal from L2 has not been finalized. + * + * @param _l1Token Address of L1 token to finalizeWithdrawal for. + * @param _l2Token Address of L2 token where withdrawal was initiated. + * @param _from L2 address initiating the transfer. + * @param _to L1 address to credit the withdrawal to. + * @param _amount Amount of the ERC20 to deposit. + * @param _data Data provided by the sender on L2. This data is provided + * solely as a convenience for external contracts. Aside from enforcing a maximum + * length, these contracts provide no guarantees about its content. + */ + function finalizeERC20Withdrawal( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external onlyOtherBridge { + emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); + finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _data); + } + + /********************** + * Internal Functions * + **********************/ + + function _initiateETHDeposit( + address _from, + address _to, + uint32 _minGasLimit, + bytes memory _data + ) internal { + emit ETHDepositInitiated(_from, _to, msg.value, _data); + _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _data); + } + + function _initiateERC20Deposit( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) internal { + emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data); + _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _data); + } +} diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index d1bb474a9f26..c3703ce44d2c 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -1,14 +1,14 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -/* Library Imports */ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title L2OutputOracle - * @notice + * @notice The L2 state is committed to in this contract + * The payable keyword is used on appendL2Output to save gas on the msg.value check. + * This contract should be deployed behind an upgradable proxy */ -// The payable keyword is used on appendL2Output to save gas on the msg.value check. // slither-disable-next-line locked-ether contract L2OutputOracle is Ownable { /********** @@ -16,10 +16,18 @@ contract L2OutputOracle is Ownable { **********/ /// @notice Emitted when an output is appended. - event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + event l2OutputAppended( + bytes32 indexed _l2Output, + uint256 indexed _l1Timestamp, + uint256 indexed _l2timestamp + ); /// @notice Emitted when an output is deleted. - event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + event l2OutputDeleted( + bytes32 indexed _l2Output, + uint256 indexed _l1Timestamp, + uint256 indexed _l2timestamp + ); /********************** * Contract Variables * @@ -41,7 +49,16 @@ contract L2OutputOracle is Ownable { uint256 public latestBlockTimestamp; /// @notice A mapping from L2 timestamps to the output root for the block with that timestamp. - mapping(uint256 => bytes32) internal l2Outputs; + mapping(uint256 => OutputProposal) internal l2Outputs; + + /// @notice OutputProposal represents a commitment to the L2 state. + /// The timestamp is the L1 timestamp that the output root is posted. + /// This timestamp is used to verify that the finalization period + /// has passed since the output root was submitted. + struct OutputProposal { + bytes32 outputRoot; + uint256 timestamp; + } /*************** * Constructor * @@ -72,10 +89,13 @@ contract L2OutputOracle is Ownable { SUBMISSION_INTERVAL = _submissionInterval; L2_BLOCK_TIME = _l2BlockTime; - l2Outputs[_startingBlockTimestamp] = _genesisL2Output; // solhint-disable not-rely-on-time + // solhint-disable-next-line not-rely-on-time + l2Outputs[_startingBlockTimestamp] = OutputProposal(_genesisL2Output, block.timestamp); HISTORICAL_TOTAL_BLOCKS = _historicalTotalBlocks; - latestBlockTimestamp = _startingBlockTimestamp; // solhint-disable not-rely-on-time - STARTING_BLOCK_TIMESTAMP = _startingBlockTimestamp; // solhint-disable not-rely-on-time + // solhint-disable-next-line not-rely-on-time + latestBlockTimestamp = _startingBlockTimestamp; + // solhint-disable-next-line not-rely-on-time + STARTING_BLOCK_TIMESTAMP = _startingBlockTimestamp; _transferOwnership(sequencer); } @@ -119,21 +139,30 @@ contract L2OutputOracle is Ownable { ); } - l2Outputs[_l2timestamp] = _l2Output; + l2Outputs[_l2timestamp] = OutputProposal(_l2Output, block.timestamp); latestBlockTimestamp = _l2timestamp; - emit l2OutputAppended(_l2Output, _l2timestamp); + emit l2OutputAppended(_l2Output, block.timestamp, _l2timestamp); } /** * @notice Deletes the most recent output. - * @param _l2Output The value of the most recent output. Used to prevent erroneously deleting - * the wrong root + * @param _proposal Represents the output proposal to delete */ - function deleteL2Output(bytes32 _l2Output) external onlyOwner { - bytes32 outputToDelete = l2Outputs[latestBlockTimestamp]; - require(_l2Output == outputToDelete, "Can only delete the most recent output."); - emit l2OutputDeleted(outputToDelete, latestBlockTimestamp); + function deleteL2Output(OutputProposal memory _proposal) external onlyOwner { + OutputProposal memory outputToDelete = l2Outputs[latestBlockTimestamp]; + + require( + _proposal.outputRoot == outputToDelete.outputRoot, + "Can only delete the most recent output." + ); + require(_proposal.timestamp == outputToDelete.timestamp, ""); + + emit l2OutputDeleted( + outputToDelete.outputRoot, + outputToDelete.timestamp, + latestBlockTimestamp + ); delete l2Outputs[latestBlockTimestamp]; latestBlockTimestamp = latestBlockTimestamp - SUBMISSION_INTERVAL; @@ -147,11 +176,11 @@ contract L2OutputOracle is Ownable { } /** - * @notice Returns the L2 output root given a target L2 block timestamp. Returns 0 if none is - * found. + * @notice Returns the L2 output proposal given a target L2 block timestamp. + * Returns a null output proposal if none is found. * @param _l2Timestamp The L2 block timestamp of the target block. */ - function getL2Output(uint256 _l2Timestamp) external view returns (bytes32) { + function getL2Output(uint256 _l2Timestamp) external view returns (OutputProposal memory) { return l2Outputs[_l2Timestamp]; } diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts/contracts/L1/OptimismPortal.sol index d3fb9b0cfa2a..a0656cde315f 100644 --- a/packages/contracts/contracts/L1/OptimismPortal.sol +++ b/packages/contracts/contracts/L1/OptimismPortal.sol @@ -1,32 +1,111 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -/* Inherited Imports */ -import { DepositFeed } from "./abstracts/DepositFeed.sol"; -import { WithdrawalsRelay } from "./abstracts/WithdrawalsRelay.sol"; - -/* Interactions Imports */ import { L2OutputOracle } from "./L2OutputOracle.sol"; +import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; +import { ExcessivelySafeCall } from "../libraries/ExcessivelySafeCall.sol"; /** * @title OptimismPortal - * @notice The OptimismPortal is a contract on L1 used to deposit and withdraw between L2 and L1. - * The OptimismPortal must inherit from both the DepositFeed and WithdrawalsRelay as it holds the - * pool of ETH which is deposited to and withdrawn from L2. Aside from affecting the ETH balance, - * the deposit and withdrawal codepaths should be independent from one another. + * This contract should be deployed behind an upgradable proxy. */ -contract OptimismPortal is DepositFeed, WithdrawalsRelay { +contract OptimismPortal { + /********** + * Errors * + **********/ + + /** + * @notice Error emitted when the output root proof is invalid. + */ + error InvalidOutputRootProof(); + + /** + * @notice Error emitted when the withdrawal inclusion proof is invalid. + */ + error InvalidWithdrawalInclusionProof(); + + /** + * @notice Error emitted when a withdrawal has already been finalized. + */ + error WithdrawalAlreadyFinalized(); + + /** + * @notice Error emitted on deposits which create a new contract with a non-zero target. + */ + error NonZeroCreationTarget(); + + /********** + * Events * + **********/ + + /** + * @notice Emitted when a Transaction is deposited from L1 to L2. The parameters of this + * event are read by the rollup node and used to derive deposit transactions on L2. + */ + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 mint, + uint256 value, + uint64 gasLimit, + bool isCreation, + bytes data + ); + + /** + * @notice Emitted when a withdrawal is finalized + */ + event WithdrawalFinalized(bytes32 indexed, bool success); + + /************* + * Constants * + *************/ + + /** + * @notice Value used to reset the l2Sender, this is more efficient than setting it to zero. + */ + address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; + + /************* + * Variables * + *************/ + + /** + * @notice Minimum time that must elapse before a withdrawal can be finalized. + */ + uint256 public immutable FINALIZATION_PERIOD; + + /** + * @notice Address of the L2OutputOracle. + */ + L2OutputOracle public immutable L2_ORACLE; + + /** + * @notice Public variable which can be used to read the address of the L2 account which + * initated the withdrawal. Can also be used to determine whether or not execution is occuring + * downstream of a call to finalizeWithdrawalTransaction(). + */ + address public l2Sender = DEFAULT_L2_SENDER; + + /** + * @notice A list of withdrawal hashes which have been successfully finalized. + * Used for replay protection. + */ + mapping(bytes32 => bool) public finalizedWithdrawals; + /*************** * Constructor * ***************/ - constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) - WithdrawalsRelay(_l2Oracle, _finalizationPeriod) - {} + constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) { + L2_ORACLE = _l2Oracle; + FINALIZATION_PERIOD = _finalizationPeriod; + } - /********************** - * External Functions * - **********************/ + /******************** + * Public Functions * + ********************/ /** * @notice Accepts value so that users can send ETH directly to this contract and @@ -35,6 +114,132 @@ contract OptimismPortal is DepositFeed, WithdrawalsRelay { * depositTransaction() function directly. */ receive() external payable { - depositTransaction(msg.sender, msg.value, 30000, false, bytes("")); + depositTransaction(msg.sender, msg.value, 100000, false, bytes("")); + } + + /** + * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in + * deriving deposit transactions. + * @param _to The L2 destination address. + * @param _value The ETH value to send in the deposit transaction. + * @param _gasLimit The L2 gasLimit. + * @param _isCreation Whether or not the transaction should be contract creation. + * @param _data The input data. + */ + function depositTransaction( + address _to, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) public payable { + // Differentiate between sending to address(0) + // and creating a contract + if (_isCreation && _to != address(0)) { + revert NonZeroCreationTarget(); + } + + address from = msg.sender; + // Transform the from-address to its alias if the caller is a contract. + if (msg.sender != tx.origin) { + from = AddressAliasHelper.applyL1ToL2Alias(msg.sender); + } + + emit TransactionDeposited(from, _to, msg.value, _value, _gasLimit, _isCreation, _data); + } + + /** + * @notice Finalizes a withdrawal transaction. + * @param _nonce Nonce for the provided message. + * @param _sender Message sender address on L2. + * @param _target Target address on L1. + * @param _value ETH to send to the target. + * @param _gasLimit Gas to be forwarded to the target. + * @param _data Data to send to the target. + * @param _l2Timestamp L2 timestamp of the outputRoot. + * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. + * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. + */ + function finalizeWithdrawalTransaction( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes calldata _data, + uint256 _l2Timestamp, + WithdrawalVerifier.OutputRootProof calldata _outputRootProof, + bytes calldata _withdrawalProof + ) external payable { + // Prevent reentrency + require(_target != address(this), "Cannot send message to self."); + + // Get the output root. + L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2Timestamp); + + // Ensure that enough time has passed since the proposal was submitted + // before allowing a withdrawal. A fault proof should be submitted + // before this check is allowed to pass. + require( + block.timestamp > proposal.timestamp + FINALIZATION_PERIOD, + "Proposal is not yet finalized." + ); + + // Verify that the output root can be generated with the elements in the proof. + if (proposal.outputRoot != WithdrawalVerifier._deriveOutputRoot(_outputRootProof)) { + revert InvalidOutputRootProof(); + } + + // Verify that the hash of the withdrawal transaction's arguments are included in the + // storage hash of the withdrawer contract. + bytes32 withdrawalHash = WithdrawalVerifier.withdrawalHash( + _nonce, + _sender, + _target, + _value, + _gasLimit, + _data + ); + + // Verify proof that a withdrawal on L2 was initated + if ( + WithdrawalVerifier._verifyWithdrawalInclusion( + withdrawalHash, + _outputRootProof.withdrawerStorageRoot, + _withdrawalProof + ) == false + ) { + revert InvalidWithdrawalInclusionProof(); + } + + // Check that this withdrawal has not already been finalized. + if (finalizedWithdrawals[withdrawalHash] == true) { + revert WithdrawalAlreadyFinalized(); + } + + // Set the withdrawal as finalized + finalizedWithdrawals[withdrawalHash] = true; + + // Save enough gas so that the call cannot use up all of the gas + require(gasleft() >= _gasLimit + 20000, "Insufficient gas to finalize withdrawal."); + + // Set the l2Sender so that other contracts can know which account + // on L2 is making the withdrawal + l2Sender = _sender; + // Make the call and ensure that a contract cannot out of gas + // us by returning a huge amount of data + (bool success, ) = ExcessivelySafeCall.excessivelySafeCall( + _target, + _gasLimit, + _value, + 0, + _data + ); + // Be sure to reset the l2Sender + l2Sender = DEFAULT_L2_SENDER; + + // All withdrawals are immediately finalized. Replayability can + // be achieved through contracts built on top of this contract + emit WithdrawalFinalized(withdrawalHash, success); } } diff --git a/packages/contracts/contracts/L1/abstracts/DepositFeed.sol b/packages/contracts/contracts/L1/abstracts/DepositFeed.sol deleted file mode 100644 index 46b040d09f49..000000000000 --- a/packages/contracts/contracts/L1/abstracts/DepositFeed.sol +++ /dev/null @@ -1,73 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.10; - -import { IDepositFeed } from "./IDepositFeed.sol"; - -/* Library Imports */ -import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; - -/** - * @title DepositFeed - * @notice Implements the logic for depositing from L1 to L2. - */ -abstract contract DepositFeed is IDepositFeed { - /********** - * Errors * - **********/ - - /** - * @notice Error emitted on deposits which create a new contract with a non-zero target. - */ - error NonZeroCreationTarget(); - - /********** - * Events * - **********/ - - /** - * @notice Emitted when a Transaction is deposited from L1 to L2. The parameters of this - * event are read by the rollup node and used to derive deposit transactions on L2. - */ - event TransactionDeposited( - address indexed from, - address indexed to, - uint256 mint, - uint256 value, - uint64 gasLimit, - bool isCreation, - bytes data - ); - - /********************** - * External Functions * - **********************/ - - /** - * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in - * deriving deposit transactions. - * @param _to The L2 destination address. - * @param _value The ETH value to send in the deposit transaction. - * @param _gasLimit The L2 gasLimit. - * @param _isCreation Whether or not the transaction should be contract creation. - * @param _data The input data. - */ - function depositTransaction( - address _to, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes memory _data - ) public payable { - if (_isCreation && _to != address(0)) { - revert NonZeroCreationTarget(); - } - - address from = msg.sender; - // Transform the from-address to its alias if the caller is a contract. - if (msg.sender != tx.origin) { - from = AddressAliasHelper.applyL1ToL2Alias(msg.sender); - } - - emit TransactionDeposited(from, _to, msg.value, _value, _gasLimit, _isCreation, _data); - } -} diff --git a/packages/contracts/contracts/L1/abstracts/IDepositFeed.sol b/packages/contracts/contracts/L1/abstracts/IDepositFeed.sol deleted file mode 100644 index e61662a3a336..000000000000 --- a/packages/contracts/contracts/L1/abstracts/IDepositFeed.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.8.10; - -interface IDepositFeed { - function depositTransaction( - address _to, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes memory _data - ) external payable; -} diff --git a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol b/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol deleted file mode 100644 index 22309967b75d..000000000000 --- a/packages/contracts/contracts/L1/abstracts/WithdrawalsRelay.sol +++ /dev/null @@ -1,154 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.10; - -/* Interactions Imports */ -import { L2OutputOracle } from "../L2OutputOracle.sol"; - -/* Library Imports */ -import { WithdrawalVerifier } from "../../libraries/Lib_WithdrawalVerifier.sol"; - -/** - * @title WithdrawalsRelay - * @notice The WithdrawalsRelay is inherited by the OptimismPortal on L1, and faciliates finalizing - * withdrawals between L2 and L1. - */ -abstract contract WithdrawalsRelay { - /********** - * Errors * - **********/ - - /// @notice Error emitted when attempting to finalize a withdrawal too early. - error NotYetFinal(); - - /// @notice Error emitted when the output root proof is invalid. - error InvalidOutputRootProof(); - - /// @notice Error emitted when the withdrawal inclusion proof is invalid. - error InvalidWithdrawalInclusionProof(); - - /// @notice Error emitted when a withdrawal has already been finalized. - error WithdrawalAlreadyFinalized(); - - /********** - * Events * - **********/ - - /// @notice Emitted when a withdrawal is finalized - event WithdrawalFinalized(bytes32 indexed); - - /// @notice Value used to reset the l2Sender, this is more efficient than setting it to zero. - address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; - - /********************** - * Contract Variables * - **********************/ - - /// @notice Minimum time that must elapse before a withdrawal can be finalized. - uint256 public immutable FINALIZATION_PERIOD; - - /// @notice Address of the L2OutputOracle. - L2OutputOracle public immutable L2_ORACLE; - - /** - * @notice Public variable which can be used to read the address of the L2 account which - * initated the withdrawal. Can also be used to determine whether or not execution is occuring - * downstream of a call to finalizeWithdrawalTransaction(). - */ - address public l2Sender = DEFAULT_L2_SENDER; - - /** - * @notice A list of withdrawal hashes which have been successfully finalized. - * Used for replay protection. - */ - mapping(bytes32 => bool) public finalizedWithdrawals; - - /*************** - * Constructor * - ***************/ - - constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) { - L2_ORACLE = _l2Oracle; - FINALIZATION_PERIOD = _finalizationPeriod; - } - - /********************** - * External Functions * - **********************/ - - /** - * @notice Finalizes a withdrawal transaction. - * @param _nonce Nonce for the provided message. - * @param _sender Message sender address on L2. - * @param _target Target address on L1. - * @param _value ETH to send to the target. - * @param _gasLimit Gas to be forwarded to the target. - * @param _data Data to send to the target. - * @param _timestamp L2 timestamp of the outputRoot. - * @param _outputRootProof Inclusion proof of the withdrawer contracts storage root. - * @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract. - */ - function finalizeWithdrawalTransaction( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes calldata _data, - uint256 _timestamp, - WithdrawalVerifier.OutputRootProof calldata _outputRootProof, - bytes calldata _withdrawalProof - ) external { - // Check that the timestamp is sufficiently finalized. - // The timestamp corresponds to a particular L2 output, - // so it is safe to be passed in by a user. - unchecked { - if (block.timestamp < _timestamp + FINALIZATION_PERIOD) { - revert NotYetFinal(); - } - } - - // Get the output root. - bytes32 outputRoot = L2_ORACLE.getL2Output(_timestamp); - - // Verify that the output root can be generated with the elements in the proof. - if (outputRoot != WithdrawalVerifier._deriveOutputRoot(_outputRootProof)) { - revert InvalidOutputRootProof(); - } - - // Verify that the hash of the withdrawal transaction's arguments are included in the - // storage hash of the withdrawer contract. - bytes32 withdrawalHash = WithdrawalVerifier._deriveWithdrawalHash( - _nonce, - _sender, - _target, - _value, - _gasLimit, - _data - ); - if ( - WithdrawalVerifier._verifyWithdrawalInclusion( - withdrawalHash, - _outputRootProof.withdrawerStorageRoot, - _withdrawalProof - ) == false - ) { - revert InvalidWithdrawalInclusionProof(); - } - - // Check that this withdrawal has not already been finalized. - if (finalizedWithdrawals[withdrawalHash] == true) { - revert WithdrawalAlreadyFinalized(); - } - finalizedWithdrawals[withdrawalHash] = true; - - l2Sender = _sender; - // Make the call. - (bool s, ) = _target.call{ value: _value, gas: _gasLimit }(_data); - s; // Silence the compiler's "Return value of low-level calls not used" warning. - l2Sender = DEFAULT_L2_SENDER; - - // All withdrawals are immediately finalized. If the ability to replay a transaction is - // required, that support can be provided in external contracts. - emit WithdrawalFinalized(withdrawalHash); - } -} diff --git a/packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol b/packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol deleted file mode 100644 index b3ef8e0c578d..000000000000 --- a/packages/contracts/contracts/L1/messaging/IL1CrossDomainMessenger.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* Library Imports */ -import { Lib_OVMCodec } from "@eth-optimism/contracts/libraries/codec/Lib_OVMCodec.sol"; - -/* Interface Imports */ -import { - ICrossDomainMessenger -} from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol"; - -/** - * @title IL1CrossDomainMessenger - */ -interface IL1CrossDomainMessenger is ICrossDomainMessenger { - /******************* - * Data Structures * - *******************/ - - struct L2MessageInclusionProof { - bytes32 stateRoot; - Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader; - Lib_OVMCodec.ChainInclusionProof stateRootProof; - bytes stateTrieWitness; - bytes storageTrieWitness; - } - - /******************** - * Public Functions * - ********************/ - - /** - * Relays a cross domain message to a contract. - * @param _target Target contract address. - * @param _sender Message sender address. - * @param _message Message to send to the target. - * @param _messageNonce Nonce for the provided message. - */ - function relayMessage( - address _target, - address _sender, - bytes memory _message, - uint256 _messageNonce - ) external; -} diff --git a/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol b/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol deleted file mode 100644 index 910880a57a5e..000000000000 --- a/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -// solhint-disable max-line-length -/* Library Imports */ -import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; -import { Lib_OVMCodec } from "@eth-optimism/contracts/libraries/codec/Lib_OVMCodec.sol"; -import { - Lib_SecureMerkleTrie -} from "@eth-optimism/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; -import { - Lib_DefaultValues -} from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; -import { - Lib_PredeployAddresses -} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; -import { - Lib_CrossDomainUtils -} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; - -/* Interface Imports */ -import { IL1CrossDomainMessenger } from "./IL1CrossDomainMessenger.sol"; -import { OptimismPortal } from "../OptimismPortal.sol"; - -/* External Imports */ -import { - OwnableUpgradeable -} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { - PausableUpgradeable -} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; -import { - ReentrancyGuardUpgradeable -} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; - -// solhint-enable max-line-length - -/** - * @title L1CrossDomainMessenger - * @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages - * from L2 onto L1. In the event that a message sent from L1 to L2 is rejected for exceeding the L2 - * epoch gas limit, it can be resubmitted via this contract's replay function. - * - */ -contract L1CrossDomainMessenger is - IL1CrossDomainMessenger, - OwnableUpgradeable, - PausableUpgradeable, - ReentrancyGuardUpgradeable -{ - /********** - * Events * - **********/ - - event MessageBlocked(bytes32 indexed _xDomainCalldataHash); - - event MessageAllowed(bytes32 indexed _xDomainCalldataHash); - - /********************** - * Contract Variables * - **********************/ - OptimismPortal public optimismPortal; - address public l2CrossDomainMessenger; - - // Bedrock upgrade note: the nonce must be initialized to greater than the last value of - // CanonicalTransactionChain.queueElements.length. Otherwise it will be possible to have - // messages which cannot be relayed on L2. - uint256 public messageNonce; - - mapping(bytes32 => bool) public blockedMessages; - mapping(bytes32 => bool) public relayedMessages; - mapping(bytes32 => bool) public successfulMessages; - - address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; - - /*************** - * Constructor * - ***************/ - - /** - * This contract is intended to be behind a delegate proxy. - * We still need to set this value in initialize(). - */ - constructor() {} - - /******************** - * Public Functions * - ********************/ - - /** - * @param _optimismPortal Address of the OptimismPortal. - */ - function initialize(OptimismPortal _optimismPortal, address _l2CrossDomainMessenger) - external - initializer - { - require( - address(optimismPortal) == address(0), - "L1CrossDomainMessenger already intialized." - ); - optimismPortal = _optimismPortal; - l2CrossDomainMessenger = _l2CrossDomainMessenger; - xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; - - // Initialize upgradable OZ contracts - __Context_init_unchained(); // Context is a dependency for both Ownable and Pausable - __Ownable_init_unchained(); - __Pausable_init_unchained(); - __ReentrancyGuard_init_unchained(); - } - - /** - * Pause relaying. - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * Block a message. - * @param _xDomainCalldataHash Hash of the message to block. - */ - function blockMessage(bytes32 _xDomainCalldataHash) external onlyOwner { - blockedMessages[_xDomainCalldataHash] = true; - emit MessageBlocked(_xDomainCalldataHash); - } - - /** - * Allow a message. - * @param _xDomainCalldataHash Hash of the message to block. - */ - function allowMessage(bytes32 _xDomainCalldataHash) external onlyOwner { - blockedMessages[_xDomainCalldataHash] = false; - emit MessageAllowed(_xDomainCalldataHash); - } - - /** - * Get the xDomainMessageSender - */ - function xDomainMessageSender() external view returns (address) { - require( - xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, - "xDomainMessageSender is not set" - ); - return xDomainMsgSender; - } - - /** - * Sends a cross domain message to the target messenger. - * This function faciliates L1 to L2 communication. - * @param _target Target contract address. - * @param _message Message to send to the target. - * @param _gasLimit Gas limit for the provided message. - */ - function sendMessage( - address _target, - bytes memory _message, - uint32 _gasLimit - ) external { - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - _target, - msg.sender, - _message, - messageNonce - ); - - emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit); - - _sendXDomainMessage(xDomainCalldata, _gasLimit); - } - - /** - * Relays a cross domain message to a contract. - * This function faciliates L2 to L1 communication. - * Calls WithdrawalsRelay.finalizeWithdrawalTransaction - * @inheritdoc IL1CrossDomainMessenger - */ - function relayMessage( - address _target, - address _sender, - bytes memory _message, - uint256 _messageNonce - ) external nonReentrant whenNotPaused { - require( - msg.sender == address(optimismPortal), - "Messages must be relayed by first calling the Optimism Portal" - ); - require( - optimismPortal.l2Sender() == l2CrossDomainMessenger, - "Message must be sent from the L2 Cross Domain Messenger" - ); - - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - _target, - _sender, - _message, - _messageNonce - ); - - bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); - - require( - successfulMessages[xDomainCalldataHash] == false, - "Provided message has already been received." - ); - - require( - blockedMessages[xDomainCalldataHash] == false, - "Provided message has been blocked." - ); - - require( - _target != address(optimismPortal), - "Cannot send L2->L1 messages to L1 system contracts." - ); - - xDomainMsgSender = _sender; - // slither-disable-next-line reentrancy-no-eth, reentrancy-events, reentrancy-benign - (bool success, ) = _target.call(_message); - // slither-disable-next-line reentrancy-benign - xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; - - // Mark the message as received if the call was successful. Ensures that a message can be - // relayed multiple times in the case that the call reverted. - if (success == true) { - // slither-disable-next-line reentrancy-no-eth - successfulMessages[xDomainCalldataHash] = true; - // slither-disable-next-line reentrancy-events - emit RelayedMessage(xDomainCalldataHash); - } else { - // slither-disable-next-line reentrancy-events - emit FailedRelayedMessage(xDomainCalldataHash); - } - - // Store an identifier that can be used to prove that the given message was relayed by some - // user. Gives us an easy way to pay relayers for their work. - bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number)); - // slither-disable-next-line reentrancy-benign - relayedMessages[relayId] = true; - } - - /********************** - * Internal Functions * - **********************/ - - /** - * Sends a cross domain message. To preserve backwards compatibility, - * the gasLimit is a uint256 so that the function selector stays the same. - * TODO: revert on overflow when converting to uint64? - * @param _message Message to send. - * @param _gasLimit L2 gas limit for the message. - */ - function _sendXDomainMessage(bytes memory _message, uint256 _gasLimit) internal { - optimismPortal.depositTransaction( - Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, - 0, - uint64(_gasLimit), - false, - _message - ); - } -} diff --git a/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol b/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol deleted file mode 100644 index 2cb22988ee8d..000000000000 --- a/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol +++ /dev/null @@ -1,272 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* Interface Imports */ -import { IL1StandardBridge } from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; -import { IL1ERC20Bridge } from "@eth-optimism/contracts/L1/messaging/IL1ERC20Bridge.sol"; -import { IL2ERC20Bridge } from "@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { OptimismPortal } from "../OptimismPortal.sol"; - -/* Library Imports */ -import { - Lib_PredeployAddresses -} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; -import { Address } from "@openzeppelin/contracts/utils/Address.sol"; -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; - -/** - * @title L1StandardBridge - * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard - * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits - * and listening to it for newly finalized withdrawals. - * - */ -contract L1StandardBridge is IL1StandardBridge { - using SafeERC20 for IERC20; - - /******************************** - * External Contract References * - ********************************/ - - OptimismPortal public optimismPortal; - address public l2TokenBridge; - - // Maps L1 token to L2 token to balance of the L1 token deposited - mapping(address => mapping(address => uint256)) public deposits; - - /*************** - * Constructor * - ***************/ - - // This contract lives behind a proxy, so the constructor parameters will go unused. - constructor() {} - - /****************** - * Initialization * - ******************/ - - /** - * @param _optimismPortal OptimismPortal address. - * @param _l2TokenBridge L2 standard bridge address. - */ - // slither-disable-next-line external-function - function initialize(OptimismPortal _optimismPortal, address _l2TokenBridge) public { - require(address(optimismPortal) == address(0), "Contract has already been initialized."); - optimismPortal = _optimismPortal; - l2TokenBridge = _l2TokenBridge; - } - - /************** - * Depositing * - **************/ - - /** @dev Modifier requiring sender to be EOA. This check could be bypassed by a malicious - * contract via initcode, but it takes care of the user error we want to avoid. - */ - modifier onlyEOA() { - // Used to stop deposits from contracts (avoid accidentally lost tokens) - require(!Address.isContract(msg.sender), "Account not EOA"); - _; - } - - /** - * @dev This function can be called with no data - * to deposit an amount of ETH to the caller's balance on L2. - * Since the receive function doesn't take data, a conservative - * default amount is forwarded to L2. - */ - receive() external payable onlyEOA { - _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes("")); - } - - /** - * @inheritdoc IL1StandardBridge - */ - function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA { - _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data); - } - - /** - * @inheritdoc IL1StandardBridge - */ - function depositETHTo( - address _to, - uint32 _l2Gas, - bytes calldata _data - ) external payable { - _initiateETHDeposit(msg.sender, _to, _l2Gas, _data); - } - - /** - * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of - * the deposit. - * @param _from Account to pull the deposit from on L1. - * @param _to Account to give the deposit to on L2. - * @param _l2Gas Gas limit required to complete the deposit on L2. - * @param _data Optional data to forward to L2. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. - */ - function _initiateETHDeposit( - address _from, - address _to, - uint32 _l2Gas, - bytes memory _data - ) internal { - emit ETHDepositInitiated(_from, _to, msg.value, _data); - - // Send calldata into L2 - optimismPortal.depositTransaction{ value: msg.value }(_to, msg.value, _l2Gas, false, _data); - } - - /** - * @inheritdoc IL1ERC20Bridge - */ - function depositERC20( - address _l1Token, - address _l2Token, - uint256 _amount, - uint32 _l2Gas, - bytes calldata _data - ) external virtual onlyEOA { - _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data); - } - - /** - * @inheritdoc IL1ERC20Bridge - */ - function depositERC20To( - address _l1Token, - address _l2Token, - address _to, - uint256 _amount, - uint32 _l2Gas, - bytes calldata _data - ) external virtual { - _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data); - } - - /** - * @dev Performs the logic for deposits by informing the L2 Deposited Token - * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom) - * - * @param _l1Token Address of the L1 ERC20 we are depositing - * @param _l2Token Address of the L1 respective L2 ERC20 - * @param _from Account to pull the deposit from on L1 - * @param _to Account to give the deposit to on L2 - * @param _amount Amount of the ERC20 to deposit. - * @param _l2Gas Gas limit required to complete the deposit on L2. - * @param _data Optional data to forward to L2. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. - */ - function _initiateERC20Deposit( - address _l1Token, - address _l2Token, - address _from, - address _to, - uint256 _amount, - uint32 _l2Gas, - bytes calldata _data - ) internal { - // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future - // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if - // from is an EOA or address(0). - // slither-disable-next-line reentrancy-events, reentrancy-benign - IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount); - - // Construct calldata for _l2Token.finalizeDeposit(_to, _amount) - bytes memory message = abi.encodeWithSelector( - IL2ERC20Bridge.finalizeDeposit.selector, - _l1Token, - _l2Token, - _from, - _to, - _amount, - _data - ); - - // slither-disable-next-line reentrancy-benign - deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount; - - // slither-disable-next-line reentrancy-events - emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data); - - // Send calldata into L2 - optimismPortal.depositTransaction( - Lib_PredeployAddresses.L2_STANDARD_BRIDGE, - 0, - _l2Gas, - false, - message - ); - } - - /************************* - * Cross-chain Functions * - *************************/ - - /** - * @notice Ensures that the caller is the portal, and that it has the l2Sender value - * set to the address of the L2 Token Bridge. - */ - modifier onlyL2Bridge() { - require( - msg.sender == address(optimismPortal), - "Messages must be relayed by first calling the Optimism Portal" - ); - require( - optimismPortal.l2Sender() == l2TokenBridge, - "Message must be sent from the L2 Token Bridge" - ); - _; - } - - /** - * @inheritdoc IL1StandardBridge - */ - function finalizeETHWithdrawal( - address _from, - address _to, - uint256 _amount, - bytes calldata _data - ) external onlyL2Bridge { - emit ETHWithdrawalFinalized(_from, _to, _amount, _data); - - (bool success, ) = _to.call{ value: _amount }(new bytes(0)); - require(success, "TransferHelper::safeTransferETH: ETH transfer failed"); - } - - /** - * @inheritdoc IL1ERC20Bridge - */ - function finalizeERC20Withdrawal( - address _l1Token, - address _l2Token, - address _from, - address _to, - uint256 _amount, - bytes calldata _data - ) external onlyL2Bridge { - deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] - _amount; - emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); - - // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer - IERC20(_l1Token).safeTransfer(_to, _amount); - } - - /***************************** - * Temporary - Migrating ETH * - *****************************/ - - /** - * @dev Adds ETH balance to the account. This is meant to allow for ETH - * to be migrated from an old gateway to a new gateway. - * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the - * old contract - */ - // Bedrock upgrade note: we may use this if this contract gets merged into the portal, - // or even if we just start using a new proxy. - function donateETH() external payable {} -} diff --git a/packages/contracts/contracts/L2/Burner.sol b/packages/contracts/contracts/L2/Burner.sol index f922f0a2db84..36b2ef1c56a7 100644 --- a/packages/contracts/contracts/L2/Burner.sol +++ b/packages/contracts/contracts/L2/Burner.sol @@ -1,6 +1,11 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +/** + * @title Burner + * @dev This contract is used to remove ETH from + * the L2 circulating supply as it is withdrawn. + */ contract Burner { constructor() payable { selfdestruct(payable(address(this))); diff --git a/packages/contracts/contracts/L2/IWithdrawer.sol b/packages/contracts/contracts/L2/IWithdrawer.sol deleted file mode 100644 index d2f3f9b9a268..000000000000 --- a/packages/contracts/contracts/L2/IWithdrawer.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.8.0; - -interface IWithdrawer { - event WithdrawalInitiated( - uint256 indexed nonce, - address indexed sender, - address indexed target, - uint256 value, - uint256 gasLimit, - bytes data - ); - event WithdrawerBalanceBurnt(uint256 indexed amount); - - function burn() external; - - function initiateWithdrawal( - address _target, - uint256 _gasLimit, - bytes memory _data - ) external payable; - - function nonce() external view returns (uint256); - - function withdrawals(bytes32) external view returns (bool); -} diff --git a/packages/contracts/contracts/L2/L1Block.sol b/packages/contracts/contracts/L2/L1Block.sol index a25011dcdbc5..8b6b5fc4d849 100644 --- a/packages/contracts/contracts/L2/L1Block.sol +++ b/packages/contracts/contracts/L2/L1Block.sol @@ -3,21 +3,56 @@ pragma solidity 0.8.10; /** * @title L1Block + * @dev This is an L2 predeploy contract that holds values from the L1 + * chain. It can only be updated by a special account that has no private + * key managed by the L2 system. Transactions sent to this contract can + * be thought of as "L2 system transactions". */ contract L1Block { /** - * Only the Depositor account may call setL1BlockValues(). + * @notice Only the Depositor account may call setL1BlockValues(). */ error OnlyDepositor(); + /** + * @notice The depositor account is a special account that sends + * transactions to this contract. + */ address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; + /** + * @notice The latest L1 block number known by the L2 system + */ uint64 public number; + + /** + * @notice The latest L1 timestamp known by the L2 system + */ uint64 public timestamp; + + /** + * @notice The latest L1 basefee + */ uint256 public basefee; + + /** + * @notice The latest L1 blockhash + */ bytes32 public hash; + + /** + * @notice The number of L2 blocks in the same epoch + */ uint64 public sequenceNumber; + /** + * @notice Sets the L1 values + * @param _number L1 blocknumber + * @param _timestamp L1 timestamp + * @param _basefee L1 basefee + * @param _hash L1 blockhash + * @param _sequenceNumber Number of L2 blocks since epoch start + */ function setL1BlockValues( uint64 _number, uint64 _timestamp, diff --git a/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol b/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol new file mode 100644 index 000000000000..7a713a912cdf --- /dev/null +++ b/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol"; +import { L2ToL1MessagePasser } from "./L2ToL1MessagePasser.sol"; + +contract L2CrossDomainMessenger is CrossDomainMessenger { + /******************** + * Public Functions * + ********************/ + + /** + * @notice initialize the L2CrossDomainMessenger by giving + * it the address of the L1CrossDomainMessenger on L1 + */ + function initialize(address _l1CrossDomainMessenger) external { + address[] memory blockedSystemAddresses = new address[](2); + blockedSystemAddresses[0] = address(this); + blockedSystemAddresses[1] = Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER; + + _initialize(_l1CrossDomainMessenger, blockedSystemAddresses); + } + + /********************** + * Internal Functions * + **********************/ + + /** + * @notice Only the L1CrossDomainMessenger can call the + * L2CrossDomainMessenger + */ + function _isSystemMessageSender() internal view override returns (bool) { + return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == otherMessenger; + } + + /** + * @notice Sending a message from L2 to L1 involves calling the L2ToL1MessagePasser + * where it stores in a storage slot a commitment to the message being + * sent to L1. A proof is then verified against that storage slot on L1. + */ + function _sendMessage( + address _to, + uint64 _gasLimit, + uint256 _value, + bytes memory _data + ) internal override { + L2ToL1MessagePasser(payable(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER)) + .initiateWithdrawal{ value: _value }(_to, _gasLimit, _data); + } +} diff --git a/packages/contracts/contracts/L2/L2StandardBridge.sol b/packages/contracts/contracts/L2/L2StandardBridge.sol new file mode 100644 index 000000000000..578a9c981969 --- /dev/null +++ b/packages/contracts/contracts/L2/L2StandardBridge.sol @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; +import { StandardBridge } from "../universal/StandardBridge.sol"; +import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol"; + +/** + * @title L2StandardBridge + * @dev This contract is an L2 predeploy that is responsible for facilitating + * deposits of tokens from L1 to L2. + * TODO: ensure that this has 1:1 backwards compatibility + */ +contract L2StandardBridge is StandardBridge { + /********** + * Events * + **********/ + + event WithdrawalInitiated( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event DepositFinalized( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event DepositFailed( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + /******************** + * Public Functions * + ********************/ + + /** + * @notice Initialize the L2StandardBridge. This must only be callable + * once. `_initialize` ensures this. + */ + function initialize(address payable _otherBridge) public { + _initialize(payable(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER), _otherBridge); + } + + /** + * @notice Withdraw tokens to self on L1 + * @param _l2Token The L2 token address to withdraw + * @param _amount The amount of L2 token to withdraw + * @param _minGasLimit The min gas limit in the withdrawing call + * @param _data Additional calldata to pass along + */ + function withdraw( + address _l2Token, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) external payable virtual { + _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _data); + } + + /** + * @notice Withdraw tokens to an address on L1 + * @param _l2Token The L2 token address to withdraw + * @param _to The L1 account to withdraw to + * @param _amount The amount of L2 token to withdraw + * @param _minGasLimit The min gas limit in the withdrawing call + * @param _data Additional calldata to pass along + */ + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) external payable virtual { + _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _data); + } + + /** + * @notice Finalize the L1 to L2 deposit. This should only be callable by + * a deposit through the L1StandardBridge. + * @param _l1Token The L1 token address + * @param _l2Token The corresponding L2 token address + * @param _from The sender of the tokens + * @param _to The recipient of the tokens + * @param _amount The amount of tokens + * @param _data Additional calldata + */ + function finalizeDeposit( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external payable virtual { + // Check to see if the bridge is being used to deposit ETH. + // The `msg.value` must match the `_amount` to prevent + // ETH from getting stuck in the contract + if ( + _l1Token == address(0) && + _l2Token == Lib_PredeployAddresses.OVM_ETH && + msg.value == _amount + ) { + // An ETH deposit is being made via the Token Bridge. + // We simply forward it on. If this call fails, ETH will be stuck, but the L1Bridge + // uses onlyEOA on the receive function, so anyone sending to a contract knows + // what they are doing. + finalizeBridgeETH(_from, _to, _amount, _data); + emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); + } else if ( + _isOptimismMintable(_l2Token, _l1Token) + ) // Check the target token is compliant and + // verify the deposited token on L1 matches the L2 deposited token representation here + // slither-disable-next-line reentrancy-events + { + // When a deposit is finalized, we credit the account on L2 with the same amount of + // tokens. + // slither-disable-next-line reentrancy-events + finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _data); + // slither-disable-next-line reentrancy-events + emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); + } else { + // Either the L2 token which is being deposited-into disagrees about the correct address + // of its L1 token, or does not support the correct interface. + // This should only happen if there is a malicious L2 token, or if a user somehow + // specified the wrong L2 token address to deposit into. + // In either case, we stop the process here and construct a withdrawal + // message so that users can get their funds out in some cases. + // There is no way to prevent malicious token contracts altogether, but this does limit + // user error and mitigate some forms of malicious contract behavior. + emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data); + + // Withdraw ETH in the case that the user submitted a bad ETH + // deposit to prevent ETH from getting stuck + // TODO: can this be wrapped into _initiateWithdrawal? + // need to handle using `msg.value` here instead of `_value` + if (_l2Token == Lib_PredeployAddresses.OVM_ETH) { + _initiateBridgeETH(_from, _to, msg.value, 0, _data); + } else { + _initiateBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, 0, _data); + } + } + } + + /********************** + * Internal Functions * + **********************/ + + /** + * @notice Handle withdrawals, taking into account the legacy form of ETH + * when it was represented as an ERC20 at the OVM_ETH contract. + * TODO: require(msg.value == _value) for OVM_ETH case? + */ + function _initiateWithdrawal( + address _l2Token, + address _from, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) internal { + address l1Token = OptimismMintableERC20(_l2Token).l1Token(); + emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data); + if (_l2Token == Lib_PredeployAddresses.OVM_ETH) { + _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _data); + } else { + _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _data); + } + } +} diff --git a/packages/contracts/contracts/L2/Withdrawer.sol b/packages/contracts/contracts/L2/L2ToL1MessagePasser.sol similarity index 62% rename from packages/contracts/contracts/L2/Withdrawer.sol rename to packages/contracts/contracts/L2/L2ToL1MessagePasser.sol index 0d7147c34008..99eeb21e8c8d 100644 --- a/packages/contracts/contracts/L2/Withdrawer.sol +++ b/packages/contracts/contracts/L2/L2ToL1MessagePasser.sol @@ -1,19 +1,14 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; -/* Library Imports */ -import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; - -/* Interaction imports */ import { Burner } from "./Burner.sol"; /** - * @title Withdrawer - * @notice The Withdrawer contract facilitates sending both ETH value and data from L2 to L1. - * It is predeployed in the L2 state at address 0x4200000000000000000000000000000000000016. + * @title L2ToL1MessagePasser + * TODO: should this be renamed to L2OptimismPortal? */ -contract Withdrawer { +contract L2ToL1MessagePasser { /********** * Events * **********/ @@ -36,25 +31,42 @@ contract Withdrawer { bytes data ); - /// @notice Emitted when the balance of this contract is burned. + /** + * @notice Emitted when the balance of this contract is burned. + */ event WithdrawerBalanceBurnt(uint256 indexed amount); - /********************** - * Contract Variables * - **********************/ + /************* + * Variables * + *************/ - /// @notice A unique value hashed with each withdrawal. + /** + * @notice Includes the message hashes for all withdrawals + */ + mapping(bytes32 => bool) public sentMessages; + + /** + * @notice A unique value hashed with each withdrawal. + */ uint256 public nonce; - /// @notice A mapping listing withdrawals which have been initiated herein. - mapping(bytes32 => bool) public withdrawals; + /******************** + * Public Functions * + ********************/ - /********************** - * External Functions * - **********************/ + /** + * @notice Allow users to withdraw by sending ETH + * directly to this contract. + * TODO: maybe this should be only EOA + */ + receive() external payable { + initiateWithdrawal(msg.sender, 100000, bytes("")); + } /** * @notice Initiates a withdrawal to execute on L1. + * TODO: message hashes must be migrated since the legacy + * hashes are computed differently * @param _target Address to call on L1 execution. * @param _gasLimit GasLimit to provide on L1. * @param _data Data to forward to L1 target. @@ -62,11 +74,9 @@ contract Withdrawer { function initiateWithdrawal( address _target, uint256 _gasLimit, - bytes calldata _data - ) external payable { - address from = msg.sender; - - bytes32 withdrawalHash = WithdrawalVerifier._deriveWithdrawalHash( + bytes memory _data + ) public payable { + bytes32 withdrawalHash = WithdrawalVerifier.withdrawalHash( nonce, msg.sender, _target, @@ -74,9 +84,10 @@ contract Withdrawer { _gasLimit, _data ); - withdrawals[withdrawalHash] = true; - emit WithdrawalInitiated(nonce, from, _target, msg.value, _gasLimit, _data); + sentMessages[withdrawalHash] = true; + + emit WithdrawalInitiated(nonce, msg.sender, _target, msg.value, _gasLimit, _data); unchecked { ++nonce; } diff --git a/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol b/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol deleted file mode 100644 index 3fa345d61f3f..000000000000 --- a/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/** - * @title IL2ERC20Bridge - */ -interface IL2ERC20Bridge { - /********** - * Events * - **********/ - - event WithdrawalInitiated( - address indexed _l1Token, - address indexed _l2Token, - address indexed _from, - address _to, - uint256 _amount, - bytes _data - ); - - event DepositFinalized( - address indexed _l1Token, - address indexed _l2Token, - address indexed _from, - address _to, - uint256 _amount, - bytes _data - ); - - event DepositFailed( - address indexed _l1Token, - address indexed _l2Token, - address indexed _from, - address _to, - uint256 _amount, - bytes _data - ); - - /******************** - * Public Functions * - ********************/ - - /** - * @dev get the address of the corresponding L1 bridge contract. - * @return Address of the corresponding L1 bridge contract. - */ - function l1TokenBridge() external returns (address); - - /** - * @dev initiate a withdraw of some tokens to the caller's account on L1 - * @param _l2Token Address of L2 token where withdrawal was initiated. - * @param _amount Amount of the token to withdraw. - * param _l1Gas Unused, but included for potential forward compatibility considerations. - * @param _data Optional data to forward to L1. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. - */ - function withdraw( - address _l2Token, - uint256 _amount, - uint32 _l1Gas, - bytes calldata _data - ) external; - - /** - * @dev initiate a withdraw of some token to a recipient's account on L1. - * @param _l2Token Address of L2 token where withdrawal is initiated. - * @param _to L1 adress to credit the withdrawal to. - * @param _amount Amount of the token to withdraw. - * param _l1Gas Unused, but included for potential forward compatibility considerations. - * @param _data Optional data to forward to L1. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. - */ - function withdrawTo( - address _l2Token, - address _to, - uint256 _amount, - uint32 _l1Gas, - bytes calldata _data - ) external; - - /************************* - * Cross-chain Functions * - *************************/ - - /** - * @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this - * L2 token. This call will fail if it did not originate from a corresponding deposit in - * L1StandardTokenBridge. - * @param _l1Token Address for the l1 token this is called with - * @param _l2Token Address for the l2 token this is called with - * @param _from Account to pull the deposit from on L2. - * @param _to Address to receive the withdrawal at - * @param _amount Amount of the token to withdraw - * @param _data Data provider by the sender on L1. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. - */ - function finalizeDeposit( - address _l1Token, - address _l2Token, - address _from, - address _to, - uint256 _amount, - bytes calldata _data - ) external; -} diff --git a/packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol b/packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol deleted file mode 100644 index d3a5e7d4e4ad..000000000000 --- a/packages/contracts/contracts/L2/messaging/IL2StandardTokenFactory.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.8.10; - -interface IL2StandardTokenFactory { - event StandardL2TokenCreated(address indexed _l1Token, address indexed _l2Token); - - function createStandardL2Token( - address _l1Token, - string memory _name, - string memory _symbol - ) external; -} diff --git a/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol b/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol deleted file mode 100644 index a7517600599f..000000000000 --- a/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -// solhint-disable max-line-length -/* Library Imports */ -import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; -import { - Lib_CrossDomainUtils -} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; -import { - Lib_DefaultValues -} from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; -import { Lib_BedrockPredeployAddresses } from "../../libraries/Lib_BedrockPredeployAddresses.sol"; - -/* Interface Imports */ -import { - IL2CrossDomainMessenger -} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; -import { Withdrawer } from "../Withdrawer.sol"; - -// solhint-enable max-line-length - -/** - * @title L2CrossDomainMessenger - * @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point - * for L2 messages sent via the L1 Cross Domain Messenger. - * - */ -contract L2CrossDomainMessenger is IL2CrossDomainMessenger { - /************* - * Variables * - *************/ - - mapping(bytes32 => bool) public relayedMessages; - mapping(bytes32 => bool) public successfulMessages; - mapping(bytes32 => bool) public sentMessages; - uint256 public messageNonce; - address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; - address public l1CrossDomainMessenger; - - /*************** - * Constructor * - ***************/ - - constructor(address _l1CrossDomainMessenger) { - l1CrossDomainMessenger = _l1CrossDomainMessenger; - } - - /******************** - * Public Functions * - ********************/ - - function xDomainMessageSender() external view returns (address) { - require( - xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, - "xDomainMessageSender is not set" - ); - return xDomainMsgSender; - } - - /** - * Sends a cross domain message to the target messenger. - * @param _target Target contract address. - * @param _message Message to send to the target. - * @param _gasLimit Gas limit for the provided message. - */ - function sendMessage( - address _target, - bytes memory _message, - uint32 _gasLimit - ) external { - // Temp note: I think we might be able to remove xDomainCallData from this contract - // entirely. - // Possibly also from the L1xDM as well, but needs considerations. - // Rationale: the proof no longer occurs in the L1 messenger, but rather in the - // WithdrawalRelayer logic (which is inherited into the Portal). This proof relies on - // the value returned by WithdrawalVerifier._deriveWithdrawalHash(), which takes in - // more arguments. - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - _target, - msg.sender, - _message, - messageNonce - ); - - // Temp note: Further to my notes above, afaict this mapping is not used for anything. - // It'd be great if we can save an SSTORE by removing it. - sentMessages[keccak256(xDomainCalldata)] = true; - - // Emit an event before we bump the nonce or the nonce will be off by one. - emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit); - unchecked { - ++messageNonce; - } - - // Actually send the message. - Withdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER).initiateWithdrawal( - l1CrossDomainMessenger, - _gasLimit, - _message - ); - } - - /** - * Relays a cross domain message to a contract. - * @inheritdoc IL2CrossDomainMessenger - */ - function relayMessage( - address _target, - address _sender, - bytes memory _message, - uint256 _messageNonce - ) external { - // Since it is impossible to deploy a contract to an address on L2 which matches - // the alias of the L1CrossDomainMessenger, this check can only pass when it is called in - // the first call frame of a deposit transaction. Thus reentrancy is prevented here. - require( - AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1CrossDomainMessenger, - "Provided message could not be verified." - ); - - // Temp note: Here we would need to keep the xDomainCalldata hashing and - // storage, because it allows replays when the call fails, and prevents - // them when it succeeds. - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - _target, - _sender, - _message, - _messageNonce - ); - - bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); - - require( - successfulMessages[xDomainCalldataHash] == false, - "Provided message has already been received." - ); - - // Prevent calls to WITHDRAWER, which would enable - // an attacker to maliciously craft the _message to spoof - // a call from any L2 account. - // Todo: evaluate if this attack is still relevant - if (_target == Lib_BedrockPredeployAddresses.WITHDRAWER) { - // Write to the successfulMessages mapping and return immediately. - successfulMessages[xDomainCalldataHash] = true; - return; - } - - xDomainMsgSender = _sender; - // slither-disable-next-line reentrancy-no-eth, reentrancy-events, reentrancy-benign - (bool success, ) = _target.call(_message); - // slither-disable-next-line reentrancy-benign - xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; - - // Mark the message as received if the call was successful. Ensures that a message can be - // relayed multiple times in the case that the call reverted. - if (success == true) { - // slither-disable-next-line reentrancy-no-eth - successfulMessages[xDomainCalldataHash] = true; - // slither-disable-next-line reentrancy-events - emit RelayedMessage(xDomainCalldataHash); - } else { - // slither-disable-next-line reentrancy-events - emit FailedRelayedMessage(xDomainCalldataHash); - } - - // Store an identifier that can be used to prove that the given message was relayed by some - // user. Gives us an easy way to pay relayers for their work. - // TODO: consider unaliasing `msg.sender` here - bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number)); - - // slither-disable-next-line reentrancy-benign - relayedMessages[relayId] = true; - } -} diff --git a/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol b/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol deleted file mode 100644 index b3671f302690..000000000000 --- a/packages/contracts/contracts/L2/messaging/L2StandardBridge.sol +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* Interface Imports */ -import { IL1StandardBridge } from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; -import { IL1ERC20Bridge } from "@eth-optimism/contracts/L1/messaging/IL1ERC20Bridge.sol"; -import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol"; - -/* Library Imports */ -import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import { - Lib_PredeployAddresses -} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; -import { Lib_BedrockPredeployAddresses } from "../../libraries/Lib_BedrockPredeployAddresses.sol"; -import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; - -/* Contract Imports */ -import { IL2StandardERC20 } from "@eth-optimism/contracts/standards/IL2StandardERC20.sol"; -import { Withdrawer } from "../Withdrawer.sol"; - -/** - * @title L2StandardBridge - * @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to - * enable ETH and ERC20 transitions between L1 and L2. - * This contract acts as a minter for new tokens when it hears about deposits into the L1 Standard - * bridge. - * This contract also acts as a burner of the tokens intended for withdrawal, informing the L1 - * bridge to release L1 funds. - */ -contract L2StandardBridge is IL2ERC20Bridge { - /******************************** - * External Contract References * - ********************************/ - - address public l1TokenBridge; - - /*************** - * Constructor * - ***************/ - - /** - * @param _l1TokenBridge Address of the L1 bridge deployed to the main chain. - */ - constructor(address _l1TokenBridge) { - l1TokenBridge = _l1TokenBridge; - } - - /*************** - * Withdrawing * - ***************/ - - /** - * @inheritdoc IL2ERC20Bridge - */ - function withdraw( - address _l2Token, - uint256 _amount, - uint32 _l1Gas, - bytes calldata _data - ) external virtual { - _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data); - } - - /** - * @inheritdoc IL2ERC20Bridge - */ - function withdrawTo( - address _l2Token, - address _to, - uint256 _amount, - uint32 _l1Gas, - bytes calldata _data - ) external virtual { - _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data); - } - - /** - * @dev Performs the logic for withdrawals by burning the token and informing - * the L1 token Gateway of the withdrawal. - * @param _l2Token Address of L2 token where withdrawal is initiated. - * @param _from Account to pull the withdrawal from on L2. - * @param _to Account to give the withdrawal to on L1. - * @param _amount Amount of the token to withdraw. - * @param _l1Gas Unused, but included for potential forward compatibility considerations. - * @param _data Optional data to forward to L1. This data is provided - * solely as a convenience for external contracts. Aside from enforcing a maximum - * length, these contracts provide no guarantees about its content. - */ - function _initiateWithdrawal( - address _l2Token, - address _from, - address _to, - uint256 _amount, - uint32 _l1Gas, - bytes calldata _data - ) internal { - // When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2 - // usage - // slither-disable-next-line reentrancy-events - IL2StandardERC20(_l2Token).burn(msg.sender, _amount); - - // Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount) - // slither-disable-next-line reentrancy-events - address l1Token = IL2StandardERC20(_l2Token).l1Token(); - bytes memory message = abi.encodeWithSelector( - IL1ERC20Bridge.finalizeERC20Withdrawal.selector, - l1Token, - _l2Token, - _from, - _to, - _amount, - _data - ); - - // slither-disable-next-line reentrancy-events - emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data); - - // Send message up to L1 bridge - Withdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER).initiateWithdrawal( - l1TokenBridge, - _l1Gas, - message - ); - } - - /************************************ - * Cross-chain Function: Depositing * - ************************************/ - - /** - * @inheritdoc IL2ERC20Bridge - */ - function finalizeDeposit( - address _l1Token, - address _l2Token, - address _from, - address _to, - uint256 _amount, - bytes calldata _data - ) external virtual { - // Since it is impossible to deploy a contract to an address on L2 which matches - // the alias of the l1TokenBridge, this check can only pass when it is called in - // the first call frame of a deposit transaction. Thus reentrancy is prevented here. - require( - AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1TokenBridge, - "Can only be called by a the l1TokenBridge" - ); - - if ( - // Check the target token is compliant and - // verify the deposited token on L1 matches the L2 deposited token representation here - // slither-disable-next-line reentrancy-events - ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) && - _l1Token == IL2StandardERC20(_l2Token).l1Token() - ) { - // When a deposit is finalized, we credit the account on L2 with the same amount of - // tokens. - // slither-disable-next-line reentrancy-events - IL2StandardERC20(_l2Token).mint(_to, _amount); - // slither-disable-next-line reentrancy-events - emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); - } else { - // Either the L2 token which is being deposited-into disagrees about the correct address - // of its L1 token, or does not support the correct interface. - // This should only happen if there is a malicious L2 token, or if a user somehow - // specified the wrong L2 token address to deposit into. - // In either case, we stop the process here and construct a withdrawal - // message so that users can get their funds out in some cases. - // There is no way to prevent malicious token contracts altogether, but this does limit - // user error and mitigate some forms of malicious contract behavior. - bytes memory message = abi.encodeWithSelector( - IL1ERC20Bridge.finalizeERC20Withdrawal.selector, - _l1Token, - _l2Token, - _to, // switched the _to and _from here to bounce back the deposit to the sender - _from, - _amount, - _data - ); - - emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data); - - // Send message up to L1 bridge - Withdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER).initiateWithdrawal( - l1TokenBridge, - 0, - message - ); - } - } -} diff --git a/packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol b/packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol deleted file mode 100644 index c9380746274c..000000000000 --- a/packages/contracts/contracts/L2/messaging/L2StandardTokenFactory.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* Contract Imports */ -import { L2StandardERC20 } from "../tokens/L2StandardERC20.sol"; -import { - Lib_PredeployAddresses -} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; - -/** - * @title L2StandardTokenFactory - * @dev Factory contract for creating standard L2 token representations of L1 ERC20s - * compatible with and working on the standard bridge. - */ -contract L2StandardTokenFactory { - event StandardL2TokenCreated(address indexed _l1Token, address indexed _l2Token); - - /** - * @dev Creates an instance of the standard ERC20 token on L2. - * @param _l1Token Address of the corresponding L1 token. - * @param _name ERC20 name. - * @param _symbol ERC20 symbol. - */ - function createStandardL2Token( - address _l1Token, - string memory _name, - string memory _symbol - ) external { - require(_l1Token != address(0), "Must provide L1 token address"); - - L2StandardERC20 l2Token = new L2StandardERC20( - Lib_PredeployAddresses.L2_STANDARD_BRIDGE, - _l1Token, - _name, - _symbol - ); - - emit StandardL2TokenCreated(_l1Token, address(l2Token)); - } -} diff --git a/packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol b/packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol deleted file mode 100644 index f9e981842520..000000000000 --- a/packages/contracts/contracts/L2/tokens/IL2StandardERC20.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - -interface IL2StandardERC20 is IERC20, IERC165 { - function l1Token() external returns (address); - - function l2Bridge() external returns (address); - - function mint(address _to, uint256 _amount) external; - - function burn(address _from, uint256 _amount) external; - - event Mint(address indexed _account, uint256 _amount); - event Burn(address indexed _account, uint256 _amount); -} diff --git a/packages/contracts/contracts/L2/tokens/L2StandardERC20.sol b/packages/contracts/contracts/L2/tokens/L2StandardERC20.sol deleted file mode 100644 index 06144d7cb343..000000000000 --- a/packages/contracts/contracts/L2/tokens/L2StandardERC20.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -// import { ERC20 } from "solmate/tokens/ERC20.sol"; -// import { ERC20 } from "solmate/tokens/ERC20.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "./IL2StandardERC20.sol"; - -contract L2StandardERC20 is IL2StandardERC20, ERC20 { - address public l1Token; - address public l2Bridge; - - /** - * @param _l2Bridge Address of the L2 standard bridge. - * @param _l1Token Address of the corresponding L1 token. - * @param _name ERC20 name. - * @param _symbol ERC20 symbol. - */ - constructor( - address _l2Bridge, - address _l1Token, - string memory _name, - string memory _symbol - ) ERC20(_name, _symbol) { - l1Token = _l1Token; - l2Bridge = _l2Bridge; - } - - modifier onlyL2Bridge() { - require(msg.sender == l2Bridge, "Only L2 Bridge can mint and burn"); - _; - } - - // slither-disable-next-line external-function - function supportsInterface(bytes4 _interfaceId) public pure returns (bool) { - bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165 - bytes4 secondSupportedInterface = IL2StandardERC20.l1Token.selector ^ - IL2StandardERC20.mint.selector ^ - IL2StandardERC20.burn.selector; - return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface; - } - - // slither-disable-next-line external-function - function mint(address _to, uint256 _amount) public virtual onlyL2Bridge { - _mint(_to, _amount); - - emit Mint(_to, _amount); - } - - // slither-disable-next-line external-function - function burn(address _from, uint256 _amount) public virtual onlyL2Bridge { - _burn(_from, _amount); - - emit Burn(_from, _amount); - } -} diff --git a/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol b/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol new file mode 100644 index 000000000000..6d94ebd9000b --- /dev/null +++ b/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.9; + +// FROM: https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol +// TODO: Just use the original once we get our PR merged. +library ExcessivelySafeCall { + /// @notice Use when you _really_ really _really_ don't trust the called + /// contract. This prevents the called contract from causing reversion of + /// the caller in as many ways as we can. + /// @dev The main difference between this and a solidity low-level call is + /// that we limit the number of bytes that the callee can cause to be + /// copied to caller memory. This prevents stupid things like malicious + /// contracts returning 10,000,000 bytes causing a local OOG when copying + /// to memory. + /// @param _target The address to call + /// @param _gas The amount of gas to forward to the remote contract + /// @param _value Ether value to send with the call + /// @param _maxCopy The maximum number of bytes of returndata to copy + /// to memory. + /// @param _calldata The data to send to the remote contract + /// @return success and returndata, as `.call()`. Returndata is capped to + /// `_maxCopy` bytes. + function excessivelySafeCall( + address _target, + uint256 _gas, + uint256 _value, + uint16 _maxCopy, + bytes memory _calldata + ) internal returns (bool, bytes memory) { + // set up for assembly call + uint256 _toCopy; + bool _success; + bytes memory _returnData = new bytes(_maxCopy); + // dispatch message to recipient + // by assembly calling "handle" function + // we call via assembly to avoid memcopying a very large returndata + // returned by a malicious contract + assembly { + _success := call( + _gas, // gas + _target, // recipient + _value, // ether value + add(_calldata, 0x20), // inloc + mload(_calldata), // inlen + 0, // outloc + 0 // outlen + ) + // limit our copy to 256 bytes + _toCopy := returndatasize() + if gt(_toCopy, _maxCopy) { + _toCopy := _maxCopy + } + // Store the length of the copied bytes + mstore(_returnData, _toCopy) + // copy the bytes from returndata[0:_toCopy] + returndatacopy(add(_returnData, 0x20), 0, _toCopy) + } + return (_success, _returnData); + } +} diff --git a/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol b/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol index 07513b05dfcc..8a64bc6b1bf3 100644 --- a/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol +++ b/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.9; /** * @title Lib_BedrockPredeployAddresses + * TODO: just merge this value into the monorepo */ library Lib_BedrockPredeployAddresses { address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015; - address internal constant WITHDRAWER = 0x4200000000000000000000000000000000000016; } diff --git a/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol b/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol new file mode 100644 index 000000000000..703ba64deab4 --- /dev/null +++ b/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol @@ -0,0 +1,249 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { + Lib_CrossDomainUtils +} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; +import { Lib_RLPWriter } from "@eth-optimism/contracts/libraries/rlp/Lib_RLPWriter.sol"; + +/** + * @title CrossDomainHashing + * This library is responsible for holding cross domain utility + * functions. + * TODO(tynes): merge with Lib_CrossDomainUtils + * TODO(tynes): fill out more devdocs + */ +library CrossDomainHashing { + /** + * @notice Compute the L2 transaction hash given + * data about an L1 deposit transaction. This is useful for + * environments that do not have access to arbitrary + * RLP encoding functionality but have access to the + * standard web3 API + * TODO: rearrange args in a sane way + * @param _l1BlockHash The L1 block hash corresponding to the block + * the deposit was included in + * @param _logIndex The log index of the event that the deposit was + * created from. This can be found on the transaction receipt + * @param _from The sender of the deposit + * @param _to The L2 contract to be called by the deposit transaction + * @param _isCreate Indicates if the deposit creates a contract + * @param _mint The amount of ETH being minted by the transaction + * @param _value The amount of ETH send in the L2 call + * @param _gas The gas limit for the L2 call + */ + function L2TransactionHash( + bytes32 _l1BlockHash, + uint256 _logIndex, + address _from, + address _to, + bool _isCreate, + uint256 _mint, + uint256 _value, + uint256 _gas, + bytes memory _data + ) internal pure returns (bytes32) { + bytes memory raw = L2Transaction( + _l1BlockHash, + _logIndex, + _from, + _to, + _isCreate, + _mint, + _value, + _gas, + _data + ); + + return keccak256(raw); + } + + /** + * @notice Compute the deposit transaction source hash. + * This value ensures that the L2 transaction hash is unique + * and deterministic based on L1 execution + * @param l1BlockHash The L1 blockhash corresponding to the block including + * the deposit + * @param logIndex The index of the log that created the deposit transaction + */ + function sourceHash(bytes32 l1BlockHash, uint256 logIndex) internal pure returns (bytes32) { + bytes32 depositId = keccak256(abi.encode(l1BlockHash, logIndex)); + return keccak256(abi.encode(bytes32(0), depositId)); + } + + /** + * @notice RLP encode a deposit transaction + * This only works for user deposits, not system deposits + * TODO: better name + rearrange the input param ordering? + */ + function L2Transaction( + bytes32 _l1BlockHash, + uint256 _logIndex, + address _from, + address _to, + bool _isCreate, + uint256 _mint, + uint256 _value, + uint256 _gas, + bytes memory _data + ) internal pure returns (bytes memory) { + bytes32 source = sourceHash(_l1BlockHash, _logIndex); + + bytes[] memory raw = new bytes[](7); + + raw[0] = Lib_RLPWriter.writeBytes(bytes32ToBytes(source)); + raw[1] = Lib_RLPWriter.writeAddress(_from); + + if (_isCreate == true) { + require(_to == address(0)); + raw[2] = Lib_RLPWriter.writeBytes(""); + } else { + raw[2] = Lib_RLPWriter.writeAddress(_to); + } + + raw[3] = Lib_RLPWriter.writeUint(_mint); + raw[4] = Lib_RLPWriter.writeUint(_value); + raw[5] = Lib_RLPWriter.writeUint(_gas); + raw[6] = Lib_RLPWriter.writeBytes(_data); + + bytes memory encoded = Lib_RLPWriter.writeList(raw); + return abi.encodePacked(uint8(0x7e), encoded); + } + + /** + * @notice Helper function to turn bytes32 into bytes + */ + function bytes32ToBytes(bytes32 input) internal pure returns (bytes memory) { + bytes memory b = new bytes(32); + assembly { + mstore(add(b, 32), input) // set the bytes data + } + return b; + } + + /** + * @notice Adds the version to the nonce + */ + function addVersionToNonce(uint256 _nonce, uint16 _version) + internal + pure + returns (uint256 nonce) + { + assembly { + nonce := or(shl(240, _version), _nonce) + } + } + + /** + * @notice Gets the version out of the nonce + */ + function getVersionFromNonce(uint256 _nonce) internal pure returns (uint16 version) { + assembly { + version := shr(240, _nonce) + } + } + + /** + * @notice Encodes the cross domain message based on the version that + * is encoded in the nonce + */ + function getVersionedEncoding( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) internal pure returns (bytes memory) { + uint16 version = getVersionFromNonce(_nonce); + if (version == 0) { + return getEncodingV0(_target, _sender, _data, _nonce); + } else if (version == 1) { + return getEncodingV1(_nonce, _sender, _target, _value, _gasLimit, _data); + } + + revert("Unknown version."); + } + + /** + * @notice Compute the cross domain hash based on the versioned nonce + */ + function getVersionedHash( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) internal pure returns (bytes32) { + uint16 version = getVersionFromNonce(_nonce); + if (version == 0) { + return getHashV0(_target, _sender, _data, _nonce); + } else if (version == 1) { + return getHashV1(_nonce, _sender, _target, _value, _gasLimit, _data); + } + + revert("Unknown version."); + } + + /** + * @notice Compute the legacy cross domain serialization + */ + function getEncodingV0( + address _target, + address _sender, + bytes memory _data, + uint256 _nonce + ) internal pure returns (bytes memory) { + return Lib_CrossDomainUtils.encodeXDomainCalldata(_target, _sender, _data, _nonce); + } + + /** + * @notice Compute the V1 cross domain serialization + */ + function getEncodingV1( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) internal pure returns (bytes memory) { + return + abi.encodeWithSignature( + "relayMessage(uint256,address,address,uint256,uint256,bytes)", + _nonce, + _sender, + _target, + _value, + _gasLimit, + _data + ); + } + + /** + * @notice Compute the legacy hash of a cross domain message + */ + function getHashV0( + address _target, + address _sender, + bytes memory _data, + uint256 _nonce + ) internal pure returns (bytes32) { + return keccak256(getEncodingV0(_target, _sender, _data, _nonce)); + } + + /** + * @notice Compute the V1 hash of a cross domain message + */ + function getHashV1( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) internal pure returns (bytes32) { + return keccak256(getEncodingV1(_nonce, _sender, _target, _value, _gasLimit, _data)); + } +} diff --git a/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol index 9d998afba2be..afee6537550f 100644 --- a/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol +++ b/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol @@ -5,6 +5,9 @@ pragma solidity 0.8.10; import { Lib_SecureMerkleTrie } from "@eth-optimism/contracts/libraries/trie/Lib_SecureMerkleTrie.sol"; +import { + Lib_CrossDomainUtils +} from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; /** * @title WithdrawalVerifier @@ -28,13 +31,13 @@ library WithdrawalVerifier { * @param _gasLimit Gas to be forwarded to the target. * @param _data Data to send to the target. */ - function _deriveWithdrawalHash( + function withdrawalHash( uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, - bytes calldata _data + bytes memory _data ) internal pure returns (bytes32) { return keccak256(abi.encode(_nonce, _sender, _target, _value, _gasLimit, _data)); } @@ -44,7 +47,7 @@ library WithdrawalVerifier { * @param _outputRootProof The elements which were hashed together to generate the output root. * @return Whether or not the output root matches the hashed output of the proof. */ - function _deriveOutputRoot(OutputRootProof calldata _outputRootProof) + function _deriveOutputRoot(OutputRootProof memory _outputRootProof) internal pure returns (bytes32) @@ -71,12 +74,12 @@ library WithdrawalVerifier { function _verifyWithdrawalInclusion( bytes32 _withdrawalHash, bytes32 _withdrawerStorageRoot, - bytes calldata _withdrawalProof + bytes memory _withdrawalProof ) internal pure returns (bool) { bytes32 storageKey = keccak256( abi.encode( _withdrawalHash, - uint256(1) // The withdrawals mapping is at the second slot in the layout. + uint256(0) // The withdrawals mapping is at the first slot in the layout. ) ); diff --git a/packages/contracts/contracts/test/CommonTest.t.sol b/packages/contracts/contracts/test/CommonTest.t.sol index f3442f14ab14..353ce619f430 100644 --- a/packages/contracts/contracts/test/CommonTest.t.sol +++ b/packages/contracts/contracts/test/CommonTest.t.sol @@ -3,9 +3,29 @@ pragma solidity 0.8.10; /* Testing utilities */ import { Test } from "forge-std/Test.sol"; -import { Vm } from "forge-std/Vm.sol"; +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; +import { L1StandardBridge } from "../L1/L1StandardBridge.sol"; +import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; +import { OptimismMintableTokenFactory } from "../universal/OptimismMintableTokenFactory.sol"; +import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol"; +import { OptimismPortal } from "../L1/OptimismPortal.sol"; +import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; +import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol"; +import { L2CrossDomainMessenger } from "../L2/L2CrossDomainMessenger.sol"; +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; + +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { console } from "forge-std/console.sol"; contract CommonTest is Test { + address alice = address(128); + address bob = address(256); + address immutable ZERO_ADDRESS = address(0); address immutable NON_ZERO_ADDRESS = address(1); uint256 immutable NON_ZERO_VALUE = 100; @@ -13,4 +33,276 @@ contract CommonTest is Test { uint64 immutable NON_ZERO_GASLIMIT = 50000; bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); bytes NON_ZERO_DATA = hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"; + + function _setUp() public { + // Give alice and bob some ETH + vm.deal(alice, 1 << 16); + vm.deal(bob, 1 << 16); + + vm.label(alice, "alice"); + vm.label(bob, "bob"); + } +} +contract L2OutputOracle_Initializer is CommonTest { + // Test target + L2OutputOracle oracle; + + // Constructor arguments + address sequencer = 0x000000000000000000000000000000000000AbBa; + uint256 submissionInterval = 1800; + uint256 l2BlockTime = 2; + bytes32 genesisL2Output = keccak256(abi.encode(0)); + uint256 historicalTotalBlocks = 100; + + // Cache of the initial L2 timestamp + uint256 startingBlockTimestamp; + + // By default the first block has timestamp zero, which will cause underflows in the tests + uint256 initTime = 1000; + + function setUp() public virtual { + _setUp(); + + // Move time forward so we have a non-zero starting timestamp + vm.warp(initTime); + // Deploy the L2OutputOracle and transfer owernship to the sequencer + oracle = new L2OutputOracle( + submissionInterval, + l2BlockTime, + genesisL2Output, + historicalTotalBlocks, + initTime, + sequencer + ); + startingBlockTimestamp = block.timestamp; + } +} + +contract Messenger_Initializer is L2OutputOracle_Initializer { + OptimismPortal op; + L1CrossDomainMessenger L1Messenger; + L2CrossDomainMessenger L2Messenger; + L2ToL1MessagePasser messagePasser; + + event SentMessage( + address indexed target, + address sender, + bytes message, + uint256 messageNonce, + uint256 gasLimit + ); + + event WithdrawalInitiated( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data + ); + + event RelayedMessage(bytes32 indexed msgHash); + + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 mint, + uint256 value, + uint64 gasLimit, + bool isCreation, + bytes data + ); + + event WithdrawalFinalized(bytes32 indexed, bool success); + + function setUp() public virtual override { + super.setUp(); + + // Deploy the OptimismPortal + op = new OptimismPortal(oracle, 100); + vm.label(address(op), "OptimismPortal"); + + L1Messenger = new L1CrossDomainMessenger(); + L1Messenger.initialize(op); + + L2CrossDomainMessenger l2m = new L2CrossDomainMessenger(); + vm.etch(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, address(l2m).code); + L2Messenger = L2CrossDomainMessenger(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER); + + L2Messenger.initialize(address(L1Messenger)); + + // Set the L2ToL1MessagePasser at the correct address + L2ToL1MessagePasser mp = new L2ToL1MessagePasser(); + vm.etch(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER, address(mp).code); + messagePasser = L2ToL1MessagePasser(payable(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER)); + + vm.label( + Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER, + "L2ToL1MessagePasser" + ); + + vm.label( + Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, + "L2CrossDomainMessenger" + ); + + vm.label( + AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), + "L1CrossDomainMessenger_aliased" + ); + } } + +contract Bridge_Initializer is Messenger_Initializer { + L1StandardBridge L1Bridge; + L2StandardBridge L2Bridge; + OptimismMintableTokenFactory L2TokenFactory; + OptimismMintableTokenFactory L1TokenFactory; + ERC20 L1Token; + OptimismMintableERC20 L2Token; + ERC20 NativeL2Token; + OptimismMintableERC20 RemoteL1Token; + + event ETHDepositInitiated( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ETHWithdrawalFinalized( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ERC20DepositInitiated( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event ERC20WithdrawalFinalized( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event WithdrawalInitiated( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event DepositFinalized( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event DepositFailed( + address indexed _l1Token, + address indexed _l2Token, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event ETHBridgeInitiated( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ETHBridgeFinalized( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ERC20BridgeInitiated( + address indexed _localToken, + address indexed _remoteToken, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event ERC20BridgeFinalized( + address indexed _localToken, + address indexed _remoteToken, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + function setUp() public virtual override { + super.setUp(); + + vm.label( + Lib_PredeployAddresses.L2_STANDARD_BRIDGE, + "L2StandardBridge" + ); + vm.label( + Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY, + "L2StandardTokenFactory" + ); + + // Deploy the L1 bridge and initialize it with the address of the + // L1CrossDomainMessenger + L1Bridge = new L1StandardBridge(); + L1Bridge.initialize(payable(address(L1Messenger))); + vm.label(address(L1Bridge), "L1StandardBridge"); + + // Deploy the L2StandardBridge, move it to the correct predeploy + // address and then initialize it + L2StandardBridge l2B = new L2StandardBridge(); + vm.etch(Lib_PredeployAddresses.L2_STANDARD_BRIDGE, address(l2B).code); + L2Bridge = L2StandardBridge(payable(Lib_PredeployAddresses.L2_STANDARD_BRIDGE)); + L2Bridge.initialize(payable(address(L1Bridge))); + + // Set up the L2 mintable token factory + OptimismMintableTokenFactory factory = new OptimismMintableTokenFactory(); + vm.etch(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY, address(factory).code); + L2TokenFactory = OptimismMintableTokenFactory(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY); + L2TokenFactory.initialize(Lib_PredeployAddresses.L2_STANDARD_BRIDGE); + + L1Token = new ERC20("Native L1 Token", "L1T"); + + // Deploy the L2 ERC20 now + L2Token = OptimismMintableERC20(L2TokenFactory.createStandardL2Token( + address(L1Token), + string(abi.encodePacked("L2-", L1Token.name())), + string(abi.encodePacked("L2-", L1Token.symbol())) + )); + + NativeL2Token = new ERC20("Native L2 Token", "L2T"); + L1TokenFactory = new OptimismMintableTokenFactory(); + L1TokenFactory.initialize(address(L1Bridge)); + + RemoteL1Token = OptimismMintableERC20(L1TokenFactory.createStandardL2Token( + address(NativeL2Token), + string(abi.encodePacked("L1-", NativeL2Token.name())), + string(abi.encodePacked("L1-", NativeL2Token.symbol())) + )); + } +} + diff --git a/packages/contracts/contracts/test/CrossDomainHashing.t.sol b/packages/contracts/contracts/test/CrossDomainHashing.t.sol new file mode 100644 index 000000000000..bbb14b570eea --- /dev/null +++ b/packages/contracts/contracts/test/CrossDomainHashing.t.sol @@ -0,0 +1,71 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { CommonTest } from "./CommonTest.t.sol"; +import { CrossDomainHashing } from "../libraries/Lib_CrossDomainHashing.sol"; + +contract CrossDomainHashing_Test is CommonTest { + function test_nonceVersioning(uint240 _nonce, uint16 _version) external { + uint256 nonce = CrossDomainHashing.addVersionToNonce(uint256(_nonce), _version); + uint16 version = CrossDomainHashing.getVersionFromNonce(nonce); + assertEq(version, _version); + } + + // TODO(tynes): turn this into differential fuzzing + // it is very easy to do so with the typescript + function test_l2TransactionHash() external { + bytes32 l1BlockHash = 0xd1a498e053451fc90bd8a597051a1039010c8e55e2659b940d3070b326e4f4c5; + uint256 logIndex = 0x0; + address from = address(0xDe3829A23DF1479438622a08a116E8Eb3f620BB5); + address to = address(0xB7e390864a90b7b923C9f9310C6F98aafE43F707); + bool isCreate = false; + uint256 mint = 0xe043da617250000; + uint256 value = 0xde0b6b3a7640000; + uint256 gas = 0x2dc6c0; + bytes memory data = hex""; + + bytes32 sourceHash = CrossDomainHashing.sourceHash( + l1BlockHash, + logIndex + ); + + assertEq( + sourceHash, + 0x77fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd0735 + ); + + bytes memory raw = CrossDomainHashing.L2Transaction( + l1BlockHash, + logIndex, + from, + to, + isCreate, + mint, + value, + gas, + data + ); + + assertEq( + raw, + hex"7ef862a077fc5994647d128a4d131d273a5e89e0306aac472494068a4f1fceab83dd073594de3829a23df1479438622a08a116e8eb3f620bb594b7e390864a90b7b923c9f9310c6f98aafe43f707880e043da617250000880de0b6b3a7640000832dc6c080" + ); + + bytes32 digest = CrossDomainHashing.L2TransactionHash( + l1BlockHash, + logIndex, + from, + to, + isCreate, + mint, + value, + gas, + data + ); + + assertEq( + digest, + 0xf5f97d03e8be48a4b20ed70c9d8b11f1c851bf949bf602b7580985705bb09077 + ); + } +} diff --git a/packages/contracts/contracts/test/DepositFeed.t.sol b/packages/contracts/contracts/test/DepositFeed.t.sol deleted file mode 100644 index 4cc4ec87ba18..000000000000 --- a/packages/contracts/contracts/test/DepositFeed.t.sol +++ /dev/null @@ -1,218 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.10; - -/* Testing utilities */ -import { CommonTest } from "./CommonTest.t.sol"; - -/* Library Imports */ -import { - AddressAliasHelper -} from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; - -/* Target contract */ -import { DepositFeed } from "../L1/abstracts/DepositFeed.sol"; - -contract Target is DepositFeed {} - -contract DepositFeedTest is CommonTest { - - Target df; - - event TransactionDeposited( - address indexed from, - address indexed to, - uint256 mint, - uint256 value, - uint64 gasLimit, - bool isCreation, - bytes data - ); - - function setUp() external { - df = new Target(); - } - - // Test: depositTransaction fails when contract creation has a non-zero destination address - function test_depositTransaction_ContractCreationReverts() external { - vm.expectRevert(abi.encodeWithSignature("NonZeroCreationTarget()")); - df.depositTransaction(NON_ZERO_ADDRESS, NON_ZERO_VALUE, NON_ZERO_GASLIMIT, true, hex""); - } - - // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value - function test_depositTransaction_NoValueEOA() external { - // EOA emulation - vm.prank(address(this), address(this)); - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - address(this), - NON_ZERO_ADDRESS, - ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - - df.depositTransaction( - NON_ZERO_ADDRESS, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - } - - // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value - function test_depositTransaction_NoValueContract() external { - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - NON_ZERO_ADDRESS, - ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - - df.depositTransaction( - NON_ZERO_ADDRESS, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - } - - // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value - function test_depositTransaction_createWithZeroValueForEOA() external { - // EOA emulation - vm.prank(address(this), address(this)); - - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - address(this), - ZERO_ADDRESS, - ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA - ); - - df.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); - } - - // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value - function test_depositTransaction_createWithZeroValueForContract() external { - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - ZERO_ADDRESS, - ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA - ); - - df.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); - } - - // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH - function test_depositTransaction_withEthValueFromEOA() external { - // EOA emulation - vm.prank(address(this), address(this)); - - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - address(this), - NON_ZERO_ADDRESS, - NON_ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - - df.depositTransaction{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - assertEq(address(df).balance, NON_ZERO_VALUE); - } - - // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH - function test_depositTransaction_withEthValueFromContract() external { - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - NON_ZERO_ADDRESS, - NON_ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - - df.depositTransaction{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - } - - // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH - function test_depositTransaction_withEthValueAndEOAContractCreation() external { - // EOA emulation - vm.prank(address(this), address(this)); - - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - address(this), - ZERO_ADDRESS, - NON_ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - hex"" - ); - - df.depositTransaction{ value: NON_ZERO_VALUE }( - ZERO_ADDRESS, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - hex"" - ); - assertEq(address(df).balance, NON_ZERO_VALUE); - } - - // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH - function test_depositTransaction_withEthValueAndContractContractCreation() external { - vm.expectEmit(true, true, false, true); - emit TransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - ZERO_ADDRESS, - NON_ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA - ); - - df.depositTransaction{ value: NON_ZERO_VALUE }( - ZERO_ADDRESS, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA - ); - assertEq(address(df).balance, NON_ZERO_VALUE); - } -} diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts/contracts/test/L1Block.t.sol index 2707a18c0f51..12278001dded 100644 --- a/packages/contracts/contracts/test/L1Block.t.sol +++ b/packages/contracts/contracts/test/L1Block.t.sol @@ -1,12 +1,10 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -import { DSTest } from "forge-std/Test.sol"; -import { Vm } from "forge-std/Vm.sol"; +import { CommonTest } from "./CommonTest.t.sol"; import { L1Block } from "../L2/L1Block.sol"; -contract L1BLockTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); +contract L1BLockTest is CommonTest { L1Block lb; address depositor; bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1)); @@ -18,6 +16,16 @@ contract L1BLockTest is DSTest { lb.setL1BlockValues(uint64(1), uint64(2), 3, NON_ZERO_HASH, uint64(4)); } + function test_updatesValues(uint64 n, uint64 t, uint256 b, bytes32 h, uint64 s) external { + vm.prank(depositor); + lb.setL1BlockValues(n, t, b, h, s); + assertEq(lb.number(), n); + assertEq(lb.timestamp(), t); + assertEq(lb.basefee(), b); + assertEq(lb.hash(), h); + assertEq(lb.sequenceNumber(), s); + } + function test_number() external { assertEq(lb.number(), uint64(1)); } diff --git a/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol b/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol index bd86d37c30dc..b3eaf07f48e5 100644 --- a/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol +++ b/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol @@ -2,10 +2,13 @@ pragma solidity 0.8.10; /* Testing utilities */ -import { CommonTest } from "./CommonTest.t.sol"; +import { Messenger_Initializer } from "./CommonTest.t.sol"; import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; /* Libraries */ +import { + AddressAliasHelper +} from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; import { Lib_DefaultValues } from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; @@ -21,81 +24,116 @@ import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { OptimismPortal } from "../L1/OptimismPortal.sol"; +import { CrossDomainHashing } from "../libraries/Lib_CrossDomainHashing.sol"; + /* Target contract */ -import { L1CrossDomainMessenger } from "../L1/messaging/L1CrossDomainMessenger.sol"; -import { IDepositFeed } from "../L1/abstracts/IDepositFeed.sol"; +import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol"; import { ICrossDomainMessenger } from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol"; -contract L1CrossDomainMessenger_Test is CommonTest, L2OutputOracle_Initializer { - // Dependencies - OptimismPortal op; - // 'L2OutputOracle oracle' is declared in L2OutputOracle_Initializer - - event SentMessage( - address indexed target, - address sender, - bytes message, - uint256 messageNonce, - uint256 gasLimit - ); - event RelayedMessage(bytes32 indexed msgHash); - - // Contract under test - L1CrossDomainMessenger messenger; - +contract L1CrossDomainMessenger_Test is Messenger_Initializer { // Receiver address for testing address recipient = address(0xabbaacdc); - function setUp() external { - // new portal with small finalization window - op = new OptimismPortal(oracle, 100); - messenger = new L1CrossDomainMessenger(); - messenger.initialize(op, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER); + function setUp() public override { + super.setUp(); } // pause: should pause the contract when called by the current owner - function test_pause() external { - messenger.pause(); - assert(messenger.paused()); + function test_L1MessengerPause() external { + L1Messenger.pause(); + assert(L1Messenger.paused()); } // pause: should not pause the contract when called by account other than the owner - function testCannot_pause() external { + function testCannot_L1MessengerPause() external { vm.expectRevert("Ownable: caller is not the owner"); vm.prank(address(0xABBA)); - messenger.pause(); + L1Messenger.pause(); } - // sendMessage: should be able to send a single message - function test_sendMessage() external { - uint256 messageNonce = messenger.messageNonce(); - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - recipient, - address(this), - NON_ZERO_DATA, - messageNonce + // the version is encoded in the nonce + function test_L1MessengerMessageVersion() external { + assertEq( + CrossDomainHashing.getVersionFromNonce(L1Messenger.messageNonce()), + L1Messenger.MESSAGE_VERSION() ); + } + + // sendMessage: should be able to send a single message + // TODO: this same test needs to be done with the legacy message type + // by setting the message version to 0 + function test_L1MessengerSendMessage() external { + // deposit transaction on the optimism portal should be called vm.expectCall( address(op), abi.encodeWithSelector( - IDepositFeed.depositTransaction.selector, + OptimismPortal.depositTransaction.selector, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, 0, - NON_ZERO_GASLIMIT, + 100, false, - xDomainCalldata + CrossDomainHashing.getVersionedEncoding( + L1Messenger.messageNonce(), + alice, + recipient, + 0, + 100, + hex"ff" + ) ) ); - messenger.sendMessage(recipient, NON_ZERO_DATA, uint32(NON_ZERO_GASLIMIT)); + + // TransactionDeposited event + vm.expectEmit(true, true, true, true); + emit TransactionDeposited( + AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), + Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, + 0, + 0, + 100, + false, + CrossDomainHashing.getVersionedEncoding( + L1Messenger.messageNonce(), + alice, + recipient, + 0, + 100, + hex"ff" + ) + ); + + // SentMessage event + vm.expectEmit(true, true, true, true); + emit SentMessage( + recipient, + alice, + hex"ff", + L1Messenger.messageNonce(), + 100 + ); + + vm.prank(alice); + L1Messenger.sendMessage(recipient, hex"ff", uint32(100)); } // sendMessage: should be able to send the same message twice - function test_sendMessageTwice() external { - messenger.sendMessage(recipient, NON_ZERO_DATA, uint32(NON_ZERO_GASLIMIT)); - messenger.sendMessage(recipient, NON_ZERO_DATA, uint32(NON_ZERO_GASLIMIT)); + function test_L1MessengerTwiceSendMessage() external { + uint256 nonce = L1Messenger.messageNonce(); + L1Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); + L1Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); + // the nonce increments for each message sent + assertEq( + nonce + 2, + L1Messenger.messageNonce() + ); + } + + function test_L1MessengerXDomainSenderReverts() external { + vm.expectRevert("xDomainMessageSender is not set"); + L1Messenger.xDomainMessageSender(); } // xDomainMessageSender: should return the xDomainMsgSender address @@ -103,216 +141,81 @@ contract L1CrossDomainMessenger_Test is CommonTest, L2OutputOracle_Initializer { // function test_xDomainSenderSetCorrectly() external {} // relayMessage: should send a successful call to the target contract - function test_relayMessageSucceeds() external { + function test_L1MessengerRelayMessageSucceeds() external { address target = address(0xabcd); address sender = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; - bytes memory message = hex"1111"; - uint256 messageNonce = 42; - // The encoding we'll use to verify that the message was successful relayed - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - target, - sender, - message, - messageNonce - ); - // ensure that both the messenger and target receive a call - vm.expectCall( - address(messenger), - abi.encodeWithSelector( - L1CrossDomainMessenger.relayMessage.selector, - target, - sender, - message, - messageNonce - ) - ); - vm.expectCall(address(0xabcd), hex"1111"); + vm.expectCall(target, hex"1111"); + // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. vm.store(address(op), 0, bytes32(abi.encode(sender))); vm.prank(address(op)); + vm.expectEmit(true, true, true, true); - emit RelayedMessage(keccak256(xDomainCalldata)); - messenger.relayMessage(target, sender, message, messageNonce); - // Ensure the hash of the xDomainCalldata was stored in the successfulMessages mapping. - bytes32 messageHash = keccak256(xDomainCalldata); - assert(messenger.successfulMessages(messageHash)); - } + bytes32 hash = CrossDomainHashing.getVersionedHash( + 0, + sender, + target, + 0, + 0, + hex"1111" + ); + emit RelayedMessage(hash); - // relayMessage: should revert if still inside the fraud proof window - function test_relayMessageInsideFraudProofWindow() external { - bytes memory cd = abi.encodeWithSelector( - L1CrossDomainMessenger.relayMessage.selector, - address(42), - address(this), - hex"1111", - 0 + L1Messenger.relayMessage( + 0, // nonce + sender, + target, + 0, // value + 0, + hex"1111" ); - WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({ - version: bytes32(0), - stateRoot: bytes32(0), - withdrawerStorageRoot: bytes32(0), - latestBlockhash:bytes32(0) - }); - - bytes memory withdrawProof = bytes(hex""); - - // get the finalization window - uint256 window = op.FINALIZATION_PERIOD(); - assert(window != 0); - // set block.timestamp to be one less than the finalization window. - // the timestamp 0 is passed into `finalizeWithdrawalTransaction` - vm.warp(window - 1); - - // The OptimismPortal is responsible for keeping track - // of the finalization window - vm.expectRevert(abi.encodeWithSignature("NotYetFinal()")); - op.finalizeWithdrawalTransaction( - 0, // nonce - address(this), // sender - address(42), // target - 0, // value - 100000, // gasLimit - cd, // calldata - 0, // timestamp - outputRootProof, // outputRootProof - withdrawProof // withdrawProof - ); + // the message hash is in the successfulMessages mapping + assert(L1Messenger.successfulMessages(hash)); + // it is not in the received messages mapping + assertEq(L1Messenger.receivedMessages(hash), false); } // relayMessage: should revert if attempting to relay a message sent to an L1 system contract - function test_relayMessageToSystemContract() external { + function test_L1MessengerRelayMessageToSystemContract() external { // set the target to be the OptimismPortal address target = address(op); address sender = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; bytes memory message = hex"1111"; - uint256 messageNonce = 42; // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), 0, bytes32(abi.encode(sender))); vm.prank(address(op)); - vm.expectRevert("Cannot send L2->L1 messages to L1 system contracts."); - messenger.relayMessage(target, sender, message, messageNonce); - } + vm.expectRevert("Message cannot be replayed."); + L1Messenger.relayMessage(0, sender, target, 0, 0, message); - // relayMessage: should revert if provided an invalid output root proof - function test_revertOnInvalidOutputRootProof() external { - // create an invalid output root proof - WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({ - version: bytes32(0), - stateRoot: bytes32(0), - withdrawerStorageRoot: bytes32(0), - latestBlockhash:bytes32(0) - }); - bytes memory withdrawProof = bytes(hex""); - - vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); - op.finalizeWithdrawalTransaction( - 0, // nonce - address(this), // sender - address(42), // target - 0, // value - 100000, // gasLimit - bytes(""), // calldata - 0, // timestamp - outputRootProof, // outputRootProof - withdrawProof // withdrawProof - ); + vm.store(address(op), 0, bytes32(abi.encode(sender))); + vm.expectRevert("Message cannot be replayed."); + L1Messenger.relayMessage(0, sender, target, 0, 0, message); } // relayMessage: the xDomainMessageSender is reset to the original value - function test_xDomainMessageSenderResets() external { + function test_L1MessengerxDomainMessageSenderResets() external { vm.expectRevert("xDomainMessageSender is not set"); - messenger.xDomainMessageSender(); + L1Messenger.xDomainMessageSender(); address sender = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER; - bytes memory message = hex"1111"; - uint256 messageNonce = 42; - vm.store(address(op), 0, bytes32(abi.encode(sender))); vm.prank(address(op)); - messenger.relayMessage(address(0), sender, message, messageNonce); + L1Messenger.relayMessage(0, address(0), address(0), 0, 0, hex""); vm.expectRevert("xDomainMessageSender is not set"); - messenger.xDomainMessageSender(); - } - - // relayMessage: should revert if trying to send the same message twice - function test_relayShouldRevertSendingSameMessageTwice() external { - // TODO: this is a test on the L2CrossDomainMessenger + L1Messenger.xDomainMessageSender(); } // relayMessage: should revert if paused - function test_relayShouldRevertIfPaused() external { - vm.prank(messenger.owner()); - messenger.pause(); + function test_L1MessengerRelayShouldRevertIfPaused() external { + vm.prank(L1Messenger.owner()); + L1Messenger.pause(); vm.expectRevert("Pausable: paused"); - messenger.relayMessage(address(0), address(0), hex"", 0); - } - - // blockMessage and allowMessage: should revert if called by an account other than the owner - function test_relayMessageBlockingAuth() external { - bytes32 msgHash = bytes32(hex"ff"); - - vm.prank(address(0)); - vm.expectRevert("Ownable: caller is not the owner"); - messenger.blockMessage(msgHash); - assert(messenger.blockedMessages(msgHash) == false); - - vm.prank(address(0)); - vm.expectRevert("Ownable: caller is not the owner"); - messenger.allowMessage(msgHash); - assert(messenger.blockedMessages(msgHash) == false); - } - - // blockMessage and allowMessage: should revert if the message is blocked - function test_relayRevertOnBlockedMessage() external { - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - address(0), - address(0), - hex"ff", - 0 - ); - bytes32 msgHash = keccak256(xDomainCalldata); - - vm.prank(messenger.owner()); - messenger.blockMessage(msgHash); - - vm.store(address(op), 0, bytes32(abi.encode(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER))); - vm.prank(address(op)); - vm.expectRevert("Provided message has been blocked."); - messenger.relayMessage(address(0), address(0), hex"ff", 0); - } - - // blockMessage and allowMessage: should succeed if the message is blocked, then unblocked - function test_blockAndUnblockSuccessfulMessage() external { - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - address(0), - address(0), - hex"ff", - 0 - ); - bytes32 msgHash = keccak256(xDomainCalldata); - - vm.prank(messenger.owner()); - messenger.blockMessage(msgHash); - - vm.store(address(op), 0, bytes32(abi.encode(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER))); - vm.prank(address(op)); - vm.expectRevert("Provided message has been blocked."); - messenger.relayMessage(address(0), address(0), hex"ff", 0); - - vm.prank(messenger.owner()); - messenger.allowMessage(msgHash); - - vm.prank(address(op)); - - vm.expectEmit(true, true, true, true); - emit RelayedMessage(msgHash); - messenger.relayMessage(address(0), address(0), hex"ff", 0); + L1Messenger.relayMessage(0, address(0), address(0), 0, 0, hex""); } } diff --git a/packages/contracts/contracts/test/L1StandardBridge.t.sol b/packages/contracts/contracts/test/L1StandardBridge.t.sol index 89e709c5e299..6eeb1537c772 100644 --- a/packages/contracts/contracts/test/L1StandardBridge.t.sol +++ b/packages/contracts/contracts/test/L1StandardBridge.t.sol @@ -1,102 +1,406 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +import { Bridge_Initializer } from "./CommonTest.t.sol"; +import { StandardBridge } from "../universal/StandardBridge.sol"; +import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; +import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol"; import { Lib_PredeployAddresses } from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; - -import { IWithdrawer } from "../L2/IWithdrawer.sol"; -import { Withdrawer } from "../L2/Withdrawer.sol"; -import { L2StandardBridge } from "../L2/messaging/L2StandardBridge.sol"; -import { L1StandardBridge } from "../L1/messaging/L1StandardBridge.sol"; -import { OptimismPortal } from "../L1/OptimismPortal.sol"; -import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; -import { L2StandardTokenFactory } from "../L2/messaging/L2StandardTokenFactory.sol"; -import { IL2StandardTokenFactory } from "../L2/messaging/IL2StandardTokenFactory.sol"; -import { L2StandardERC20 } from "../L2/tokens/L2StandardERC20.sol"; -import { IL2StandardERC20 } from "../L2/tokens/IL2StandardERC20.sol"; - +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { CommonTest } from "./CommonTest.t.sol"; -import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; -import { LibRLP } from "./Lib_RLP.t.sol"; - -contract L1StandardBridge_Test is CommonTest, L2OutputOracle_Initializer { - OptimismPortal op; +import { stdStorage, StdStorage } from "forge-std/Test.sol"; - IWithdrawer W; - L1StandardBridge L1Bridge; - L2StandardBridge L2Bridge; - IL2StandardTokenFactory L2TokenFactory; - IL2StandardERC20 L2Token; +import { console } from "forge-std/console.sol"; - function setUp() external { - L1Bridge = new L1StandardBridge(); - L2Bridge = new L2StandardBridge(address(L1Bridge)); - op = new OptimismPortal(oracle, 100); +contract L1StandardBridge_Test is Bridge_Initializer { + using stdStorage for StdStorage; - L1Bridge.initialize(op, address(L2Bridge)); - - Withdrawer w = new Withdrawer(); - vm.etch(Lib_BedrockPredeployAddresses.WITHDRAWER, address(w).code); - W = IWithdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER); - - L2StandardTokenFactory factory = new L2StandardTokenFactory(); - vm.etch(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY, address(factory).code); - L2TokenFactory = IL2StandardTokenFactory(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY); + function setUp() public override { + super.setUp(); + } - ERC20 token = new ERC20("Test Token", "TT"); + function test_initialize() external { + assertEq( + address(L1Bridge.messenger()), + address(L1Messenger) + ); - // Deploy the L2 ERC20 now - L2TokenFactory.createStandardL2Token( - address(token), - string(abi.encodePacked("L2-", token.name())), - string(abi.encodePacked("L2-", token.symbol())) + assertEq( + address(L1Bridge.otherBridge()), + Lib_PredeployAddresses.L2_STANDARD_BRIDGE ); - L2Token = IL2StandardERC20( - LibRLP.computeAddress(address(L2TokenFactory), 0) + assertEq( + address(L2Bridge), + Lib_PredeployAddresses.L2_STANDARD_BRIDGE ); } - function test_L1BridgeSetsPortalAndL2Bridge() external { - OptimismPortal portal = L1Bridge.optimismPortal(); - address bridge = L1Bridge.l2TokenBridge(); + // receive + // - can accept ETH + function test_receive() external { + assertEq(address(op).balance, 0); + + vm.expectEmit(true, true, true, true); + emit ETHBridgeInitiated(alice, alice, 100, hex""); + + vm.expectCall( + address(L1Messenger), + abi.encodeWithSelector( + CrossDomainMessenger.sendMessage.selector, + address(L2Bridge), + abi.encodeWithSelector( + StandardBridge.finalizeBridgeETH.selector, + alice, + alice, + 100, + hex"" + ), + 200_000 + ) + ); - assertEq(address(portal), address(op)); - assertEq(bridge, address(L2Bridge)); + vm.prank(alice, alice); + address(L1Bridge).call{ value: 100 }(hex""); + assertEq(address(op).balance, 100); } - // receive - // - can accept ETH // depositETH // - emits ETHDepositInitiated // - calls optimismPortal.depositTransaction // - only EOA // - ETH ends up in the optimismPortal + function test_depositETH() external { + assertEq(address(op).balance, 0); + + vm.expectEmit(true, true, true, true); + emit ETHBridgeInitiated(alice, alice, 500, hex"ff"); + + vm.expectCall( + address(L1Messenger), + abi.encodeWithSelector( + CrossDomainMessenger.sendMessage.selector, + address(L2Bridge), + abi.encodeWithSelector( + StandardBridge.finalizeBridgeETH.selector, + alice, + alice, + 500, + hex"ff" + ), + 50000 + ) + ); + + vm.prank(alice, alice); + L1Bridge.depositETH{ value: 500 }(50000, hex"ff"); + assertEq(address(op).balance, 500); + } + + function test_onlyEOADepositETH() external { + // turn alice into a contract + vm.etch(alice, address(L1Token).code); + + vm.expectRevert("Account not EOA"); + vm.prank(alice); + L1Bridge.depositETH{ value: 1 }(300, hex""); + } + // depositETHTo // - emits ETHDepositInitiated // - calls optimismPortal.depositTransaction // - EOA or contract can call // - ETH ends up in the optimismPortal + function test_depositETHTo() external { + assertEq(address(op).balance, 0); + + vm.expectEmit(true, true, true, true); + emit ETHDepositInitiated(alice, bob, 600, hex"dead"); + + vm.expectEmit(true, true, true, true); + emit ETHBridgeInitiated(alice, bob, 600, hex"dead"); + + // depositETHTo on the L1 bridge should be called + vm.expectCall( + address(L1Bridge), + abi.encodeWithSelector( + L1Bridge.depositETHTo.selector, + bob, + 1000, + hex"dead" + ) + ); + + // the L1 bridge should call + // L1CrossDomainMessenger.sendMessage + vm.expectCall( + address(L1Messenger), + abi.encodeWithSelector( + CrossDomainMessenger.sendMessage.selector, + address(L2Bridge), + abi.encodeWithSelector( + StandardBridge.finalizeBridgeETH.selector, + alice, + bob, + 600, + hex"dead" + ), + 1000 + ) + ); + + // TODO: assert on OptimismPortal being called + // and the event being emitted correctly + + // deposit eth to bob + vm.prank(alice, alice); + L1Bridge.depositETHTo{ value: 600 }(bob, 1000, hex"dead"); + } + // depositERC20 // - updates bridge.deposits // - emits ERC20DepositInitiated // - calls optimismPortal.depositTransaction // - only callable by EOA + function test_depositERC20() external { + vm.expectEmit(true, true, true, true); + emit ERC20DepositInitiated( + address(L1Token), + address(L2Token), + alice, + alice, + 100, + hex"" + ); + + deal(address(L1Token), alice, 100000, true); + + vm.prank(alice); + L1Token.approve(address(L1Bridge), type(uint256).max); + + // The L1Bridge should transfer alice's tokens + // to itself + vm.expectCall( + address(L1Token), + abi.encodeWithSelector( + ERC20.transferFrom.selector, + alice, + address(L1Bridge), + 100 + ) + ); + + // TODO: optimismPortal.depositTransaction call + event + + vm.prank(alice); + L1Bridge.depositERC20( + address(L1Token), + address(L2Token), + 100, + 10000, + hex"" + ); + + assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100); + } + + function test_onlyEOADepositERC20() external { + // turn alice into a contract + vm.etch(alice, hex"ffff"); + + vm.expectRevert("Account not EOA"); + vm.prank(alice, alice); + L1Bridge.depositERC20( + address(0), + address(0), + 100, + 100, + hex"" + ); + } + // depositERC20To // - updates bridge.deposits // - emits ERC20DepositInitiated // - calls optimismPortal.depositTransaction - // - reverts if called by EOA // - callable by a contract + function test_depositERC20To() external { + vm.expectEmit(true, true, true, true); + emit ERC20DepositInitiated( + address(L1Token), + address(L2Token), + alice, + bob, + 1000, + hex"" + ); + + deal(address(L1Token), alice, 100000, true); + + vm.prank(alice); + L1Token.approve(address(L1Bridge), type(uint256).max); + + vm.expectCall( + address(L1Token), + abi.encodeWithSelector( + ERC20.transferFrom.selector, + alice, + address(L1Bridge), + 1000 + ) + ); + + vm.prank(alice); + L1Bridge.depositERC20To( + address(L1Token), + address(L2Token), + bob, + 1000, + 10000, + hex"" + ); + + assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000); + } + // finalizeETHWithdrawal // - emits ETHWithdrawalFinalized // - only callable by L2 bridge + function test_finalizeETHWithdrawal() external { + uint256 aliceBalance = alice.balance; + + vm.expectEmit(true, true, true, true); + emit ETHWithdrawalFinalized( + alice, + alice, + 100, + hex"" + ); + + vm.expectCall( + alice, + hex"" + ); + + vm.mockCall( + address(L1Bridge.messenger()), + abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(address(L1Bridge.otherBridge())) + ); + // ensure that the messenger has ETH to call with + vm.deal(address(L1Bridge.messenger()), 100); + vm.prank(address(L1Bridge.messenger())); + L1Bridge.finalizeETHWithdrawal{ value: 100 }( + alice, + alice, + 100, + hex"" + ); + + assertEq(address(L1Bridge.messenger()).balance, 0); + assertEq(aliceBalance + 100, alice.balance); + } + // finalizeERC20Withdrawal // - updates bridge.deposits // - emits ERC20WithdrawalFinalized // - only callable by L2 bridge + function test_finalizeERC20Withdrawal() external { + deal(address(L1Token), address(L1Bridge), 100, true); + + uint256 slot = stdstore + .target(address(L1Bridge)) + .sig("deposits(address,address)") + .with_key(address(L1Token)) + .with_key(address(L2Token)) + .find(); + + // Give the L1 bridge some ERC20 tokens + vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100))); + assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100); + + vm.expectEmit(true, true, true, true); + emit ERC20WithdrawalFinalized( + address(L1Token), + address(L2Token), + alice, + alice, + 100, + hex"" + ); + + vm.expectCall( + address(L1Token), + abi.encodeWithSelector( + ERC20.transfer.selector, + alice, + 100 + ) + ); + + vm.mockCall( + address(L1Bridge.messenger()), + abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(address(L1Bridge.otherBridge())) + ); + vm.prank(address(L1Bridge.messenger())); + L1Bridge.finalizeERC20Withdrawal( + address(L1Token), + address(L2Token), + alice, + alice, + 100, + hex"" + ); + + assertEq(L1Token.balanceOf(address(L1Bridge)), 0); + assertEq(L1Token.balanceOf(address(alice)), 100); + } + + function test_onlyPortalFinalizeERC20Withdrawal() external { + vm.mockCall( + address(L1Bridge.messenger()), + abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(address(L1Bridge.otherBridge())) + ); + vm.prank(address(28)); + vm.expectRevert("Could not authenticate bridge message."); + L1Bridge.finalizeERC20Withdrawal( + address(L1Token), + address(L2Token), + alice, + alice, + 100, + hex"" + ); + } + + function test_onlyL2BridgeFinalizeERC20Withdrawal() external { + vm.mockCall( + address(L1Bridge.messenger()), + abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(address(address(0))) + ); + vm.prank(address(L1Bridge.messenger())); + vm.expectRevert("Could not authenticate bridge message."); + L1Bridge.finalizeERC20Withdrawal( + address(L1Token), + address(L2Token), + alice, + alice, + 100, + hex"" + ); + } + // donateETH // - can send ETH to the contract + function test_donateETH() external { + assertEq(address(L1Bridge).balance, 0); + vm.prank(alice); + L1Bridge.donateETH{ value: 1000 }(); + assertEq(address(L1Bridge).balance, 1000); + } } diff --git a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol index 708839aa62c5..2c427b71e99e 100644 --- a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol +++ b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol @@ -1,8 +1,7 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -import { CommonTest } from "./CommonTest.t.sol"; -import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; +import { Messenger_Initializer } from "./CommonTest.t.sol"; import { Lib_PredeployAddresses @@ -12,13 +11,12 @@ import { } from "@eth-optimism/contracts/libraries/bridge/Lib_CrossDomainUtils.sol"; import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; +import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -import { OptimismPortal } from "../L1/OptimismPortal.sol"; -import { L2CrossDomainMessenger } from "../L2/messaging/L2CrossDomainMessenger.sol"; -import { L1CrossDomainMessenger } from "../L1/messaging/L1CrossDomainMessenger.sol"; -import { Withdrawer } from "../L2/Withdrawer.sol"; -import { IWithdrawer } from "../L2/IWithdrawer.sol"; +import { L2CrossDomainMessenger } from "../L2/L2CrossDomainMessenger.sol"; +import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol"; import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; +import { CrossDomainHashing } from "../libraries/Lib_CrossDomainHashing.sol"; import { Lib_DefaultValues @@ -26,180 +24,156 @@ import { import { console } from "forge-std/console.sol"; -contract L2CrossDomainMessenger_Test is CommonTest, L2OutputOracle_Initializer { - - // Dependencies - OptimismPortal op; - - IWithdrawer W; - L1CrossDomainMessenger L1Messenger; - L2CrossDomainMessenger L2Messenger; - - event SentMessage( - address indexed target, - address sender, - bytes message, - uint256 messageNonce, - uint256 gasLimit - ); - - event WithdrawalInitiated( - uint256 indexed nonce, - address indexed sender, - address indexed target, - uint256 value, - uint256 gasLimit, - bytes data - ); - - function setUp() external { - op = new OptimismPortal(oracle, 100); - L1Messenger = new L1CrossDomainMessenger(); - L1Messenger.initialize(op, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER); - - L2Messenger = new L2CrossDomainMessenger(address(L1Messenger)); - - // Deploy the Withdrawer and then get its code to set at the - // correct address - Withdrawer w = new Withdrawer(); - bytes memory code = address(w).code; - vm.etch(Lib_BedrockPredeployAddresses.WITHDRAWER, code); - W = IWithdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER); +contract L2CrossDomainMessenger_Test is Messenger_Initializer { + // Receiver address for testing + address recipient = address(0xabbaacdc); + + function setUp() public override { + super.setUp(); } - // xDomainMessageSender: should return correct L1Messenger address - function test_L2MessengerCorrectL1Messenger() external { - address l1 = L2Messenger.l1CrossDomainMessenger(); - assertEq(l1, address(L1Messenger)); + function test_L2MessengerPause() external { + L2Messenger.pause(); + assert(L2Messenger.paused()); } - // xDomainMessageSender: should return the xDomainMsgSender address - function test_L2MessengerxDomainMsgSender() external { - vm.expectRevert("xDomainMessageSender is not set"); - L2Messenger.xDomainMessageSender(); + function testCannot_L2MessengerPause() external { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(address(0xABBA)); + L2Messenger.pause(); + } - bytes32 slot = vm.load(address(L2Messenger), bytes32(uint256(4))); - assertEq(address(uint160(uint256(slot))), Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER); + function test_L2MessengerMessageVersion() external { + assertEq( + CrossDomainHashing.getVersionFromNonce(L2Messenger.messageNonce()), + L2Messenger.MESSAGE_VERSION() + ); } - // sendMessage: should be able to send a single message function test_L2MessengerSendMessage() external { - address target = address(0); - bytes memory message = hex""; - uint32 gasLimit = 1000; - - uint256 nonce = W.nonce(); - address sender = address(L2Messenger); + vm.expectCall( + address(messagePasser), + abi.encodeWithSelector( + L2ToL1MessagePasser.initiateWithdrawal.selector, + address(L1Messenger), + 100, + CrossDomainHashing.getVersionedEncoding( + L2Messenger.messageNonce(), + alice, + recipient, + 0, + 100, + hex"ff" + ) + ) + ); + // WithdrawalInitiated event vm.expectEmit(true, true, true, true); - emit SentMessage(target, address(this), message, nonce, gasLimit); - vm.expectEmit(true, true, true, true); - emit WithdrawalInitiated(nonce, sender, address(L1Messenger), 0, gasLimit, message); + emit WithdrawalInitiated( + messagePasser.nonce(), + address(L2Messenger), + address(L1Messenger), + 0, + 100, + CrossDomainHashing.getVersionedEncoding( + L2Messenger.messageNonce(), + alice, + recipient, + 0, + 100, + hex"ff" + ) + ); - L2Messenger.sendMessage(target, message, gasLimit); + vm.prank(alice); + L2Messenger.sendMessage(recipient, hex"ff", uint32(100)); } - // sendMessage: should be able to send the same message twice - function test_L2MessengerSendSameMessageTwice() external { - L2Messenger.sendMessage(address(0), hex"", 1000); - L2Messenger.sendMessage(address(0), hex"", 1000); - // TODO: assertion on events, nonce increments + function test_L2MessengerTwiceSendMessage() external { + uint256 nonce = L2Messenger.messageNonce(); + L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); + L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); + // the nonce increments for each message sent + assertEq( + nonce + 2, + L2Messenger.messageNonce() + ); } - // relayMessage: should revert if the L1 message sender is not the L1CrossDomainMessenger - function test_L2MessengerRevertInvalidL1XDomainMessenger() external { - vm.expectRevert("Provided message could not be verified."); - vm.prank(address(0)); - L2Messenger.relayMessage( - address(0), - address(0), - hex"", - 0 - ); + function test_L2MessengerXDomainSenderReverts() external { + vm.expectRevert("xDomainMessageSender is not set"); + L2Messenger.xDomainMessageSender(); } - // relayMessage: should send a call to the target contract - function test_L2MessengerCallsTarget() external { - address target = address(4); + function test_L2MessengerRelayMessageSucceeds() external { + address target = address(0xabcd); + address sender = address(L1Messenger); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); - vm.expectCall(target, hex"ff"); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage( + vm.expectCall(target, hex"1111"); + + vm.prank(caller); + + vm.expectEmit(true, true, true, true); + + bytes32 hash = CrossDomainHashing.getVersionedHash( + 0, + sender, target, - address(this), - hex"ff", - 1000 + 0, + 0, + hex"1111" ); - } - // relayMessage: the xDomainMessageSender is reset to the original value - function test_L2MessengerXDomainMessageSenderReset() external { - vm.expectRevert("xDomainMessageSender is not set"); - L2Messenger.xDomainMessageSender(); + emit RelayedMessage(hash); - vm.expectCall(address(4), hex"ff"); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); L2Messenger.relayMessage( - address(4), - address(this), - hex"ff", - 1000 + 0, // nonce + sender, + target, + 0, // value + 0, + hex"1111" ); - vm.expectRevert("xDomainMessageSender is not set"); - L2Messenger.xDomainMessageSender(); - bytes32 slot = vm.load(address(L2Messenger), bytes32(uint256(4))); - assertEq(address(uint160(uint256(slot))), Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER); + // the message hash is in the successfulMessages mapping + assert(L2Messenger.successfulMessages(hash)); + // it is not in the received messages mapping + assertEq(L2Messenger.receivedMessages(hash), false); } - // relayMessage: should revert if trying to send the same message twice - function test_L2MessengerCannotRelaySameMessageTwice() external { - vm.expectCall(address(4), hex"ff"); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage( - address(4), - address(this), - hex"ff", - 1000 - ); + // relayMessage: should revert if attempting to relay a message sent to an L1 system contract + function test_L2MessengerRelayMessageToSystemContract() external { + address target = address(messagePasser); + address sender = address(L1Messenger); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + bytes memory message = hex"1111"; - vm.expectRevert("Provided message has already been received."); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage( - address(4), - address(this), - hex"ff", - 1000 - ); + vm.prank(caller); + vm.expectRevert("Message cannot be replayed."); + L1Messenger.relayMessage(0, sender, target, 0, 0, message); } - // relayMessage: should not make a call if the target is the L2 MessagePasser - function test_L2MessengerCannotCallL2MessagePasser() external { - address target = Lib_BedrockPredeployAddresses.WITHDRAWER; + // relayMessage: the xDomainMessageSender is reset to the original value + function test_L2MessengerxDomainMessageSenderResets() external { + vm.expectRevert("xDomainMessageSender is not set"); + L2Messenger.xDomainMessageSender(); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage( - target, - address(this), - hex"ff", - 1000 - ); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + vm.prank(caller); + L2Messenger.relayMessage(0, address(0), address(0), 0, 0, hex""); - bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( - target, - address(this), - hex"ff", - 1000 - ); - bytes32 hash = keccak256(xDomainCalldata); - assert(L2Messenger.successfulMessages(hash) == true); + vm.expectRevert("xDomainMessageSender is not set"); + L2Messenger.xDomainMessageSender(); + } - bytes32 relayId = keccak256(abi.encodePacked( - xDomainCalldata, - AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), - block.number - )); + // relayMessage: should revert if paused + function test_L2MessengerRelayShouldRevertIfPaused() external { + vm.prank(L2Messenger.owner()); + L2Messenger.pause(); - assert(L2Messenger.relayedMessages(relayId) == false); + vm.expectRevert("Pausable: paused"); + L2Messenger.relayMessage(0, address(0), address(0), 0, 0, hex""); } } diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index 3a45339e7a33..b012189c8cea 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -1,49 +1,16 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -/* Testing utilities */ -import { CommonTest } from "./CommonTest.t.sol"; - +import { L2OutputOracle_Initializer } from "./CommonTest.t.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -contract L2OutputOracle_Initializer is CommonTest { - // Utility variables - uint256 appendedTimestamp; - - // Test target - L2OutputOracle oracle; - - // Constructor arguments - address sequencer = 0x000000000000000000000000000000000000AbBa; - uint256 submissionInterval = 1800; - uint256 l2BlockTime = 2; - bytes32 genesisL2Output = keccak256(abi.encode(0)); - uint256 historicalTotalBlocks = 100; - - // Cache of the initial L2 timestamp - uint256 startingBlockTimestamp; - - // By default the first block has timestamp zero, which will cause underflows in the tests - uint256 initTime = 1000; - - constructor() { - // Move time forward so we have a non-zero starting timestamp - vm.warp(initTime); - // Deploy the L2OutputOracle and transfer owernship to the sequencer - oracle = new L2OutputOracle( - submissionInterval, - l2BlockTime, - genesisL2Output, - historicalTotalBlocks, - initTime, - sequencer - ); - startingBlockTimestamp = block.timestamp; +contract L2OutputOracleTest is L2OutputOracle_Initializer { + bytes32 appendedOutput1 = keccak256(abi.encode(1)); + + function setUp() public override { + super.setUp(); } -} -// Define this test in a standalone contract to ensure it runs immediately after the constructor. -contract L2OutputOracleTest_Constructor is L2OutputOracle_Initializer { function test_constructor() external { assertEq(oracle.owner(), sequencer); assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval); @@ -51,20 +18,10 @@ contract L2OutputOracleTest_Constructor is L2OutputOracle_Initializer { assertEq(oracle.HISTORICAL_TOTAL_BLOCKS(), historicalTotalBlocks); assertEq(oracle.latestBlockTimestamp(), startingBlockTimestamp); assertEq(oracle.STARTING_BLOCK_TIMESTAMP(), startingBlockTimestamp); - assertEq(oracle.getL2Output(startingBlockTimestamp), genesisL2Output); - } -} - -contract L2OutputOracleTest is L2OutputOracle_Initializer { - bytes32 appendedOutput1 = keccak256(abi.encode(1)); - - constructor() { - appendedTimestamp = oracle.nextTimestamp(); - // Warp to after the timestamp we'll append - vm.warp(appendedTimestamp + 1); - vm.prank(sequencer); - oracle.appendL2Output(appendedOutput1, appendedTimestamp, 0, 0); + L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(startingBlockTimestamp); + assertEq(proposal.outputRoot, genesisL2Output); + assertEq(proposal.timestamp, initTime); } /**************** @@ -73,13 +30,30 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // Test: latestBlockTimestamp() should return the correct value function test_latestBlockTimestamp() external { + uint256 appendedTimestamp = oracle.nextTimestamp(); + + // Warp to after the timestamp we'll append + vm.warp(appendedTimestamp + 1); + vm.prank(sequencer); + oracle.appendL2Output(appendedOutput1, appendedTimestamp, 0, 0); assertEq(oracle.latestBlockTimestamp(), appendedTimestamp); } // Test: getL2Output() should return the correct value function test_getL2Output() external { - assertEq(oracle.getL2Output(appendedTimestamp), appendedOutput1); - assertEq(oracle.getL2Output(appendedTimestamp + 1), 0); + uint256 nextTimestamp = oracle.nextTimestamp(); + + vm.warp(nextTimestamp + 1); + vm.prank(sequencer); + oracle.appendL2Output(appendedOutput1, nextTimestamp, 0, 0); + + L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(nextTimestamp); + assertEq(proposal.outputRoot, appendedOutput1); + assertEq(proposal.timestamp, nextTimestamp + 1); + + L2OutputOracle.OutputProposal memory proposal2 = oracle.getL2Output(0); + assertEq(proposal2.outputRoot, bytes32(0)); + assertEq(proposal2.timestamp, 0); } @@ -88,7 +62,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq( oracle.nextTimestamp(), // The return value should match this arithmetic - initTime + submissionInterval * 2 + oracle.latestBlockTimestamp() + oracle.SUBMISSION_INTERVAL() ); } @@ -109,6 +83,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { expected = historicalTotalBlocks + 1 + (33 / l2BlockTime); assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); } + // Test: computeL2BlockNumber() fails with a blockNumber from before the startingBlockTimestamp function testCannot_computePreHistoricalL2BlockNumber() external { bytes memory expectedError = "Timestamp prior to startingBlockTimestamp"; @@ -123,10 +98,12 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { // Test: appendL2Output succeeds when given valid input, and no block hash and number are // specified. - function test_appendingAnotherOutput() external { + function test_appendingAnotherOutput() public { bytes32 appendedOutput2 = keccak256(abi.encode(2)); uint256 nextTimestamp = oracle.nextTimestamp(); + uint256 appendedTimestamp = oracle.latestBlockTimestamp(); + // Ensure the submissionInterval is enforced assertEq(nextTimestamp, appendedTimestamp + submissionInterval); @@ -164,6 +141,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { function testCannot_appendOutputIfNotSequencer() external { uint256 nextTimestamp = oracle.nextTimestamp(); + vm.prank(address(128)); vm.warp(nextTimestamp + 1); vm.expectRevert("Ownable: caller is not the owner"); oracle.appendL2Output(nonZeroHash, nextTimestamp, 0, 0); @@ -230,16 +208,27 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { * Delete Tests * ****************/ - event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l2timestamp); + event l2OutputDeleted( + bytes32 indexed _l2Output, + uint256 indexed _l1Timestamp, + uint256 indexed _l2timestamp + ); + function test_deleteL2Output() external { + test_appendingAnotherOutput(); + uint256 latestBlockTimestamp = oracle.latestBlockTimestamp(); - bytes32 outputToDelete = oracle.getL2Output(latestBlockTimestamp); - bytes32 newLatestOutput = oracle.getL2Output(latestBlockTimestamp - submissionInterval); + L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output(latestBlockTimestamp); + L2OutputOracle.OutputProposal memory newLatestOutput = oracle.getL2Output(latestBlockTimestamp - submissionInterval); vm.prank(sequencer); vm.expectEmit(true, true, false, false); - emit l2OutputDeleted(outputToDelete, latestBlockTimestamp); - oracle.deleteL2Output(outputToDelete); + emit l2OutputDeleted( + proposalToDelete.outputRoot, + proposalToDelete.timestamp, + latestBlockTimestamp + ); + oracle.deleteL2Output(proposalToDelete); // validate latestBlockTimestamp has been reduced uint256 latestBlockTimestampAfter = oracle.latestBlockTimestamp(); @@ -248,27 +237,28 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { latestBlockTimestampAfter ); + L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockTimestampAfter); // validate that the new latest output is as expected. - assertEq( - newLatestOutput, - oracle.getL2Output(latestBlockTimestampAfter) - ); + assertEq(newLatestOutput.outputRoot, proposal.outputRoot); + assertEq(newLatestOutput.timestamp, proposal.timestamp); } function testCannot_deleteL2Output_ifNotSequencer() external { uint256 latestBlockTimestamp = oracle.latestBlockTimestamp(); - bytes32 outputToDelete = oracle.getL2Output(latestBlockTimestamp); + L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockTimestamp); vm.expectRevert("Ownable: caller is not the owner"); - oracle.deleteL2Output(outputToDelete); + oracle.deleteL2Output(proposal); } - function testCannot_deleteL2Output_ifWrongOutput() external { + function testCannot_deleteWrongL2Output() external { + test_appendingAnotherOutput(); + uint256 previousBlockTimestamp = oracle.latestBlockTimestamp() - submissionInterval; - bytes32 outputToDelete = oracle.getL2Output(previousBlockTimestamp); + L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output(previousBlockTimestamp); vm.prank(sequencer); vm.expectRevert("Can only delete the most recent output."); - oracle.deleteL2Output(outputToDelete); + oracle.deleteL2Output(proposalToDelete); } } diff --git a/packages/contracts/contracts/test/L2StandardBridge.t.sol b/packages/contracts/contracts/test/L2StandardBridge.t.sol index 777c10d08289..2ce6a036090f 100644 --- a/packages/contracts/contracts/test/L2StandardBridge.t.sol +++ b/packages/contracts/contracts/test/L2StandardBridge.t.sol @@ -1,83 +1,113 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -import { - Lib_PredeployAddresses -} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; - -import { IWithdrawer } from "../L2/IWithdrawer.sol"; -import { Withdrawer } from "../L2/Withdrawer.sol"; -import { L2StandardBridge } from "../L2/messaging/L2StandardBridge.sol"; -import { L1StandardBridge } from "../L1/messaging/L1StandardBridge.sol"; -import { OptimismPortal } from "../L1/OptimismPortal.sol"; -import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; -import { L2StandardTokenFactory } from "../L2/messaging/L2StandardTokenFactory.sol"; -import { IL2StandardTokenFactory } from "../L2/messaging/IL2StandardTokenFactory.sol"; -import { L2StandardERC20 } from "../L2/tokens/L2StandardERC20.sol"; -import { IL2StandardERC20 } from "../L2/tokens/IL2StandardERC20.sol"; - -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { CommonTest } from "./CommonTest.t.sol"; -import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; -import { LibRLP } from "./Lib_RLP.t.sol"; - +import { Bridge_Initializer } from "./CommonTest.t.sol"; +import { stdStorage, StdStorage } from "forge-std/Test.sol"; +import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol"; import { console } from "forge-std/console.sol"; -contract L2StandardBridge_Test is CommonTest, L2OutputOracle_Initializer { - OptimismPortal op; - - IWithdrawer W; - L1StandardBridge L1Bridge; - L2StandardBridge L2Bridge; - IL2StandardTokenFactory L2TokenFactory; - IL2StandardERC20 L2Token; - - function setUp() external { - L1Bridge = new L1StandardBridge(); - L2Bridge = new L2StandardBridge(address(L1Bridge)); - op = new OptimismPortal(oracle, 100); - - L1Bridge.initialize(op, address(L2Bridge)); - - Withdrawer w = new Withdrawer(); - vm.etch(Lib_BedrockPredeployAddresses.WITHDRAWER, address(w).code); - W = IWithdrawer(Lib_BedrockPredeployAddresses.WITHDRAWER); - - L2StandardTokenFactory factory = new L2StandardTokenFactory(); - vm.etch(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY, address(factory).code); - L2TokenFactory = IL2StandardTokenFactory(Lib_PredeployAddresses.L2_STANDARD_TOKEN_FACTORY); +contract L2StandardBridge_Test is Bridge_Initializer { + using stdStorage for StdStorage; - ERC20 token = new ERC20("Test Token", "TT"); + function setUp() public override { + super.setUp(); + } - // Deploy the L2 ERC20 now - L2TokenFactory.createStandardL2Token( - address(token), - string(abi.encodePacked("L2-", token.name())), - string(abi.encodePacked("L2-", token.symbol())) + function test_initialize() external { + assertEq( + address(L2Bridge.messenger()), + address(L2Messenger) ); - L2Token = IL2StandardERC20( - LibRLP.computeAddress(address(L2TokenFactory), 0) + assertEq( + address(L2Bridge.otherBridge()), + address(L1Bridge) ); } - function test_L2BridgeCorrectL1Bridge() external { - address l1Bridge = L2Bridge.l1TokenBridge(); - assertEq(address(L1Bridge), l1Bridge); + // receive + // - can accept ETH + function test_receive() external { + assertEq(address(messagePasser).balance, 0); + + vm.expectEmit(true, true, true, true); + emit ETHBridgeInitiated(alice, alice, 100, hex""); + + // TODO: L2Messenger should be called + // TODO: L2ToL1MessagePasser should be called + // TODO: withdrawal hash should be computed correctly + // TODO: events from each contract + + vm.prank(alice, alice); + address(L2Bridge).call{ value: 100 }(hex""); + assertEq(address(messagePasser).balance, 100); } // withdraw // - token is burned // - emits WithdrawalInitiated // - calls Withdrawer.initiateWithdrawal + function test_withdraw() external { + // Alice has 100 L2Token + deal(address(L2Token), alice, 100, true); + assertEq(L2Token.balanceOf(alice), 100); + + vm.prank(alice, alice); + L2Bridge.withdraw( + address(L2Token), + 100, + 1000, + hex"" + ); + + // TODO: events and calls + + assertEq(L2Token.balanceOf(alice), 0); + } + // withdrawTo // - token is burned // - emits WithdrawalInitiated w/ correct recipient // - calls Withdrawer.initiateWithdrawal + function test_withdrawTo() external { + deal(address(L2Token), alice, 100, true); + + vm.prank(alice, alice); + L2Bridge.withdrawTo( + address(L2Token), + bob, + 100, + 1000, + hex"" + ); + + // TODO: events and calls + + assertEq(L2Token.balanceOf(alice), 0); + } + // finalizeDeposit // - only callable by l1TokenBridge // - supported token pair emits DepositFinalized // - invalid deposit emits DepositFailed // - invalid deposit calls Withdrawer.initiateWithdrawal + function test_finalizeDeposit() external { + // TODO: events and calls + + vm.mockCall( + address(L2Bridge.messenger()), + abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(address(L2Bridge.otherBridge())) + ); + vm.prank(address(L2Messenger)); + L2Bridge.finalizeDeposit( + address(L1Token), + address(L2Token), + alice, + alice, + 100, + hex"" + ); + } } diff --git a/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol b/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol new file mode 100644 index 000000000000..d07aa1033dda --- /dev/null +++ b/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol @@ -0,0 +1,104 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { CommonTest } from "./CommonTest.t.sol"; +import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; +import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; + +contract L2ToL1MessagePasserTest is CommonTest { + L2ToL1MessagePasser messagePasser; + + event WithdrawalInitiated( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data + ); + + event WithdrawerBalanceBurnt(uint256 indexed amount); + + function setUp() virtual public { + messagePasser = new L2ToL1MessagePasser(); + } + + // Test: initiateWithdrawal should emit the correct log when called by a contract + function test_initiateWithdrawal_fromContract() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated( + messagePasser.nonce(), + address(this), + address(4), + 100, + 64000, + hex"" + ); + + vm.deal(address(this), 2**64); + messagePasser.initiateWithdrawal{ value: 100 }( + address(4), + 64000, + hex"" + ); + } + + // Test: initiateWithdrawal should emit the correct log when called by an EOA + function test_initiateWithdrawal_fromEOA() external { + uint256 gasLimit = 64000; + address target = address(4); + uint256 value = 100; + bytes memory data = hex"ff"; + uint256 nonce = messagePasser.nonce(); + + // EOA emulation + vm.prank(alice, alice); + vm.deal(alice, 2**64); + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated( + nonce, + alice, + target, + value, + gasLimit, + data + ); + + bytes32 withdrawalHash = WithdrawalVerifier.withdrawalHash( + nonce, + alice, + target, + value, + gasLimit, + data + ); + + messagePasser.initiateWithdrawal{ value: value }( + target, + gasLimit, + data + ); + + // the sent messages mapping is filled + assertEq(messagePasser.sentMessages(withdrawalHash), true); + // the nonce increments + assertEq(nonce + 1, messagePasser.nonce()); + } + + // Test: burn should destroy the ETH held in the contract + function test_burn() external { + messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + NON_ZERO_GASLIMIT, + NON_ZERO_DATA + ); + + assertEq(address(messagePasser).balance, NON_ZERO_VALUE); + vm.expectEmit(true, false, false, false); + emit WithdrawerBalanceBurnt(NON_ZERO_VALUE); + messagePasser.burn(); + + // The Withdrawer should have no balance + assertEq(address(messagePasser).balance, 0); + } +} diff --git a/packages/contracts/contracts/test/OptimismMintableERC20.t.sol b/packages/contracts/contracts/test/OptimismMintableERC20.t.sol new file mode 100644 index 000000000000..3dd49cf81d36 --- /dev/null +++ b/packages/contracts/contracts/test/OptimismMintableERC20.t.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { Bridge_Initializer } from "./CommonTest.t.sol"; +import { LibRLP } from "./Lib_RLP.t.sol"; + +contract OptimismMintableTokenFactory_Test is Bridge_Initializer { + event Mint(address indexed _account, uint256 _amount); + event Burn(address indexed _account, uint256 _amount); + + function setUp() public override { + super.setUp(); + } + + function test_remoteToken() external { + assertEq(L2Token.remoteToken(), address(L1Token)); + } + + function test_bridge() external { + assertEq(L2Token.bridge(), address(L2Bridge)); + } + + function test_l1Token() external { + assertEq(L2Token.l1Token(), address(L1Token)); + } + + function test_l2Bridge() external { + assertEq(L2Token.l2Bridge(), address(L2Bridge)); + } + + function test_mint() external { + vm.expectEmit(true, true, true, true); + emit Mint(alice, 100); + + vm.prank(address(L2Bridge)); + L2Token.mint(alice, 100); + + assertEq(L2Token.balanceOf(alice), 100); + } + + function test_mintRevertsFromNotBridge() external { + // NOT the bridge + vm.expectRevert("Only L2 Bridge can mint and burn"); + vm.prank(address(alice)); + L2Token.mint(alice, 100); + } + + function test_burn() external { + vm.prank(address(L2Bridge)); + L2Token.mint(alice, 100); + + vm.expectEmit(true, true, true, true); + emit Burn(alice, 100); + + vm.prank(address(L2Bridge)); + L2Token.burn(alice, 100); + + assertEq(L2Token.balanceOf(alice), 0); + } + + function test_burnRevertsFromNotBridge() external { + // NOT the bridge + vm.expectRevert("Only L2 Bridge can mint and burn"); + vm.prank(address(alice)); + L2Token.burn(alice, 100); + } +} diff --git a/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol b/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol new file mode 100644 index 000000000000..2b458a226f63 --- /dev/null +++ b/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { Bridge_Initializer } from "./CommonTest.t.sol"; +import { LibRLP } from "./Lib_RLP.t.sol"; + +contract OptimismMintableTokenFactory_Test is Bridge_Initializer { + event StandardL2TokenCreated(address indexed _remoteToken, address indexed _localToken); + event OptimismMintableTokenCreated( + address indexed _localToken, + address indexed _remoteToken, + address _deployer + ); + + function setUp() public override { + super.setUp(); + } + + function test_initializeShouldRevert() external { + vm.expectRevert("Already initialized."); + L2TokenFactory.initialize(address(L1Bridge)); + } + + function test_bridge() external { + assertEq(address(L2TokenFactory.bridge()), address(L2Bridge)); + } + + function test_createStandardL2Token() external { + address remote = address(4); + address local = LibRLP.computeAddress(address(L2TokenFactory), 1); + + vm.expectEmit(true, true, true, true); + emit StandardL2TokenCreated( + remote, + local + ); + + vm.expectEmit(true, true, true, true); + emit OptimismMintableTokenCreated( + remote, + local, + alice + ); + + vm.prank(alice); + L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + } + + function test_createStandardL2TokenSameTwice() external { + address remote = address(4); + + vm.prank(alice); + L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + + address local = LibRLP.computeAddress(address(L2TokenFactory), 2); + + vm.expectEmit(true, true, true, true); + emit StandardL2TokenCreated( + remote, + local + ); + + vm.expectEmit(true, true, true, true); + emit OptimismMintableTokenCreated( + remote, + local, + alice + ); + + vm.prank(alice); + L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + } + + function test_createStandardL2TokenShouldRevertIfRemoteIsZero() external { + address remote = address(0); + vm.expectRevert("Must provide L1 token address"); + L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + } +} diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts/contracts/test/OptimismPortal.t.sol index c77b91e003dc..00dd74c01eb5 100644 --- a/packages/contracts/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts/contracts/test/OptimismPortal.t.sol @@ -1,14 +1,13 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; -/* Testing utilities */ +import { AddressAliasHelper } from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; + import { CommonTest } from "./CommonTest.t.sol"; -/* Target contract dependencies */ import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; - -/* Target contract */ import { OptimismPortal } from "../L1/OptimismPortal.sol"; +import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; contract OptimismPortal_Test is CommonTest { event TransactionDeposited( @@ -23,24 +22,279 @@ contract OptimismPortal_Test is CommonTest { // Dependencies L2OutputOracle oracle; - OptimismPortal op; function setUp() external { - // Oracle value is zero, but this test does not depend on it. + oracle = new L2OutputOracle( + 1800, + 2, + keccak256(abi.encode(0)), + 100, + 1, + address(666) + ); op = new OptimismPortal(oracle, 7 days); } - function test_receive_withEthValueFromEOA() external { - // EOA emulation - vm.prank(address(this), address(this)); + function test_OptimismPortalConstructor() external { + assertEq(op.FINALIZATION_PERIOD(), 7 days); + assertEq(address(op.L2_ORACLE()), address(oracle)); + assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD); + } + function test_OptimismPortalReceiveEth() external { vm.expectEmit(true, true, false, true); - emit TransactionDeposited(address(this), address(this), 100, 100, 30_000, false, hex""); + emit TransactionDeposited( + alice, + alice, + 100, + 100, + 100_000, + false, + hex"" + ); + // give alice money and send as an eoa + vm.deal(alice, 2**64); + vm.prank(alice, alice); (bool s, ) = address(op).call{ value: 100 }(hex""); - s; // Silence the compiler's "Return value of low-level calls not used" warning. + assert(s); assertEq(address(op).balance, 100); } + + // function test_OptimismPortalDepositTransaction() external {} + + // Test: depositTransaction fails when contract creation has a non-zero destination address + function test_OptimismPortalContractCreationReverts() external { + // contract creation must have a target of address(0) + vm.expectRevert(abi.encodeWithSignature("NonZeroCreationTarget()")); + op.depositTransaction(address(1), 1, 0, true, hex""); + } + + // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value + function test_depositTransaction_NoValueEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + address(this), + NON_ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + + op.depositTransaction( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + } + + // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value + function test_depositTransaction_NoValueContract() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + NON_ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + + op.depositTransaction( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + } + + // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value + function test_depositTransaction_createWithZeroValueForEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + address(this), + ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); + + op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + } + + // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value + function test_depositTransaction_createWithZeroValueForContract() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + ZERO_ADDRESS, + ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); + + op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + } + + // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH + function test_depositTransaction_withEthValueFromEOA() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + address(this), + NON_ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + + op.depositTransaction{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + assertEq(address(op).balance, NON_ZERO_VALUE); + } + + // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH + function test_depositTransaction_withEthValueFromContract() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + NON_ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + + op.depositTransaction{ value: NON_ZERO_VALUE }( + NON_ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + false, + NON_ZERO_DATA + ); + } + + // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH + function test_depositTransaction_withEthValueAndEOAContractCreation() external { + // EOA emulation + vm.prank(address(this), address(this)); + + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + address(this), + ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + hex"" + ); + + op.depositTransaction{ value: NON_ZERO_VALUE }( + ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + hex"" + ); + assertEq(address(op).balance, NON_ZERO_VALUE); + } + + // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH + function test_depositTransaction_withEthValueAndContractContractCreation() external { + vm.expectEmit(true, true, false, true); + emit TransactionDeposited( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + ZERO_ADDRESS, + NON_ZERO_VALUE, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); + + op.depositTransaction{ value: NON_ZERO_VALUE }( + ZERO_ADDRESS, + ZERO_VALUE, + NON_ZERO_GASLIMIT, + true, + NON_ZERO_DATA + ); + assertEq(address(op).balance, NON_ZERO_VALUE); + } + + // TODO: test this deeply + // function test_verifyWithdrawal() external {} + + function test_cannotVerifyRecentWithdrawal() external { + WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({ + version: bytes32(0), + stateRoot: bytes32(0), + withdrawerStorageRoot: bytes32(0), + latestBlockhash: bytes32(0) + }); + + vm.expectRevert("Proposal is not yet finalized."); + op.finalizeWithdrawalTransaction( + 0, + alice, + alice, + 0, + 0, + hex"", + 0, + outputRootProof, + hex"" + ); + } + + function test_invalidWithdrawalProof() external { + WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({ + version: bytes32(0), + stateRoot: bytes32(0), + withdrawerStorageRoot: bytes32(0), + latestBlockhash: bytes32(0) + }); + + vm.warp(oracle.nextTimestamp() + op.FINALIZATION_PERIOD()); + vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); + op.finalizeWithdrawalTransaction( + 0, + alice, + alice, + 0, + 0, + hex"", + 0, + outputRootProof, + hex"" + ); + } } diff --git a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol b/packages/contracts/contracts/test/WithdrawalsRelay.t.sol deleted file mode 100644 index 7031c1235d06..000000000000 --- a/packages/contracts/contracts/test/WithdrawalsRelay.t.sol +++ /dev/null @@ -1,174 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.10; - -/* Testing utilities */ -import { CommonTest } from "./CommonTest.t.sol"; - -/* Target contract dependencies */ -import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol"; - -/* Target contract */ -import { WithdrawalsRelay } from "../L1/abstracts/WithdrawalsRelay.sol"; - -contract Target is WithdrawalsRelay { - constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriod) - WithdrawalsRelay(_l2Oracle, _finalizationPeriod) - {} -} - -contract WithdrawalsRelay_finalizeWithdrawalTransaction_Test is CommonTest { - event TransactionDeposited( - address indexed from, - address indexed to, - uint256 mint, - uint256 value, - uint256 gasLimit, - bool isCreation, - bytes data - ); - - // Dependencies - L2OutputOracle oracle; - - // Oracle constructor arguments - address sequencer = 0x000000000000000000000000000000000000AbBa; - uint256 submissionInterval = 1800; - uint256 l2BlockTime = 2; - bytes32 genesisL2Output = keccak256(abi.encode(0)); - uint256 historicalTotalBlocks = 100; - - // Test target - Target wr; - - // Target constructor arguments - address withdrawalsPredeploy = 0x4200000000000000000000000000000000000015; - - // Cache of timestamps - uint256 startingBlockTimestamp; - uint256 appendedTimestamp; - - // By default the first block has timestamp zero, which will cause underflows in the tests, - // so we jump ahead to the exact time that I wrote this line. - uint256 initTime = 1648757197; - - // Withdrawal call parameters - uint256 wdNonce = 1; - address wdSender = address(0x02); - address wdTarget = address(0x03); - uint256 wdValue = 4; - uint256 wdGasLimit = 500000; - bytes wdData = hex"06"; - - // Generate an output and corresponding proof that we can work with. We can use whatever values - // we want except for the withdrawerStorageRoot. These roots and the proof were generated by - // running scripts/makeProof.ts with the above withdrawal call parameters as arguments. - bytes32 version = 0x0000000000000000000000000000000000000000000000000000000000000000; - bytes32 stateRoot = 0x187c35d79aa836b74475ff4940e0eff42e2ee5661f136995b4470bb92cf0813d; - bytes32 withdrawerStorageRoot = - 0x7f58036a634aca208c3e571f8306f314f83964313bc0725ceec76d839a097e79; // eth_getProof (storageHash) - bytes32 latestBlockhash = 0x0000000000000000000000000000000000000000000000000000000000000000; - - bytes withdrawalProof = - hex"e5a4e3a120453242a1d87fab6d401bd84b3d16c8d3f6a65142a069568067e7c2980af50e2801"; - - // we'll set this value in the `setUp` function and cache it here for reuse in each test - WithdrawalVerifier.OutputRootProof outputRootProof; - - constructor() { - // Move time forward so we have a non-zero starting timestamp - vm.warp(initTime); - - // Deploy the L2OutputOracle and transfer owernship to the sequencer - oracle = new L2OutputOracle( - submissionInterval, - l2BlockTime, - genesisL2Output, - historicalTotalBlocks, - initTime, - sequencer - ); - startingBlockTimestamp = block.timestamp; - - wr = new Target(oracle, 7 days); - } - - function setUp() external { - vm.warp(initTime); - bytes32 outputRoot = keccak256( - abi.encode(version, stateRoot, withdrawerStorageRoot, latestBlockhash) - ); - - uint256 nextTimestamp = oracle.nextTimestamp(); - // Warp to 1 second after the timestamp we'll append - vm.warp(nextTimestamp + 1); - vm.prank(sequencer); - oracle.appendL2Output(outputRoot, nextTimestamp, 0, 0); - - // cache the appendedTimestamp - appendedTimestamp = nextTimestamp; - outputRootProof = WithdrawalVerifier.OutputRootProof({ - version: version, - stateRoot: stateRoot, - withdrawerStorageRoot: withdrawerStorageRoot, - latestBlockhash: latestBlockhash - }); - - } - - function test_verifyWithdrawal() external { - // todo: get FFI working for this test - // string[] memory inputs = new string[](3); - // inputs[0] = "ts-node"; - // inputs[1] = "scripts/makeProof"; - // inputs[2] = string(abi.encode(wdNonce, wdSender, wdTarget, wdValue, wdGasLimit, wdData)); - // Warp to after the finality window - vm.warp(appendedTimestamp + 7 days); - wr.finalizeWithdrawalTransaction( - wdNonce, - wdSender, - wdTarget, - wdValue, - wdGasLimit, - wdData, - appendedTimestamp, - outputRootProof, - withdrawalProof - ); - } - - function test_cannotVerifyRecentWithdrawal() external { - // This call should fail because the output root we're using was appended 1 second ago. - vm.expectRevert(abi.encodeWithSignature("NotYetFinal()")); - wr.finalizeWithdrawalTransaction( - wdNonce, - wdSender, - wdTarget, - wdValue, - wdGasLimit, - wdData, - appendedTimestamp, - outputRootProof, - hex"ffff" - ); - } - - function test_cannotVerifyInvalidProof() external { - // This call should fail because the output proof is modified - vm.warp(appendedTimestamp + 7 days); - vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()")); - WithdrawalVerifier.OutputRootProof memory invalidOutpuRootProof = outputRootProof; - invalidOutpuRootProof.latestBlockhash = bytes32(hex"01"); - wr.finalizeWithdrawalTransaction( - wdNonce, - wdSender, - wdTarget, - wdValue, - wdGasLimit, - wdData, - appendedTimestamp, - invalidOutpuRootProof, - hex"ffff" - ); - } -} diff --git a/packages/contracts/contracts/test/Withdrawer.t.sol b/packages/contracts/contracts/test/Withdrawer.t.sol deleted file mode 100644 index bc155dad9263..000000000000 --- a/packages/contracts/contracts/test/Withdrawer.t.sol +++ /dev/null @@ -1,111 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.10; - -import { DSTest } from "forge-std/Test.sol"; -import { Vm } from "forge-std/Vm.sol"; -import { Withdrawer } from "../L2/Withdrawer.sol"; - -import { - AddressAliasHelper -} from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; -import { - Lib_RLPWriter -} from "@eth-optimism/contracts/libraries/rlp/Lib_RLPWriter.sol"; -import { - Lib_Bytes32Utils -} from "@eth-optimism/contracts/libraries/utils/Lib_Bytes32Utils.sol"; - - -contract WithdrawerTestCommon is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - address immutable ZERO_ADDRESS = address(0); - address immutable NON_ZERO_ADDRESS = address(1); - uint256 immutable NON_ZERO_VALUE = 100; - uint256 immutable ZERO_VALUE = 0; - uint256 immutable NON_ZERO_GASLIMIT = 50000; - bytes NON_ZERO_DATA = hex"1111"; - - event WithdrawalInitiated( - uint256 indexed nonce, - address indexed sender, - address indexed target, - uint256 value, - uint256 gasLimit, - bytes data - ); - - Withdrawer wd; - - function setUp() public virtual { - wd = new Withdrawer(); - } -} - -contract WithdrawerTestInitiateWithdrawal is WithdrawerTestCommon { - - // Test: initiateWithdrawal should emit the correct log when called by a contract - function test_initiateWithdrawal_fromContract() external { - vm.expectEmit(true, true, true, true); - emit WithdrawalInitiated( - 0, - address(this), - NON_ZERO_ADDRESS, - NON_ZERO_VALUE, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA - ); - - wd.initiateWithdrawal{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA - ); - } - - // Test: initiateWithdrawal should emit the correct log when called by an EOA - function test_initiateWithdrawal_fromEOA() external { - // EOA emulation - vm.prank(address(this), address(this)); - vm.expectEmit(true, true, true, true); - emit WithdrawalInitiated( - 0, - address(this), - NON_ZERO_ADDRESS, - NON_ZERO_VALUE, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA - ); - - wd.initiateWithdrawal{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA - ); - } -} - -contract WithdawerBurnTest is WithdrawerTestCommon { - - event WithdrawerBalanceBurnt(uint256 indexed amount); - - function setUp() public override { - // fund a new withdrawer - super.setUp(); - wd.initiateWithdrawal{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, - NON_ZERO_GASLIMIT, - NON_ZERO_DATA - ); - } - - // Test: burn should destroy the ETH held in the contract - function test_burn() external { - assertEq(address(wd).balance, NON_ZERO_VALUE); - vm.expectEmit(true, false, false, false); - emit WithdrawerBalanceBurnt(NON_ZERO_VALUE); - wd.burn(); - - // The Withdrawer should have no balance - assertEq(address(wd).balance, 0); - } -} diff --git a/packages/contracts/contracts/universal/CrossDomainMessenger.sol b/packages/contracts/contracts/universal/CrossDomainMessenger.sol new file mode 100644 index 000000000000..8414145bc4e5 --- /dev/null +++ b/packages/contracts/contracts/universal/CrossDomainMessenger.sol @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// solhint-disable max-line-length + +/* Library Imports */ +import { + Lib_DefaultValues +} from "@eth-optimism/contracts/libraries/constants/Lib_DefaultValues.sol"; +import { CrossDomainHashing } from "../libraries/Lib_CrossDomainHashing.sol"; + +/* External Imports */ +import { + OwnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { + PausableUpgradeable +} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; +import { + ReentrancyGuardUpgradeable +} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; +import { ExcessivelySafeCall } from "../libraries/ExcessivelySafeCall.sol"; + +// solhint-enable max-line-length + +/** + * @title CrossDomainMessenger + * @dev The CrossDomainMessenger contract delivers messages between two layers. + */ +abstract contract CrossDomainMessenger is + OwnableUpgradeable, + PausableUpgradeable, + ReentrancyGuardUpgradeable +{ + /********** + * Events * + **********/ + + event SentMessage( + address indexed target, + address sender, + bytes message, + uint256 messageNonce, + uint256 gasLimit + ); + + event RelayedMessage(bytes32 indexed msgHash); + + event FailedRelayedMessage(bytes32 indexed msgHash); + + /************* + * Constants * + *************/ + + uint16 public constant MESSAGE_VERSION = 1; + + /************* + * Variables * + *************/ + + // blockedMessages in old L1CrossDomainMessenger + bytes32 internal REMOVED_VARIABLE_SPACER_1; + + // relayedMessages in old L1CrossDomainMessenger + bytes32 internal REMOVED_VARIABLE_SPACER_2; + + /// @notice Mapping of message hash to boolean success value. + mapping(bytes32 => bool) public successfulMessages; + + /// @notice Current x-domain message sender. + address internal xDomainMsgSender; + + /// @notice Nonce for the next message to be sent. + uint256 internal msgNonce; + + /// @notice Address of the CrossDomainMessenger on the other chain. + address public otherMessenger; + + /// @notice Mapping of message hash to boolean receipt value. + mapping(bytes32 => bool) public receivedMessages; + + /// @notice Blocked system addresses that cannot be called (for security reasons). + mapping(address => bool) public blockedSystemAddresses; + + /******************** + * Public Functions * + ********************/ + + /** + * Pause relaying. + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * Retrieves the address of the x-domain message sender. Will throw an error + * if the sender is not currently set (equal to the default sender). + * This function is meant to be called on the remote side of a cross domain + * message so that the account that initiated the call can be known. + * + * @return Address of the x-domain message sender. + */ + function xDomainMessageSender() external view returns (address) { + require( + xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, + "xDomainMessageSender is not set" + ); + + return xDomainMsgSender; + } + + /** + * Retrieves the next message nonce. Adds the hash version to the nonce. + * + * @return Next message nonce with added hash version. + */ + function messageNonce() public view returns (uint256) { + return CrossDomainHashing.addVersionToNonce(msgNonce, MESSAGE_VERSION); + } + + /** + * @param _target Target contract address. + * @param _message Message to send to the target. + * @param _minGasLimit Gas limit for the provided message. + */ + function sendMessage( + address _target, + bytes memory _message, + uint32 _minGasLimit + ) external payable { + // TODO: Enforce minimum gas limit. + + _sendMessage( + otherMessenger, + _minGasLimit, // TODO: Pad this value. + msg.value, + CrossDomainHashing.getVersionedEncoding( + messageNonce(), + msg.sender, + _target, + msg.value, + _minGasLimit, + _message + ) + ); + + emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit); + + unchecked { + ++msgNonce; + } + } + + function relayMessage( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _minGasLimit, + bytes calldata _message + ) external payable nonReentrant whenNotPaused { + bytes32 versionedHash = CrossDomainHashing.getVersionedHash( + _nonce, + _sender, + _target, + _value, + _minGasLimit, + _message + ); + + if (_isSystemMessageSender()) { + // Should never happen. + require(msg.value == _value, "Mismatched message value."); + } else { + // TODO(tynes): could require that msg.value == 0 here + // to prevent eth from getting stuck + require(receivedMessages[versionedHash], "Message cannot be replayed."); + } + + // TODO: Should blocking happen on sending or receiving side? + // TODO: Should this just return with an event instead of reverting? + require( + blockedSystemAddresses[_target] == false, + "Cannot send message to blocked system address." + ); + + require(successfulMessages[versionedHash] == false, "Message has already been relayed."); + + // TODO: Make sure this will always give us enough gas. + require(gasleft() >= _minGasLimit + 45000, "Insufficient gas to relay message."); + + xDomainMsgSender = _sender; + (bool success, ) = ExcessivelySafeCall.excessivelySafeCall( + _target, + gasleft() - 40000, + _value, + 0, + _message + ); + xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; + + if (success == true) { + successfulMessages[versionedHash] = true; + emit RelayedMessage(versionedHash); + } else { + receivedMessages[versionedHash] = true; + emit FailedRelayedMessage(versionedHash); + } + } + + /********************** + * Internal Functions * + **********************/ + + function _isSystemMessageSender() internal view virtual returns (bool); + + function _sendMessage( + address _to, + uint64 _gasLimit, + uint256 _value, + bytes memory _data + ) internal virtual; + + /** + * Initializes the contract. + */ + function _initialize(address _otherMessenger, address[] memory _blockedSystemAddresses) + internal + initializer + { + xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; + otherMessenger = _otherMessenger; + + for (uint256 i = 0; i < _blockedSystemAddresses.length; i++) { + blockedSystemAddresses[_blockedSystemAddresses[i]] = true; + } + + // TODO: ensure we know what these are doing and why they are here + // Initialize upgradable OZ contracts + __Context_init_unchained(); + __Ownable_init_unchained(); + __Pausable_init_unchained(); + __ReentrancyGuard_init_unchained(); + } +} diff --git a/packages/contracts/contracts/universal/OptimismMintableERC20.sol b/packages/contracts/contracts/universal/OptimismMintableERC20.sol new file mode 100644 index 000000000000..90decd243954 --- /dev/null +++ b/packages/contracts/contracts/universal/OptimismMintableERC20.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +/** + * @title OptimismMintableERC20 + * This contract represents the remote representation + * of an ERC20 token. It is linked to the address of + * a token in another domain and tokens can be locked + * in the StandardBridge which will mint tokens in the + * other domain. + */ +contract OptimismMintableERC20 is ERC20 { + event Mint(address indexed _account, uint256 _amount); + event Burn(address indexed _account, uint256 _amount); + + /** + * @notice The address of the token in the remote domain + */ + address public remoteToken; + + /** + * @notice The address of the bridge responsible for + * minting. It is in the same domain. + */ + address public bridge; + + /** + * @param _bridge Address of the L2 standard bridge. + * @param _remoteToken Address of the corresponding L1 token. + * @param _name ERC20 name. + * @param _symbol ERC20 symbol. + */ + constructor( + address _bridge, + address _remoteToken, + string memory _name, + string memory _symbol + ) ERC20(_name, _symbol) { + remoteToken = _remoteToken; + bridge = _bridge; + } + + /** + * @notice Returns the corresponding L1 token address. + * This is a legacy function and wraps the remoteToken value. + */ + function l1Token() public view returns (address) { + return remoteToken; + } + + /** + * @notice The address of the bridge contract + * responsible for minting tokens. This is a legacy + * getter function + */ + function l2Bridge() public view returns (address) { + return bridge; + } + + /** + * @notice A modifier that only allows the bridge to call + */ + modifier onlyBridge() { + require(msg.sender == bridge, "Only L2 Bridge can mint and burn"); + _; + } + + /** + * @notice ERC165 + */ + // slither-disable-next-line external-function + function supportsInterface(bytes4 _interfaceId) public pure returns (bool) { + bytes4 iface1 = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165 + bytes4 iface2 = this.l1Token.selector ^ this.mint.selector ^ this.burn.selector; + bytes4 iface3 = this.remoteToken.selector ^ this.mint.selector ^ this.burn.selector; + return _interfaceId == iface1 || _interfaceId == iface3 || _interfaceId == iface2; + } + + /** + * @notice The bridge can mint tokens + */ + // slither-disable-next-line external-function + function mint(address _to, uint256 _amount) public virtual onlyBridge { + _mint(_to, _amount); + + emit Mint(_to, _amount); + } + + /** + * @notice The bridge can burn tokens + */ + // slither-disable-next-line external-function + function burn(address _from, uint256 _amount) public virtual onlyBridge { + _burn(_from, _amount); + + emit Burn(_from, _amount); + } +} diff --git a/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol b/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol new file mode 100644 index 000000000000..fc482c4e5cca --- /dev/null +++ b/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Contract Imports */ +import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol"; +import { + Lib_PredeployAddresses +} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; + +/** + * @title OptimismMintableTokenFactory + * @dev Factory contract for creating standard remote token representations of + * local ERC20s. This can be used to bridge native L1 ERC20s to L2 or native L2 + * ERC20s to L1. The tokens created through this factory are meant to operate + * with the StandardBridge contract for deposits/withdrawals. + * This contract is a predeploy on L2 at 0x4200000000000000000000000000000000000012 + * TODO: deploy to a deterministic address on L1 networks? + * TODO: should this be extended for L1/L2 with hardcoded values in + * the base contract's initialize? + */ +contract OptimismMintableTokenFactory { + event StandardL2TokenCreated(address indexed _remoteToken, address indexed _localToken); + event OptimismMintableTokenCreated( + address indexed _localToken, + address indexed _remoteToken, + address _deployer + ); + + address public bridge; + + /** + * @dev Initialize the factory + * On L2 _bridge should be Lib_PredeployAddresses.L2_STANDARD_BRIDGE, + * On L1 _bridge should be the L1StandardBridge + */ + function initialize(address _bridge) public { + require(bridge == address(0), "Already initialized."); + bridge = _bridge; + } + + /** + * @dev Creates an instance of the standard ERC20 token on L2. + * @param _remoteToken Address of the corresponding L1 token. + * @param _name ERC20 name. + * @param _symbol ERC20 symbol. + */ + function createStandardL2Token( + address _remoteToken, + string memory _name, + string memory _symbol + ) external returns (address) { + require(_remoteToken != address(0), "Must provide L1 token address"); + require(bridge != address(0), "Must initialize first"); + + OptimismMintableERC20 localToken = new OptimismMintableERC20( + bridge, + _remoteToken, + _name, + _symbol + ); + + // Legacy Purposes + emit StandardL2TokenCreated(_remoteToken, address(localToken)); + emit OptimismMintableTokenCreated(_remoteToken, address(localToken), msg.sender); + + return address(localToken); + } +} diff --git a/packages/contracts/contracts/universal/StandardBridge.sol b/packages/contracts/contracts/universal/StandardBridge.sol new file mode 100644 index 000000000000..e6e37483558b --- /dev/null +++ b/packages/contracts/contracts/universal/StandardBridge.sol @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Interface Imports */ +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/* Library Imports */ +import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +import { CrossDomainMessenger } from "./CrossDomainMessenger.sol"; +import { OptimismMintableERC20 } from "./OptimismMintableERC20.sol"; + +/** + * @title StandardBridge + * This contract can manage a 1:1 bridge between two domains for both + * ETH (native asset) and ERC20s. + * This contract should be deployed behind a proxy. + * TODO: do we want a donateERC20 function as well? + */ +abstract contract StandardBridge { + using SafeERC20 for IERC20; + + /********** + * Events * + **********/ + + event ETHBridgeInitiated( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ETHBridgeFinalized( + address indexed _from, + address indexed _to, + uint256 _amount, + bytes _data + ); + + event ERC20BridgeInitiated( + address indexed _localToken, + address indexed _remoteToken, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + event ERC20BridgeFinalized( + address indexed _localToken, + address indexed _remoteToken, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + + /************* + * Variables * + *************/ + + /** + * @notice The messenger contract on the same domain + */ + CrossDomainMessenger public messenger; + + /** + * @notice The corresponding bridge on the other domain + */ + StandardBridge public otherBridge; + + mapping(address => mapping(address => uint256)) public deposits; + + /************* + * Modifiers * + *************/ + + /** + * @notice Only allow EOAs to call the functions. Note that this + * is not safe against contracts calling code during their constructor + */ + modifier onlyEOA() { + require(!Address.isContract(msg.sender), "Account not EOA"); + _; + } + + /** + * @notice Ensures that the caller is the messenger, and that + * it has the l2Sender value set to the address of the remote Token Bridge. + */ + modifier onlyOtherBridge() { + require( + msg.sender == address(messenger) && + messenger.xDomainMessageSender() == address(otherBridge), + "Could not authenticate bridge message." + ); + _; + } + + /******************** + * Public Functions * + ********************/ + + /** + * @notice Send ETH to this contract. This is used during upgrades + */ + function donateETH() external payable {} + + /** + * @notice EOAs can simply send ETH to this contract to have it be deposited + * to L2 through the standard bridge. + */ + receive() external payable onlyEOA { + _initiateBridgeETH(msg.sender, msg.sender, msg.value, 200_000, bytes("")); + } + + /** + * @notice Send ETH to the message sender on the remote domain + */ + function bridgeETH(uint32 _minGasLimit, bytes calldata _data) public payable onlyEOA { + _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _data); + } + + /** + * @notice Send ETH to a specified account on the remote domain + */ + function bridgeETHTo( + address _to, + uint32 _minGasLimit, + bytes calldata _data + ) public payable { + _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _data); + } + + /** + * @notice Send an ERC20 to the message sender on the remote domain + */ + function bridgeERC20( + address _localToken, + address _remoteToken, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) public virtual onlyEOA { + _initiateBridgeERC20( + _localToken, + _remoteToken, + msg.sender, + msg.sender, + _amount, + _minGasLimit, + _data + ); + } + + /** + * @notice Send an ERC20 to a specified account on the remote domain + */ + function bridgeERC20To( + address _localToken, + address _remoteToken, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) public virtual { + _initiateBridgeERC20( + _localToken, + _remoteToken, + msg.sender, + _to, + _amount, + _minGasLimit, + _data + ); + } + + /** + * @notice Finalize an ETH sending transaction sent from a remote domain + */ + function finalizeBridgeETH( + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) public payable onlyOtherBridge { + require(msg.value == _amount, "Amount sent does not match amount required."); + + emit ETHBridgeFinalized(_from, _to, _amount, _data); + (bool success, ) = _to.call{ value: _amount }(new bytes(0)); + require(success, "TransferHelper::safeTransferETH: ETH transfer failed"); + } + + /** + * @notice Finalize an ERC20 sending transaction sent from a remote domain + */ + function finalizeBridgeERC20( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) public onlyOtherBridge { + if (_isOptimismMintable(_localToken, _remoteToken)) { + OptimismMintableERC20(_localToken).mint(_to, _amount); + } else { + deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount; + IERC20(_localToken).safeTransfer(_to, _amount); + } + + emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _data); + } + + /********************** + * Internal Functions * + **********************/ + + /** + * @notice Initialize the StandardBridge contract with the address of + * the messenger on the same domain as well as the address of the bridge + * on the remote domain + */ + function _initialize(address payable _messenger, address payable _otherBridge) internal { + require(address(messenger) == address(0), "Contract has already been initialized."); + + messenger = CrossDomainMessenger(_messenger); + otherBridge = StandardBridge(_otherBridge); + } + + /** + * @notice Bridge ETH to the remote chain through the messenger + */ + function _initiateBridgeETH( + address _from, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _data + ) internal { + emit ETHBridgeInitiated(_from, _to, _amount, _data); + + messenger.sendMessage{ value: _amount }( + address(otherBridge), + abi.encodeWithSelector(this.finalizeBridgeETH.selector, _from, _to, _amount, _data), + _minGasLimit + ); + } + + /** + * @notice Bridge an ERC20 to the remote chain through the messengers + */ + function _initiateBridgeERC20( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) internal { + if (_isOptimismMintable(_localToken, _remoteToken)) { + OptimismMintableERC20(_localToken).burn(msg.sender, _amount); + } else { + IERC20(_localToken).safeTransferFrom(_from, address(this), _amount); + deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount; + } + + messenger.sendMessage( + address(otherBridge), + abi.encodeWithSelector( + this.finalizeBridgeERC20.selector, + _remoteToken, + _localToken, + _from, + _to, + _amount, + _data + ), + _minGasLimit + ); + + emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _data); + } + + /** + * @notice Check to make sure that the token pair is an OptimismMintable + * token pair. + * The selector 0x1d1d8b63 represents the ERC165 representation of + * the methods l1Token(), mint(address,uint256), burn(address,uint256) + * the selector 0x0bc32271 represents the ERC165 representation of + * remoteToken(), mint(address,uint256), burn(address,uint256). + * Both are required as l1Token() is a legacy function, prefer calling + * remoteToken() + */ + function _isOptimismMintable(address _localToken, address _remoteToken) + internal + view + returns (bool) + { + return ((ERC165Checker.supportsInterface(_localToken, 0x1d1d8b63) && + _remoteToken == OptimismMintableERC20(_localToken).l1Token()) || + (ERC165Checker.supportsInterface(_localToken, 0x0bc32271) && + _remoteToken == OptimismMintableERC20(_localToken).remoteToken())); + } +} diff --git a/packages/contracts/deploy/002-L1CrossDomainMessenger.ts b/packages/contracts/deploy/002-L1CrossDomainMessenger.ts new file mode 100644 index 000000000000..dfd426354ec8 --- /dev/null +++ b/packages/contracts/deploy/002-L1CrossDomainMessenger.ts @@ -0,0 +1,34 @@ +/* Imports: Internal */ +import { DeployFunction } from 'hardhat-deploy/dist/types' +import { Contract } from 'ethers' +import 'hardhat-deploy' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + await deploy('L1CrossDomainMessenger', { + from: deployer, + args: [], + log: true, + waitConfirmations: 1, + }) + + const provider = hre.ethers.provider.getSigner(deployer) + const oracle = await hre.deployments.get('L2OutputOracle') + const messenger = await hre.deployments.get('L1CrossDomainMessenger') + + const L1CrossDomainMessenger = new Contract( + messenger.address, + messenger.abi, + provider + ) + + const tx = await L1CrossDomainMessenger.initialize(oracle.address) + const receipt = await tx.wait() + console.log(`${receipt.transactionHash}: initialize(${oracle.address})`) +} + +deployFn.tags = ['L1CrossDomainMessenger'] + +export default deployFn diff --git a/packages/contracts/deploy/003-L1StandardBridge.ts b/packages/contracts/deploy/003-L1StandardBridge.ts new file mode 100644 index 000000000000..4d0abd2b6cd4 --- /dev/null +++ b/packages/contracts/deploy/003-L1StandardBridge.ts @@ -0,0 +1,31 @@ +/* Imports: Internal */ +import { DeployFunction } from 'hardhat-deploy/dist/types' +import { Contract } from 'ethers' +import 'hardhat-deploy' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + await deploy('L1StandardBridge', { + from: deployer, + args: [], + log: true, + waitConfirmations: 1, + }) + + const provider = hre.ethers.provider.getSigner(deployer) + + const messenger = await hre.deployments.get('L1CrossDomainMessenger') + const bridge = await hre.deployments.get('L1StandardBridge') + + const L1StandardBridge = new Contract(bridge.address, bridge.abi, provider) + + const tx = await L1StandardBridge.initialize(messenger.address) + const receipt = await tx.wait() + console.log(`${receipt.transactionHash}: initialize(${messenger.address})`) +} + +deployFn.tags = ['L1StandardBridge'] + +export default deployFn diff --git a/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts b/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts new file mode 100644 index 000000000000..249745f68de6 --- /dev/null +++ b/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts @@ -0,0 +1,35 @@ +/* Imports: Internal */ +import { DeployFunction } from 'hardhat-deploy/dist/types' +import { Contract } from 'ethers' +import 'hardhat-deploy' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + await deploy('OptimismMintableTokenFactory', { + from: deployer, + args: [], + log: true, + waitConfirmations: 1, + }) + + const provider = hre.ethers.provider.getSigner(deployer) + + const factory = await hre.deployments.get('OptimismMintableTokenFactory') + const bridge = await hre.deployments.get('L1StandardBridge') + + const OptimismMintableTokenFactory = new Contract( + factory.address, + factory.abi, + provider + ) + + const tx = await OptimismMintableTokenFactory.initialize(bridge.address) + const receipt = await tx.wait() + console.log(`${receipt.transactionHash}: initialize(${bridge.address})`) +} + +deployFn.tags = ['OptimismMintableTokenFactory'] + +export default deployFn diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml index a08e0b7df33b..e453018fd9e2 100644 --- a/packages/contracts/foundry.toml +++ b/packages/contracts/foundry.toml @@ -8,6 +8,7 @@ optimizer_runs = 999999 remappings = [ '@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/', '@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/', - '@eth-optimism/contracts/=node_modules/@eth-optimism/contracts/' + '@eth-optimism/contracts/=node_modules/@eth-optimism/contracts/', + 'excessively-safe-call/=node_modules/excessively-safe-call/src/', ] bytecode_hash = "none" diff --git a/packages/contracts/lib/forge-std b/packages/contracts/lib/forge-std index e26ae2954bb6..409465b69928 160000 --- a/packages/contracts/lib/forge-std +++ b/packages/contracts/lib/forge-std @@ -1 +1 @@ -Subproject commit e26ae2954bb6d883643b92760d443dd07f413647 +Subproject commit 409465b6992822a91318142dd269660aad9e30ee diff --git a/packages/integration-tests/test/000_withdrawals.spec.ts b/packages/integration-tests/test/000_withdrawals.spec.ts index bb01c90d6784..378ad2a56ac6 100644 --- a/packages/integration-tests/test/000_withdrawals.spec.ts +++ b/packages/integration-tests/test/000_withdrawals.spec.ts @@ -8,15 +8,14 @@ import * as rlp from 'rlp' import { Block } from '@ethersproject/abstract-provider' /* Imports: Internal */ -import { WITHDRAWER_ADDR } from './shared/constants' import env from './shared/env' import { expect } from './shared/setup' import winston from 'winston' +import { predeploys } from '@eth-optimism/contracts' -const withdrawerArtifact = require('../../contracts/artifacts/contracts/L2/Withdrawer.sol/Withdrawer.json') +const l2ToL1MessagePasserArtifact = require('../../contracts/artifacts/contracts/L2/L2ToL1MessagePasser.sol/L2ToL1MessagePasser.json') const l2OOracleArtifact = require('../../contracts/artifacts/contracts/L1/L2OutputOracle.sol/L2OutputOracle.json') - /** * Calculates the target output timestamp to make the withdrawal proof against. ie. the first * output with a timestamp greater than the burn block timestamp. @@ -58,8 +57,8 @@ describe('Withdrawals', () => { portal = env.optimismPortal withdrawer = new Contract( - WITHDRAWER_ADDR, - withdrawerArtifact.abi, + predeploys.OVM_L2ToL1MessagePasser, + l2ToL1MessagePasserArtifact.abi, ) }) @@ -139,9 +138,14 @@ describe('Withdrawals', () => { ], ), ) + + const included = await withdrawer.sentMessages(withdrawalHash) + expect(included).to.be.true }) - it('should verify the withdrawal on L1', async function () { + // TODO(tynes): refactor this test. the awaitCondition hangs + // forever in its current state + it.skip('should verify the withdrawal on L1', async function () { recipient = recipient.connect(env.l1Provider) portal = portal.connect(recipient) const oracle = new Contract( @@ -158,7 +162,8 @@ describe('Withdrawals', () => { let output: string await awaitCondition(async () => { - output = await oracle.getL2Output(targetOutputTimestamp) + const proposal = await oracle.getL2Output(targetOutputTimestamp) + output = proposal.outputRoot latestBlockTimestamp = (await oracle.latestBlockTimestamp()).toNumber() if(targetOutputTimestamp - latestBlockTimestamp < difference){ // Only log when a new output has been appended @@ -182,7 +187,7 @@ describe('Withdrawals', () => { const targetBlockNumHex = utils.hexValue(targetBlockNum) const storageSlot = '00'.repeat(31) + '01' // i.e the second variable declared in the contract const proof = await env.l2Provider.send('eth_getProof', [ - WITHDRAWER_ADDR, + predeploys.OVM_L2ToL1MessagePasser, [utils.keccak256(withdrawalHash + storageSlot)], targetBlockNumHex, ]) diff --git a/packages/integration-tests/test/shared/constants.ts b/packages/integration-tests/test/shared/constants.ts deleted file mode 100644 index 164c1f163055..000000000000 --- a/packages/integration-tests/test/shared/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const WITHDRAWER_ADDR = '0x4200000000000000000000000000000000000016' \ No newline at end of file diff --git a/packages/integration-tests/test/shared/env.ts b/packages/integration-tests/test/shared/env.ts index 7fd19b24a76f..69b4760c7753 100644 --- a/packages/integration-tests/test/shared/env.ts +++ b/packages/integration-tests/test/shared/env.ts @@ -110,4 +110,4 @@ const keyify = (kv: object): string => { } const env = new OptimismEnv() -export default env \ No newline at end of file +export default env diff --git a/specs/bridges.md b/specs/bridges.md new file mode 100644 index 000000000000..48856cb76204 --- /dev/null +++ b/specs/bridges.md @@ -0,0 +1,51 @@ +# Standard Bridges + + + +**Table of Contents** + +- [Token Depositing](#token-depositing) +- [Upgradability](#upgradability) + + + +The standard bridges are responsible for allowing cross domain +ETH and ERC20 token transfers. They are built on top of the cross domain +messenger contracts and give a standard interface for depositing tokens. + +The bridge works for both L1 native tokens and L2 native tokens. The legacy API +is preserved to ensure that existing applications will not experience any +problems with the Bedrock `StandardBridge` contracts. + +The `L2StandardBridge` is a predeploy contract located at +`0x4200000000000000000000000000000000000010`. + +```solidity +interface StandardBridge { + event ERC20BridgeFinalized(address indexed _localToken, address indexed _remoteToken, address indexed _from, address _to, uint256 _amount, bytes _data); + event ERC20BridgeInitiated(address indexed _localToken, address indexed _remoteToken, address indexed _from, address _to, uint256 _amount, bytes _data); + event ETHBridgeFinalized(address indexed _from, address indexed _to, uint256 _amount, bytes _data); + event ETHBridgeInitiated(address indexed _from, address indexed _to, uint256 _amount, bytes _data); + + function bridgeERC20(address _localToken, address _remoteToken, uint256 _amount, uint32 _minGasLimit, bytes memory _data) external; + function bridgeERC20To(address _localToken, address _remoteToken, address _to, uint256 _amount, uint32 _minGasLimit, bytes memory _data) external; + function bridgeETH(uint32 _minGasLimit, bytes memory _data) payable external; + function bridgeETHTo(address _to, uint32 _minGasLimit, bytes memory _data) payable external; + function deposits(address, address) view external returns (uint256); + function finalizeBridgeERC20(address _localToken, address _remoteToken, address _from, address _to, uint256 _amount, bytes memory _data) external; + function finalizeBridgeETH(address _from, address _to, uint256 _amount, bytes memory _data) payable external; + function messenger() view external returns (address); + function otherBridge() view external returns (address); +} +``` + +## Token Depositing + +The `bridgeERC20` function is used to send a token from one domain to another +domain. An `OptimismMintableERC20` token contract must exist on the remote +domain to be able to deposit tokens to that domain. One of these tokens can be +deployed using the `OptimismMintableTokenFactory` contract. + +## Upgradability + +Both the L1 and L2 standard bridges should be behind upgradable proxies. diff --git a/specs/messengers.md b/specs/messengers.md new file mode 100644 index 000000000000..71f8e4dcfa06 --- /dev/null +++ b/specs/messengers.md @@ -0,0 +1,113 @@ +# Cross Domain Messengers + + + +**Table of Contents** + +- [Message Passing](#message-passing) +- [Upgradability](#upgradability) +- [Message Versioning](#message-versioning) + - [Message Version 0](#message-version-0) + - [Message Version 1](#message-version-1) +- [Backwards Compatibility Notes](#backwards-compatibility-notes) + + + +The cross domain messengers are responsible for providing a higher level API for +developers who are interested in sending cross domain messages. They allow for +the ability to replay cross domain messages and sit directly on top of the lower +level system contracts responsible for cross domain messaging on L1 and L2. + +The `CrossDomainMessenger` is extended to create both an +`L1CrossDomainMessenger` and well as a `L2CrossDomainMessneger`. +These contracts are then extended with their legacy APIs to provide backwards +compatibility for applications that integrated before the Bedrock system +upgrade. + +The `L2CrossDomainMessenger` is a predeploy contract located at +`0x4200000000000000000000000000000000000007`. + +```solidity +interface CrossDomainMessenger { + event FailedRelayedMessage(bytes32 indexed msgHash); + event RelayedMessage(bytes32 indexed msgHash); + event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); + + function MESSAGE_VERSION() view external returns (uint16); + function messageNonce() view external returns (uint256); + function otherMessenger() view external returns (address); + function receivedMessages(bytes32) view external returns (bool); + function relayMessage(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _minGasLimit, bytes memory _message) payable external; + function sendMessage(address _target, bytes memory _message, uint32 _minGasLimit) payable external; + function successfulMessages(bytes32) view external returns (bool); + function xDomainMessageSender() view external returns (address); +} +``` + +## Message Passing + +The `sendMessage` function is used to send a cross domain message. To trigger +the execution on the other side, the `relayMessage` function is called. +Successful messages have their hash stored in the `successfulMessages` mapping +while unsuccessful messages have their hash stored in the `receivedMessages` +mapping. + +The user experience when sending from L1 to L2 is a bit different than when +sending a transaction from L2 to L1. When going into L2 from L1, the user does +not need to call `relayMessage` on L2 themselves. The user pays for L2 gas on L1 +and the transaction is automatically pulled into L2 where it is executed on L2. +When going from L2 into L1, the user must call `relayMessage` on the +`L1CrossDomainMessenger` to finalize the withdrawal. This function can only +be called after the finalization window has passed. + +## Upgradability + +The L1 and L2 cross domain messengers should be deployed behind upgradable +proxies. This will allow for updating the message version. + +## Message Versioning + +Messages are versioned based on the first 2 bytes of their nonce. Depending on +the version, messages can have a different serialization and hashing scheme. +The first two bytes of the nonce are reserved for version metadata because +a version field was not originally included in the messages themselves, but +a `uint256` nonce is so large that we can very easily pack additional data +into that field. + +### Message Version 0 + +```solidity +abi.encodeWithSignature( + "relayMessage(address,address,bytes,uint256)", + _target, + _sender, + _message, + _messageNonce +); +``` + +### Message Version 1 + +```solidity +abi.encodeWithSignature( + "relayMessage(uint256,address,address,uint256,uint256,bytes)", + _nonce, + _sender, + _target, + _value, + _gasLimit, + _data +); +``` + +## Backwards Compatibility Notes + +An older version of the messenger contracts had the concept of blocked messages +in a `blockedMessages` mapping. This functionality was removed from the +messengers because a smart attacker could get around any message blocking +attempts. It also saves gas on finalizing withdrawals. + +The concept of a "relay id" and the `relayedMessages` mapping was removed. +It was built as a way to be able to fund third parties who relayed messages +on the behalf of users, but it was improperly implemented as it was impossible +to know if the relayed message actually succeeded. diff --git a/specs/proposals.md b/specs/proposals.md index 5861f0afe95a..511dd3009838 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -83,10 +83,10 @@ where: L2 state root on L1. 1. The `withdrawal_storage_root` (`bytes32`) elevates the Merkle-Patricia-Trie ([MPT][g-mpt]) root of the [L2 Withdrawal - contract](./withdrawals.md#withdrawer-contract) storage. Instead of making an MPT proof for a withdrawal against the - state root (proving first the storage root of the L2 withdrawal contract against the state root, then the withdrawal - against that storage root), we can prove against the L2 withdrawal contract's storage root directly, thus reducing - the verification cost of withdrawals on L1. + contract](./withdrawals.md#the-l2tol1messagepasser-contract) storage. Instead of making an MPT proof for a withdrawal + against the state root (proving first the storage root of the L2 withdrawal contract against the state root, then + the withdrawal against that storage root), we can prove against the L2 withdrawal contract's storage root directly, + thus reducing the verification cost of withdrawals on L1. ## L2 Output Oracle Smart Contract diff --git a/specs/withdrawals.md b/specs/withdrawals.md index e8ed4f2667c2..e2b3f5010b7e 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -36,7 +36,7 @@ finalization. - [Withdrawal Flow](#withdrawal-flow) - [On L2](#on-l2) - [On L1](#on-l1) -- [The L2 Withdrawer Contract](#the-l2-withdrawer-contract) +- [The L2ToL1MessagePasser Contract](#the-l2tol1messagepasser-contract) - [Address Aliasing](#address-aliasing) - [The Optimism Portal Contract](#the-optimism-portal-contract) - [Withdrawal Verification and Finalization](#withdrawal-verification-and-finalization) @@ -54,7 +54,7 @@ We first describe the end to end flow of initiating and finalizing a withdrawal: ### On L2 -An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdrawer` predeploy contract. +An L2 account sends a withdrawal message (and possibly also ETH) to the `L2ToL1MessagePasser` predeploy contract. This is a very simple contract that stores the a hash of the withdrawal data. ### On L1 @@ -68,34 +68,36 @@ An L2 account sends a withdrawal message (and possibly also ETH) to the `Withdra 3. If verification fails, the call reverts. Otherwise the call is forwarded, and the hash is recorded to prevent it from from being replayed. -## The L2 Withdrawer Contract +## The L2ToL1MessagePasser Contract -[withdrawer-contract]: #the-l2-withdrawer-contract +[message-passer-contract]: #the-l2tol1messagepasser-contract -A withdrawal is initiated by calling the Withdrawer contract's `initiateWithdrawal` function. -The Withdrawer is a simple predeploy contract at `0x4200000000000000000000000000000000000016` which stores messages -to be withdrawn. +A withdrawal is initiated by calling the L2ToL1MessagePasser contract's `initiateWithdrawal` function. +The L2ToL1MessagePasser is a simple predeploy contract at `0x4200000000000000000000000000000000000000` +which stores messages to be withdrawn. ```js -interface Withdrawer { - - event WithdrawalMessage( +interface L2ToL1MessagePasser { + event WithdrawalInitiated( uint256 indexed nonce, // this is a global nonce value for all withdrawal messages address indexed sender, address indexed target, uint256 value, uint256 gasLimit, - bytes message + bytes data ); - function initiateWithdrawal( - address target, - uint256 gasLimit, - bytes data, - ) external payable; + event WithdrawerBalanceBurnt(uint256 indexed amount); + + function burn() external; - function burn(); + function initiateWithdrawal(address _target, uint256 _gasLimit, bytes memory _data) payable external; + + function nonce() view external returns (uint256); + + function sentMessages(bytes32) view external returns (bool); } + ``` ### Address Aliasing @@ -145,7 +147,7 @@ The following inputs are required to verify and finalize a withdrawal: - Proof and verification data: - `timestamp`: The L2 timestamp corresponding with the output root. - `outputRootProof`: Four `bytes32` values which are used to derive the output root. - - `withdrawalProof`: An inclusion proof for the given withdrawal in the withdrawer contract. + - `withdrawalProof`: An inclusion proof for the given withdrawal in the L2ToL1MessagePasser contract. These inputs must satisfy the following conditions: @@ -153,7 +155,7 @@ These inputs must satisfy the following conditions: 1. `OutputOracle.l2Outputs(timestamp)` returns a non-zero value `l2Output`. 1. The keccak256 hash of the `outputRootProof` values is equal to the `l2Output`. 1. The `withdrawalProof` is a valid inclusion proof demonstrating that a hash of the Withdrawal transaction data - is contained in the storage of the Withdrawer contract on L2. + is contained in the storage of the L2ToL1MessagePasser contract on L2. ## Security Considerations From a46e9b7a718e16dbb0834a6118dc1c21836df775 Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 12 May 2022 19:25:18 +0200 Subject: [PATCH 563/585] opnode: p2p RPC, fix static-peers --- opnode/node/node.go | 54 +++++- opnode/node/server.go | 31 ++-- opnode/p2p/api.go | 348 +++++++++++++++++++++++++++++++++++++ opnode/p2p/config.go | 26 ++- opnode/p2p/gossip.go | 6 +- opnode/p2p/host.go | 48 ++++- opnode/p2p/host_test.go | 28 ++- opnode/p2p/notifee.go | 39 +++++ opnode/p2p/prepared.go | 2 +- opnode/test/system_test.go | 3 + 10 files changed, 561 insertions(+), 24 deletions(-) create mode 100644 opnode/p2p/api.go create mode 100644 opnode/p2p/notifee.go diff --git a/opnode/node/node.go b/opnode/node/node.go index 489038a31f8e..7779f1e62a64 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -6,6 +6,9 @@ import ( "sync" "time" + "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p/p2p/protocol/identify" + "github.com/libp2p/go-libp2p-core/peer" "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" @@ -40,6 +43,8 @@ type OpNode struct { l2Nodes []*rpc.Client // L2 Execution Engines to close at shutdown server *rpcServer // RPC server hosting the rollup-node API host host.Host // p2p host (optional, may be nil) + gater p2p.ConnectionGater // p2p gater, to ban/unban peers with, may be nil even with p2p enabled + connMgr connmgr.ConnManager // p2p conn manager, to keep a reliable number of peers, may be nil even with p2p enabled dv5Local *enode.LocalNode // p2p discovery identity (optional, may be nil) dv5Udp *discover.UDPv5 // p2p discovery service (optional, may be nil) gs *pubsub.PubSub // p2p gossip router (optional, may be nil) @@ -109,15 +114,16 @@ func (n *OpNode) init(ctx context.Context, cfg *Config) error { if err := n.initL2(ctx, cfg); err != nil { return err } - if err := n.initRPCServer(ctx, cfg); err != nil { - return err - } if err := n.initP2PSigner(ctx, cfg); err != nil { return err } if err := n.initP2P(ctx, cfg); err != nil { return err } + // Only expose the server at the end, ensuring all RPC backend components are initialized. + if err := n.initRPCServer(ctx, cfg); err != nil { + return err + } return nil } @@ -210,6 +216,9 @@ func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error { if err != nil { return err } + if n.host != nil { + n.server.EnableP2P(p2p.NewP2PAPIBackend(n, n.log)) + } n.log.Info("Starting JSON-RPC server") if err := n.server.Start(); err != nil { return fmt.Errorf("unable to start RPC server: %w", err) @@ -230,12 +239,21 @@ func (n *OpNode) initP2P(ctx context.Context, cfg *Config) error { } // nil if disabled. - n.host, err = cfg.P2P.Host() + n.host, err = cfg.P2P.Host(n.log) if err != nil { return fmt.Errorf("failed to start p2p host: %v", err) } if n.host != nil { + // Enable extra features, if any. During testing we don't setup the most advanced host all the time. + if extra, ok := n.host.(p2p.ExtraHostFeatures); ok { + n.gater = extra.ConnectionGater() + n.connMgr = extra.ConnectionManager() + } + // notify of any new connections/streams/etc. + n.host.Network().Notify(p2p.NewNetworkNotifier(n.log)) + // unregister identify-push handler. Only identifying on dial is fine, and more robust against spam + n.host.RemoveStreamHandler(identify.IDDelta) n.gs, err = p2p.NewGossipSub(n.resourcesCtx, n.host, &cfg.Rollup) if err != nil { return fmt.Errorf("failed to start gossipsub router: %v", err) @@ -337,6 +355,34 @@ func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, payload *l return nil } +func (n *OpNode) Host() host.Host { + return n.host +} + +func (n *OpNode) Dv5Local() *enode.LocalNode { + return n.dv5Local +} + +func (n *OpNode) Dv5Udp() *discover.UDPv5 { + return n.dv5Udp +} + +func (n *OpNode) GossipSub() *pubsub.PubSub { + return n.gs +} + +func (n *OpNode) GossipTopicInfo() p2p.GossipTopicInfo { + return n.gsOut +} + +func (n *OpNode) ConnectionGater() p2p.ConnectionGater { + return n.gater +} + +func (n *OpNode) ConnectionManager() connmgr.ConnManager { + return n.connMgr +} + // Close closes all resources. func (n *OpNode) Close() error { var result *multierror.Error diff --git a/opnode/node/server.go b/opnode/node/server.go index 9109df7425ee..97eda1155ded 100644 --- a/opnode/node/server.go +++ b/opnode/node/server.go @@ -7,6 +7,8 @@ import ( "net" "net/http" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" @@ -19,7 +21,7 @@ import ( type rpcServer struct { endpoint string - api *nodeAPI + apis []rpc.API httpServer *http.Server appVersion string listenAddr net.Addr @@ -32,23 +34,32 @@ func newRPCServer(ctx context.Context, rpcCfg *RPCConfig, rollupCfg *rollup.Conf // TODO: extend RPC config with options for WS, IPC and HTTP RPC connections endpoint := fmt.Sprintf("%s:%d", rpcCfg.ListenAddr, rpcCfg.ListenPort) r := &rpcServer{ - endpoint: endpoint, - api: api, + endpoint: endpoint, + apis: []rpc.API{{ + Namespace: "optimism", + Service: api, + Public: true, + Authenticated: false, + }}, appVersion: appVersion, log: log, } return r, nil } -func (s *rpcServer) Start() error { - apis := []rpc.API{{ - Namespace: "optimism", - Service: s.api, - Public: true, +func (s *rpcServer) EnableP2P(backend *p2p.APIBackend) { + s.apis = append(s.apis, rpc.API{ + Namespace: "", + Version: "", + Service: nil, + Public: false, Authenticated: false, - }} + }) +} + +func (s *rpcServer) Start() error { srv := rpc.NewServer() - if err := node.RegisterApis(apis, nil, srv, true); err != nil { + if err := node.RegisterApis(s.apis, nil, srv, true); err != nil { return err } diff --git a/opnode/p2p/api.go b/opnode/p2p/api.go new file mode 100644 index 000000000000..97a9460f0acf --- /dev/null +++ b/opnode/p2p/api.go @@ -0,0 +1,348 @@ +package p2p + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "net" + "time" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peerstore" + pubsub "github.com/libp2p/go-libp2p-pubsub" + ma "github.com/multiformats/go-multiaddr" +) + +// TODO: dynamic peering +// - req-resp protocol to ensure peers from a different chain learn they shouldn't be connected +// - banning peers based on score +// - store enode in peerstore in dynamic-peering background process +// - peers must be tagged with the "optimism" tag and marked with high value if the chain ID matches + +var ( + DisabledP2P = errors.New("p2p is disabled") + DisabledDiscovery = errors.New("discovery disabled") + NoConnectionManager = errors.New("no connection manager") + NoConnectionGater = errors.New("no connection gater") +) + +type Node interface { + // Host returns the libp2p host, nil if disabled + Host() host.Host + // Dv5Local returns the control over the Discv5 data of the local node, nil if disabled + Dv5Local() *enode.LocalNode + // Dv5Udp returns the control over the Discv5 network, nil if disabled + Dv5Udp() *discover.UDPv5 + // GossipSub returns the gossip router + GossipSub() *pubsub.PubSub + // GossipTopicInfo returns the gossip topic info handle + GossipTopicInfo() GossipTopicInfo + // ConnectionGater returns the connection gater, to ban/unban peers with, may be nil + ConnectionGater() ConnectionGater + // ConnectionManager returns the connection manager, to protect peers with, may be nil + ConnectionManager() connmgr.ConnManager +} + +type APIBackend struct { + node Node + log log.Logger +} + +func NewP2PAPIBackend(node Node, log log.Logger) *APIBackend { + return &APIBackend{ + node: node, + log: log, + } +} + +type PeerInfo struct { + PeerID peer.ID `json:"peerID"` + NodeID enode.ID `json:"nodeID"` + UserAgent string `json:"userAgent"` + ProtocolVersion string `json:"protocolVersion"` + ENR string `json:"ENR"` // might not always be known, e.g. if the peer connected us instead of us discovering them + Addresses []ma.Multiaddr `json:"addresses"` // may be mix of LAN / docker / external IPs. All of them are communicated. + Protocols []string `json:"protocols"` // negotiated protocols list + //GossipScore float64 + //PeerScore float64 + Connectedness network.Connectedness `json:"connectedness"` // "NotConnected", "Connected", "CanConnect" (gracefully disconnected), or "CannotConnect" (tried but failed) + Direction network.Direction `json:"direction"` // "Unknown", "Inbound" (if the peer contacted us), "Outbound" (if we connected to them) + BannedID bool `json:"bannedID"` // If the peer has been banned by peer ID + BannedIP bool `json:"bannedIP"` // If the peer has been banned by IP address + BannedSubnet bool `json:"bannedSubnet"` // If the peer has been banned as part of a whole IP subnet + Protected bool `json:"protected"` // Protected peers do not get + ChainID uint64 `json:"chainID"` // some peers might try to connect, but we figure out they are on a different chain later. This may be 0 if the peer is not an optimism node at all. + Latency time.Duration `json:"latency"` + + GossipBlocks bool `json:"gossipBlocks"` // if the peer is in our gossip topic +} + +func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMgr connmgr.ConnManager) (*PeerInfo, error) { + info := &PeerInfo{ + PeerID: id, + } + + // we might not have the pubkey if it's from a multi-addr and if we never discovered/connected them + pub := pstore.PubKey(id) + if pub != nil { + typedPub, ok := pub.(*crypto.Secp256k1PublicKey) + if !ok { + return nil, fmt.Errorf("unexpected pubkey type: %T", pub) + } + info.NodeID = enode.PubkeyToIDV4((*ecdsa.PublicKey)(typedPub)) + } + if dat, err := pstore.Get(id, "ProtocolVersion"); err != nil { + protocolVersion, ok := dat.(string) + if ok { + info.ProtocolVersion = protocolVersion + } + } + if dat, err := pstore.Get(id, "AgentVersion"); err != nil { + agentVersion, ok := dat.(string) + if ok { + info.UserAgent = agentVersion + } + } + if dat, err := pstore.Get(id, "ENR"); err != nil { + enodeData, ok := dat.(*enode.Node) + if ok { + info.ENR = enodeData.String() + } + } + info.Addresses = pstore.Addrs(id) + info.Connectedness = nw.Connectedness(id) + if protocols, err := pstore.GetProtocols(id); err != nil { + info.Protocols = protocols + } + // get the first connection direction, if any (will default to unknown when there are no connections) + for _, c := range nw.ConnsToPeer(id) { + info.Direction = c.Stat().Direction + break + } + if dat, err := pstore.Get(id, "optimismChainID"); err != nil { + chID, ok := dat.(uint64) + if ok { + info.ChainID = chID + } + } + info.Latency = pstore.LatencyEWMA(id) + if connMgr != nil { + info.Protected = connMgr.IsProtected(id, "") + } + + return info, nil +} + +type PeerDump struct { + TotalConnected uint `json:"totalConnected"` + Peers map[peer.ID]*PeerInfo `json:"peers"` + BannedPeers []peer.ID `json:"bannedPeers"` + BannedIPS []net.IP `json:"bannedIPS"` + BannedSubnets []*net.IPNet `json:"bannedSubnets"` +} + +// Peers lists information of peers. Optionally filter to only retrieve connected peers. +func (s *APIBackend) Peers(ctx context.Context, connected bool) (*PeerDump, error) { + h := s.node.Host() + if h == nil { + return nil, DisabledP2P + } + + nw := h.Network() + pstore := h.Peerstore() + var peers []peer.ID + if connected { + peers = nw.Peers() + } else { + peers = pstore.Peers() + } + + dump := &PeerDump{Peers: make(map[peer.ID]*PeerInfo)} + for _, id := range peers { + peerInfo, err := dumpPeer(id, nw, pstore, s.node.ConnectionManager()) + if err != nil { + dump.Peers[id] = peerInfo + } + if peerInfo.Connectedness == network.Connected { + dump.TotalConnected += 1 + } + } + for _, id := range s.node.GossipTopicInfo().BlocksTopicPeers() { + if p, ok := dump.Peers[id]; ok { + p.GossipBlocks = true + } + } + if gater := s.node.ConnectionGater(); gater != nil { + dump.BannedPeers = gater.ListBlockedPeers() + dump.BannedSubnets = gater.ListBlockedSubnets() + dump.BannedIPS = gater.ListBlockedAddrs() + } + return dump, nil +} + +type PeerStats struct { + Connected uint `json:"connected"` + Table uint `json:"table"` + BlocksTopic uint `json:"blocksTopic"` + Banned uint `json:"banned"` + Known uint `json:"known"` +} + +func (s *APIBackend) PeerStats() (*PeerStats, error) { + h := s.node.Host() + if h == nil { + return nil, DisabledP2P + } + + nw := h.Network() + pstore := h.Peerstore() + + stats := &PeerStats{ + Connected: uint(len(nw.Peers())), + Table: 0, + BlocksTopic: uint(len(s.node.GossipTopicInfo().BlocksTopicPeers())), + Banned: 0, + Known: uint(len(pstore.Peers())), + } + if gater := s.node.ConnectionGater(); gater != nil { + stats.Banned = uint(len(gater.ListBlockedPeers())) + } + if dv5 := s.node.Dv5Udp(); dv5 != nil { + stats.Table = uint(len(dv5.AllNodes())) + } + return stats, nil +} + +func (s *APIBackend) DiscoveryTable() ([]*enode.Node, error) { + if dv5 := s.node.Dv5Udp(); dv5 != nil { + return dv5.AllNodes(), nil + } else { + return nil, DisabledDiscovery + } +} + +func (s *APIBackend) BlockPeer(p peer.ID) error { + if gater := s.node.ConnectionGater(); gater == nil { + return NoConnectionGater + } else { + return gater.BlockPeer(p) + } +} + +func (s *APIBackend) UnblockPeer(p peer.ID) error { + if gater := s.node.ConnectionGater(); gater == nil { + return NoConnectionGater + } else { + return gater.UnblockPeer(p) + } +} + +func (s *APIBackend) ListBlockedPeers() ([]peer.ID, error) { + if gater := s.node.ConnectionGater(); gater == nil { + return nil, NoConnectionGater + } else { + return gater.ListBlockedPeers(), nil + } +} + +// BlockAddr adds an IP address to the set of blocked addresses. +// Note: active connections to the IP address are not automatically closed. +func (s *APIBackend) BlockAddr(ip net.IP) error { + if gater := s.node.ConnectionGater(); gater == nil { + return NoConnectionGater + } else { + return gater.BlockAddr(ip) + } +} + +func (s *APIBackend) UnblockAddr(ip net.IP) error { + if gater := s.node.ConnectionGater(); gater == nil { + return NoConnectionGater + } else { + return gater.UnblockAddr(ip) + } +} + +func (s *APIBackend) ListBlockedAddrs() ([]net.IP, error) { + if gater := s.node.ConnectionGater(); gater == nil { + return nil, NoConnectionGater + } else { + return gater.ListBlockedAddrs(), nil + } +} + +// BlockSubnet adds an IP subnet to the set of blocked addresses. +// Note: active connections to the IP subnet are not automatically closed. +func (s *APIBackend) BlockSubnet(ipnet *net.IPNet) error { + if gater := s.node.ConnectionGater(); gater == nil { + return NoConnectionGater + } else { + return gater.BlockSubnet(ipnet) + } +} + +func (s *APIBackend) UnblockSubnet(ipnet *net.IPNet) error { + if gater := s.node.ConnectionGater(); gater == nil { + return NoConnectionGater + } else { + return gater.UnblockSubnet(ipnet) + } +} + +func (s *APIBackend) ListBlockedSubnets() ([]*net.IPNet, error) { + if gater := s.node.ConnectionGater(); gater == nil { + return nil, NoConnectionGater + } else { + return gater.ListBlockedSubnets(), nil + } +} + +func (s *APIBackend) ProtectPeer(p peer.ID) error { + if manager := s.node.ConnectionManager(); manager == nil { + return NoConnectionManager + } else { + manager.Protect(p, "api-protected") + return nil + } +} + +func (s *APIBackend) UnprotectPeer(p peer.ID) error { + if manager := s.node.ConnectionManager(); manager == nil { + return NoConnectionManager + } else { + manager.Unprotect(p, "api-protected") + return nil + } +} + +// ConnectPeer connects to a given peer address, and wait for protocol negotiation & identification of the peer +func (s *APIBackend) ConnectPeer(ctx context.Context, addr ma.Multiaddr) error { + h := s.node.Host() + if h == nil { + return DisabledP2P + } + addrInfo, err := peer.AddrInfoFromP2pAddr(addr) + if err != nil { + return fmt.Errorf("bad peer address: %v", err) + } + // Put a sanity limit on the connection time + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() + return h.Connect(ctx, *addrInfo) +} + +func (s *APIBackend) DisconnectPeer(id peer.ID) error { + h := s.node.Host() + if h == nil { + return DisabledP2P + } + return h.Network().ClosePeer(id) +} diff --git a/opnode/p2p/config.go b/opnode/p2p/config.go index 90cfd4e2ba5a..502ede54cecf 100644 --- a/opnode/p2p/config.go +++ b/opnode/p2p/config.go @@ -12,6 +12,8 @@ import ( "strings" "time" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/libp2p/go-libp2p-core/host" @@ -40,7 +42,7 @@ import ( type SetupP2P interface { Check() error // Host creates a libp2p host service. Returns nil, nil if p2p is disabled. - Host() (host.Host, error) + Host(log log.Logger) (host.Host, error) // Discovery creates a disc-v5 service. Returns nil, nil, nil if discovery is disabled. Discovery(log log.Logger) (*enode.LocalNode, *discover.UDPv5, error) } @@ -93,6 +95,28 @@ type Config struct { BandwidthMetrics metrics.Reporter } +type ConnectionGater interface { + connmgr.ConnectionGater + + // BlockPeer adds a peer to the set of blocked peers. + // Note: active connections to the peer are not automatically closed. + BlockPeer(p peer.ID) error + UnblockPeer(p peer.ID) error + ListBlockedPeers() []peer.ID + + // BlockAddr adds an IP address to the set of blocked addresses. + // Note: active connections to the IP address are not automatically closed. + BlockAddr(ip net.IP) error + UnblockAddr(ip net.IP) error + ListBlockedAddrs() []net.IP + + // BlockSubnet adds an IP subnet to the set of blocked addresses. + // Note: active connections to the IP subnet are not automatically closed. + BlockSubnet(ipnet *net.IPNet) error + UnblockSubnet(ipnet *net.IPNet) error + ListBlockedSubnets() []*net.IPNet +} + func DefaultConnGater(conf *Config) (connmgr.ConnectionGater, error) { return conngater.NewBasicConnectionGater(conf.Store) } diff --git a/opnode/p2p/gossip.go b/opnode/p2p/gossip.go index 1cc3aed4a6e3..79eb3e9b363b 100644 --- a/opnode/p2p/gossip.go +++ b/opnode/p2p/gossip.go @@ -289,9 +289,13 @@ type GossipIn interface { OnUnsafeL2Payload(ctx context.Context, from peer.ID, msg *l2.ExecutionPayload) error } +type GossipTopicInfo interface { + BlocksTopicPeers() []peer.ID +} + type GossipOut interface { + GossipTopicInfo PublishL2Payload(ctx context.Context, msg *l2.ExecutionPayload, signer Signer) error - BlocksTopicPeers() []peer.ID Close() error } diff --git a/opnode/p2p/host.go b/opnode/p2p/host.go index 5aabfda4e3e2..08d836a5f4d2 100644 --- a/opnode/p2p/host.go +++ b/opnode/p2p/host.go @@ -6,6 +6,9 @@ import ( "net" "time" + "github.com/ethereum/go-ethereum/log" + "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" @@ -17,7 +20,20 @@ import ( madns "github.com/multiformats/go-multiaddr-dns" ) -func (conf *Config) Host() (host.Host, error) { +type ExtraHostFeatures interface { + ConnectionGater() ConnectionGater + ConnectionManager() connmgr.ConnManager +} + +type extraHost struct { + host.Host + gater ConnectionGater + connMgr connmgr.ConnManager +} + +var _ host.Host = (*extraHost)(nil) + +func (conf *Config) Host(log log.Logger) (host.Host, error) { if conf.DisableP2P { return nil, nil } @@ -114,7 +130,35 @@ func (conf *Config) Host() (host.Host, error) { EnableHolePunching: false, HolePunchingOptions: nil, } - return p2pConf.NewNode() + h, err := p2pConf.NewNode() + if err != nil { + return nil, err + } + for _, peerAddr := range conf.StaticPeers { + addr, err := peer.AddrInfoFromP2pAddr(peerAddr) + if err != nil { + return nil, fmt.Errorf("bad peer address: %v", err) + } + h.Peerstore().AddAddrs(addr.ID, addr.Addrs, time.Hour*24*7) + // We protect the peer, so the connection manager doesn't decide to prune it. + // We tag it with "static" so other protects/unprotects with different tags don't affect this protection. + connMngr.Protect(addr.ID, "static") + // Try to dial the node in the background + go func() { + log.Info("Dialing static peer", "peer", addr.ID, "addrs", addr.Addrs) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + if _, err := h.Network().DialPeer(ctx, addr.ID); err != nil { + log.Warn("Failed to dial static peer", "peer", addr.ID, "addrs", addr.Addrs) + } + }() + } + out := &extraHost{Host: h, connMgr: connMngr} + // Only add the connection gater if it offers the full interface we're looking for. + if g, ok := connGtr.(ConnectionGater); ok { + out.gater = g + } + return out, nil } // Creates a multi-addr to bind to. Does not contain a PeerID component (required for usage by external peers) diff --git a/opnode/p2p/host_test.go b/opnode/p2p/host_test.go index c346e6a5ed91..e2db746ae702 100644 --- a/opnode/p2p/host_test.go +++ b/opnode/p2p/host_test.go @@ -8,6 +8,9 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum/go-ethereum/log" + ds "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/sync" "github.com/libp2p/go-libp2p-core/connmgr" @@ -57,10 +60,10 @@ func TestingConfig(t *testing.T) *Config { func TestP2PSimple(t *testing.T) { confA := TestingConfig(t) confB := TestingConfig(t) - hostA, err := confA.Host() + hostA, err := confA.Host(testlog.Logger(t, log.LvlError).New("host", "A")) require.NoError(t, err, "failed to launch host A") defer hostA.Close() - hostB, err := confB.Host() + hostB, err := confB.Host(testlog.Logger(t, log.LvlError).New("host", "B")) require.NoError(t, err, "failed to launch host B") defer hostB.Close() err = hostA.Connect(context.Background(), peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) @@ -112,13 +115,28 @@ func TestP2PFull(t *testing.T) { confB.Store = sync.MutexWrap(ds.NewMapDatastore()) // TODO: maybe swap the order of sec/mux preferences, to test that negotiation works - hostA, err := confA.Host() + hostA, err := confA.Host(testlog.Logger(t, log.LvlError).New("host", "A")) require.NoError(t, err) defer hostA.Close() - hostB, err := confB.Host() + + // Set up B to connect statically + confB.StaticPeers, err = peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: hostA.ID(), Addrs: hostA.Addrs()}) + require.NoError(t, err) + + conns := make(chan network.Conn, 1) + hostA.Network().Notify(&network.NotifyBundle{ConnectedF: func(n network.Network, conn network.Conn) { + conns <- conn + }}) + + hostB, err := confB.Host(testlog.Logger(t, log.LvlError).New("host", "B")) require.NoError(t, err) defer hostB.Close() - err = hostA.Connect(context.Background(), peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) + + select { + case <-time.After(time.Second): + t.Fatal("failed to connect new host") + case <-conns: + } require.NoError(t, err, "failed to connect to peer B from peer A") require.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) } diff --git a/opnode/p2p/notifee.go b/opnode/p2p/notifee.go new file mode 100644 index 000000000000..611caa9342b9 --- /dev/null +++ b/opnode/p2p/notifee.go @@ -0,0 +1,39 @@ +package p2p + +import ( + "github.com/ethereum/go-ethereum/log" + "github.com/libp2p/go-libp2p-core/network" + ma "github.com/multiformats/go-multiaddr" +) + +// TODO: add metrics here as well + +type notifications struct { + log log.Logger +} + +func (notif *notifications) Listen(n network.Network, a ma.Multiaddr) { + notif.log.Info("started listening network address", "addr", a) +} +func (notif *notifications) ListenClose(n network.Network, a ma.Multiaddr) { + notif.log.Info("stopped listening network address", "addr", a) +} +func (notif *notifications) Connected(n network.Network, v network.Conn) { + + notif.log.Info("connected to peer", "peer", v.RemotePeer(), "addr", v.RemoteMultiaddr()) +} +func (notif *notifications) Disconnected(n network.Network, v network.Conn) { + notif.log.Info("disconnected from peer", "peer", v.RemotePeer(), "addr", v.RemoteMultiaddr()) +} +func (notif *notifications) OpenedStream(n network.Network, v network.Stream) { + c := v.Conn() + notif.log.Trace("opened stream", "protocol", v.Protocol(), "peer", c.RemotePeer(), "addr", c.RemoteMultiaddr()) +} +func (notif *notifications) ClosedStream(n network.Network, v network.Stream) { + c := v.Conn() + notif.log.Trace("opened stream", "protocol", v.Protocol(), "peer", c.RemotePeer(), "addr", c.RemoteMultiaddr()) +} + +func NewNetworkNotifier(log log.Logger) network.Notifiee { + return ¬ifications{log: log} +} diff --git a/opnode/p2p/prepared.go b/opnode/p2p/prepared.go index 482dfdd92be0..72c3a18b07b0 100644 --- a/opnode/p2p/prepared.go +++ b/opnode/p2p/prepared.go @@ -31,7 +31,7 @@ func (p *Prepared) Check() error { } // Host creates a libp2p host service. Returns nil, nil if p2p is disabled. -func (p *Prepared) Host() (host.Host, error) { +func (p *Prepared) Host(log log.Logger) (host.Host, error) { return p.HostP2P, nil } diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index debff989b9fc..e7f0c047f18a 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -539,6 +539,9 @@ func TestSystemMockP2P(t *testing.T) { // Verify that the tx was received via p2p require.Contains(t, published, receiptVerif.BlockHash) + + // Try get p2p debug info from the RPC + // TODO: RPC client bindings for p2p api } func TestL1InfoContract(t *testing.T) { From a817f7697052c18b1ae0e460a04d81e33b2a753b Mon Sep 17 00:00:00 2001 From: Murphy Law Date: Thu, 12 May 2022 15:33:59 -0400 Subject: [PATCH 564/585] StateViz: Visualize rollup state changes (#419) * StateViz: Visualize rollup state changes * remove DEBUGMEs * Add L1WindowBuf to viz * move stateviz to opnode/cmd * Add stateviz to docker-compose * html lint * Add SRI * Fix linter * Merge fixes * Fixes from code review * Imports * Fix space Co-authored-by: Matthew Slipper --- opnode/cmd/main.go | 7 +- opnode/cmd/stateviz/assets/index.html | 28 +++ opnode/cmd/stateviz/assets/main.js | 111 ++++++++++++ opnode/cmd/stateviz/main.go | 245 ++++++++++++++++++++++++++ opnode/flags/flags.go | 7 + opnode/node/node.go | 18 +- opnode/rollup/driver/driver.go | 4 +- opnode/rollup/driver/state.go | 31 +++- opnode/rollup/driver/state_test.go | 2 +- opnode/service.go | 18 ++ opnode/test/setup.go | 2 +- ops/Dockerfile.stateviz | 19 ++ ops/devnet-up.sh | 4 + ops/docker-compose.yml | 22 ++- 14 files changed, 499 insertions(+), 19 deletions(-) create mode 100644 opnode/cmd/stateviz/assets/index.html create mode 100644 opnode/cmd/stateviz/assets/main.js create mode 100644 opnode/cmd/stateviz/main.go create mode 100644 ops/Dockerfile.stateviz diff --git a/opnode/cmd/main.go b/opnode/cmd/main.go index 760b20cd96fb..f0e32c0d1e14 100644 --- a/opnode/cmd/main.go +++ b/opnode/cmd/main.go @@ -72,8 +72,13 @@ func RollupNodeMain(ctx *cli.Context) error { log.Error("Unable to create the log config", "error", err) return err } + snapshotLog, err := opnode.NewSnapshotLogger(ctx) + if err != nil { + log.Error("Unable to create snapshot root logger", "error", err) + return err + } - n, err := node.New(context.Background(), cfg, logCfg.NewLogger(), VersionWithMeta) + n, err := node.New(context.Background(), cfg, logCfg.NewLogger(), snapshotLog, VersionWithMeta) if err != nil { log.Error("Unable to create the rollup node", "error", err) return err diff --git a/opnode/cmd/stateviz/assets/index.html b/opnode/cmd/stateviz/assets/index.html new file mode 100644 index 000000000000..486a47395e44 --- /dev/null +++ b/opnode/cmd/stateviz/assets/index.html @@ -0,0 +1,28 @@ + + + + + + + + + + + +
+
+
+
+ + + + + + + + + diff --git a/opnode/cmd/stateviz/assets/main.js b/opnode/cmd/stateviz/assets/main.js new file mode 100644 index 000000000000..b0199ec65447 --- /dev/null +++ b/opnode/cmd/stateviz/assets/main.js @@ -0,0 +1,111 @@ +function prettyHex(hash) { + return `${hash.slice(0, 8)}..${hash.slice(56)}`; +} + +// return a light-ish hue +function colorCode(hash) { + const code = parseInt(hash.slice(60), 16); + const h = code % 361; + const s = code % 101; + let l = code % 101; + // yeah this is biased but it's good enough + if (l < 30) { + l += 30; + } + return `hsl(${h}, ${s}%, ${l}%)`; +} + +async function fetchLogs() { + const response = await fetch("/logs"); + return await response.json(); +} + +async function pageTable() { + const logs = await fetchLogs(); + if (logs.length === 0) { + return + } + + const dataEl = $(`
`); + $("#logs").append(dataEl); + + let numCols = 0 + if (logs.length !== 0) { + numCols = logs[0].length + } + const paginationEl = $(``) + $("#logs").append(paginationEl) + paginationEl.pagination({ + dataSource: logs, + pageSize: 20, + showGoInput: true, + showGoButton: true, + callback: (data, pagination) => { + let tables = [] + for (var i = 0; i < numCols; i++) { + // TODO: Fix grid overflow with more than 2 rollup drivers + let html = '
'; + html += ` + + + + + + + + + + + + `; + html += ""; + + // TODO: it'll also be useful to indicate which rollup driver updated its state for the given timestamp + for (const record of data) { + const e = record[i]; + if (e === undefined) { + // this column has reached its end + break + } + + let windowBufEl = `
    ` + e.l1WindowBuf.forEach((x) => { + windowBufEl += `
  • ${prettyHex(x.hash)}
  • ` + }) + windowBufEl += "
" + + // TODO: click to copy full hash + html += ` + + + + + + + `; + } + html += ""; + html += "
${data[0][i].engine_addr}
TimestampL1HeadL2HeadL2SafeHeadL2FinalizedHeadL1WindowBuf
+ ${e.t} + + ${prettyHex(e.l1Head.hash)} + + ${prettyHex(e.l2Head.hash)} + + ${prettyHex(e.l2SafeHead.hash)} + + ${prettyHex(e.l2FinalizedHead.hash)} + ${windowBufEl}
"; + tables.push(html); + } + + const html = tables.join("\n"); + dataEl.html(html); + $('[data-toggle="tooltip"]').tooltip(); + } + }) +} + +(async () => { + pageTable() +})() diff --git a/opnode/cmd/stateviz/main.go b/opnode/cmd/stateviz/main.go new file mode 100644 index 000000000000..edc7b2dba6b0 --- /dev/null +++ b/opnode/cmd/stateviz/main.go @@ -0,0 +1,245 @@ +package main + +import ( + "bufio" + "compress/gzip" + "embed" + "encoding/json" + "errors" + "flag" + "fmt" + "io" + "io/fs" + "net" + "net/http" + "os" + "strconv" + "strings" + "sync" + "time" + + "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum/go-ethereum/log" +) + +var ( + snapshot = flag.String("snapshot", "", "path to snapshot log") + listenAddr = flag.String("addr", "", "listen address of webserver") + refresh = flag.Duration("refresh", 10*time.Second, "snapshot refresh rate") +) + +var ( + entries map[string][]SnapshotState + entriesMutex sync.Mutex + + assetFS fs.FS +) + +type SnapshotState struct { + Timestamp string `json:"t"` + EngineAddr string `json:"engine_addr"` + Event string `json:"event"` + L1Head eth.L1BlockRef `json:"l1Head"` + L2Head eth.L2BlockRef `json:"l2Head"` + L2SafeHead eth.L2BlockRef `json:"l2SafeHead"` + L2FinalizedHead eth.BlockID `json:"l2FinalizedHead"` + L1WindowBuf []eth.BlockID `json:"l1WindowBuf"` +} + +func (e *SnapshotState) UnmarshalJSON(data []byte) error { + t := struct { + Timestamp string `json:"t"` + EngineAddr string `json:"engine_addr"` + Event string `json:"event"` + L1Head json.RawMessage `json:"l1Head"` + L2Head json.RawMessage `json:"l2Head"` + L2SafeHead json.RawMessage `json:"l2SafeHead"` + L2FinalizedHead json.RawMessage `json:"l2FinalizedHead"` + L1WindowBuf json.RawMessage `json:"l1WindowBuf"` + }{} + if err := json.Unmarshal(data, &t); err != nil { + return err + } + e.Timestamp = t.Timestamp + e.EngineAddr = t.EngineAddr + e.Event = t.Event + + unquote := func(d json.RawMessage) []byte { + s, _ := strconv.Unquote(string(d)) + return []byte(s) + } + + if err := json.Unmarshal(unquote(t.L1Head), &e.L1Head); err != nil { + return err + } + if err := json.Unmarshal(unquote(t.L2Head), &e.L2Head); err != nil { + return err + } + if err := json.Unmarshal(unquote(t.L2SafeHead), &e.L2SafeHead); err != nil { + return err + } + if err := json.Unmarshal(unquote(t.L2FinalizedHead), &e.L2FinalizedHead); err != nil { + return err + } + if err := json.Unmarshal(unquote(t.L1WindowBuf), &e.L1WindowBuf); err != nil { + return err + } + if e.L1WindowBuf == nil { + e.L1WindowBuf = make([]eth.BlockID, 0) + } + return nil +} + +//go:embed assets +var embeddedAssets embed.FS + +func main() { + flag.Parse() + + log.Root().SetHandler( + log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stdout, log.TerminalFormat(true))), + ) + + if *snapshot == "" { + log.Crit("missing required -snapshot flag") + } + + sub, err := fs.Sub(embeddedAssets, "assets") + if err != nil { + log.Crit("Failed to open asset directory", "message", err) + } + assetFS = sub + + go func() { + ticker := time.NewTicker(*refresh) + defer ticker.Stop() + for range ticker.C { + // TODO: incremental load + log.Info("loading snapshot...") + if err := loadSnapshot(); err != nil { + log.Error("failed to load snapshot", "err", err) + } + } + }() + + runServer() +} + +func loadSnapshot() error { + file, err := os.Open(*snapshot) + if err != nil { + return fmt.Errorf("%w: failed to open snapshot file", err) + } + defer file.Close() + + tempEntries := make(map[string][]SnapshotState) + scanner := bufio.NewScanner(file) + for scanner.Scan() { + var entry SnapshotState + if err := json.Unmarshal([]byte(scanner.Text()), &entry); err != nil { + return fmt.Errorf("%w: failed to decode snapshot log", err) + } + + tempEntries[entry.EngineAddr] = append(tempEntries[entry.EngineAddr], entry) + } + if err := scanner.Err(); err != nil { + return fmt.Errorf("%w: failed to scan snapshot file", err) + } + + entriesMutex.Lock() + entries = tempEntries + entriesMutex.Unlock() + + return nil +} + +func runServer() { + l, err := net.Listen("tcp", *listenAddr) + if err != nil { + log.Crit("Failed to listen on address", "message", err) + } + + mux := http.NewServeMux() + mux.Handle("/", http.FileServer(http.FS(assetFS))) + mux.HandleFunc("/logs", makeGzipHandler(logsHandler)) + + log.Info("running webserver...") + if err := http.Serve(l, mux); err != nil && !errors.Is(err, http.ErrServerClosed) { + log.Crit("http server failed", "message", err) + } +} + +type gzipResponseWriter struct { + io.Writer + http.ResponseWriter +} + +func (w gzipResponseWriter) Write(b []byte) (int, error) { + return w.Writer.Write(b) +} + +func makeGzipHandler(fn http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + fn(w, r) + return + } + w.Header().Set("Content-Encoding", "gzip") + gz := gzip.NewWriter(w) + defer gz.Close() + gzr := gzipResponseWriter{Writer: gz, ResponseWriter: w} + fn(gzr, r) + } +} + +func logsHandler(w http.ResponseWriter, r *http.Request) { + var output [][]SnapshotState + + entriesMutex.Lock() + // shallow copy so we can update the SnapshotState slice head + entriesCopy := make(map[string][]SnapshotState) + for k, v := range entries { + entriesCopy[k] = v + } + entriesMutex.Unlock() + + // sort log entries and zip em up + // Each record/row contains SnapshotStates for each rollup driver + // Note that we assume each SnapshotState slice is sorted by the timestamp + for { + var min *SnapshotState + var minKey string + for k, v := range entriesCopy { + if len(v) == 0 { + continue + } + if min == nil || v[0].Timestamp < min.Timestamp { + min = &v[0] + minKey = k + } + } + + if min == nil { + break + } + + entriesCopy[minKey] = entriesCopy[minKey][1:] + + rec := make([]SnapshotState, 0, len(entriesCopy)) + rec = append(rec, *min) + for k, v := range entriesCopy { + if k != minKey && len(v) != 0 { + newEntry := v[0] + newEntry.Timestamp = min.Timestamp + rec = append(rec, newEntry) + } + } + output = append(output, rec) + } + + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Cache-Control", "public, max-age=100000") + if err := json.NewEncoder(w).Encode(output); err != nil { + log.Warn("failed to encode logs", "message", err) + } +} diff --git a/opnode/flags/flags.go b/opnode/flags/flags.go index b1f0287ac18c..f06e10e67761 100644 --- a/opnode/flags/flags.go +++ b/opnode/flags/flags.go @@ -80,6 +80,12 @@ var ( Usage: "Color the log output", EnvVar: prefixEnvVar("LOG_COLOR"), } + + SnapshotLog = cli.StringFlag{ + Name: "snapshotlog.file", + Usage: "Path to the snapshot log file", + EnvVar: prefixEnvVar("SNAPSHOT_LOG"), + } ) var requiredFlags = []cli.Flag{ @@ -97,6 +103,7 @@ var optionalFlags = append([]cli.Flag{ LogLevelFlag, LogFormatFlag, LogColorFlag, + SnapshotLog, }, p2pFlags...) // Flags contains the list of configuration options available to the binary. diff --git a/opnode/node/node.go b/opnode/node/node.go index 489038a31f8e..3bd2f1aed9c0 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -76,7 +76,7 @@ func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) return ret, nil } -func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (*OpNode, error) { +func New(ctx context.Context, cfg *Config, log log.Logger, snapshotLog log.Logger, appVersion string) (*OpNode, error) { if err := cfg.Check(); err != nil { return nil, err } @@ -88,7 +88,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* // not a context leak, gossipsub is closed with a context. n.resourcesCtx, n.resourcesClose = context.WithCancel(context.Background()) - err := n.init(ctx, cfg) + err := n.init(ctx, cfg, snapshotLog) if err != nil { // ensure we always close the node resources if we fail to initialize the node. if closeErr := n.Close(); closeErr != nil { @@ -99,14 +99,14 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string) (* return n, nil } -func (n *OpNode) init(ctx context.Context, cfg *Config) error { +func (n *OpNode) init(ctx context.Context, cfg *Config, snapshotLog log.Logger) error { if err := n.initTracer(ctx, cfg); err != nil { return err } if err := n.initL1(ctx, cfg); err != nil { return err } - if err := n.initL2(ctx, cfg); err != nil { + if err := n.initL2(ctx, cfg, snapshotLog); err != nil { return err } if err := n.initRPCServer(ctx, cfg); err != nil { @@ -161,7 +161,7 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error { } // AttachEngine attaches an engine to the rollup node. -func (n *OpNode) AttachEngine(ctx context.Context, cfg *Config, addr string) error { +func (n *OpNode) AttachEngine(ctx context.Context, cfg *Config, addr string, snapshotLog log.Logger) error { n.l2Lock.Lock() defer n.l2Lock.Unlock() @@ -180,16 +180,17 @@ func (n *OpNode) AttachEngine(ctx context.Context, cfg *Config, addr string) err return err } - engine := driver.NewDriver(cfg.Rollup, client, n.l1Source, n, engLog, cfg.Sequencer) + snap := snapshotLog.New("engine_addr", addr) + engine := driver.NewDriver(cfg.Rollup, client, n.l1Source, n, engLog, snap, cfg.Sequencer) n.l2Nodes = append(n.l2Nodes, l2Node) n.l2Engines = append(n.l2Engines, engine) return nil } -func (n *OpNode) initL2(ctx context.Context, cfg *Config) error { +func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger) error { for i, addr := range cfg.L2EngineAddrs { - if err := n.AttachEngine(ctx, cfg, addr); err != nil { + if err := n.AttachEngine(ctx, cfg, addr, snapshotLog); err != nil { return fmt.Errorf("failed to attach configured engine %d (%s): %v", i, addr, err) } } @@ -202,6 +203,7 @@ func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error { return fmt.Errorf("failed to dial l2 address (%s): %w", cfg.L2NodeAddr, err) } + // TODO: attach the p2p node ID to the snapshot logger client, err := l2.NewReadOnlySource(l2Node, &cfg.Rollup.Genesis, n.log) if err != nil { return err diff --git a/opnode/rollup/driver/driver.go b/opnode/rollup/driver/driver.go index e7e90c1ae6b2..816caea9a626 100644 --- a/opnode/rollup/driver/driver.go +++ b/opnode/rollup/driver/driver.go @@ -66,7 +66,7 @@ type Network interface { PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayload) error } -func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, network Network, log log.Logger, sequencer bool) *Driver { +func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, network Network, log log.Logger, snapshotLog log.Logger, sequencer bool) *Driver { output := &outputImpl{ Config: cfg, dl: l1, @@ -74,7 +74,7 @@ func NewDriver(cfg rollup.Config, l2 *l2.Source, l1 *l1.Source, network Network, log: log, } return &Driver{ - s: NewState(log, cfg, l1, l2, output, network, sequencer), + s: NewState(log, snapshotLog, cfg, l1, l2, output, network, sequencer), } } diff --git a/opnode/rollup/driver/state.go b/opnode/rollup/driver/state.go index c5599ace9c22..28aa6eff1f58 100644 --- a/opnode/rollup/driver/state.go +++ b/opnode/rollup/driver/state.go @@ -2,6 +2,7 @@ package driver import ( "context" + "encoding/json" "fmt" gosync "sync" "time" @@ -33,19 +34,21 @@ type state struct { output outputInterface network Network // may be nil, network for is optional - log log.Logger - done chan struct{} + log log.Logger + snapshotLog log.Logger + done chan struct{} wg gosync.WaitGroup } // NewState creates a new driver state. State changes take effect though the given output. // Optionally a network can be provided to publish things to other nodes than the engine of the driver. -func NewState(log log.Logger, config rollup.Config, l1Chain L1Chain, l2Chain L2Chain, output outputInterface, network Network, sequencer bool) *state { +func NewState(log log.Logger, snapshotLog log.Logger, config rollup.Config, l1Chain L1Chain, l2Chain L2Chain, output outputInterface, network Network, sequencer bool) *state { return &state{ Config: config, done: make(chan struct{}), log: log, + snapshotLog: snapshotLog, l1: l1Chain, l2: l2Chain, output: output, @@ -274,8 +277,8 @@ func (s *state) createNewL2Block(ctx context.Context) error { func (s *state) handleEpoch(ctx context.Context) (bool, error) { s.log.Trace("Handling epoch", "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead) // Extend cached window if we do not have enough saved blocks + // attempt to buffer up to 2x the size of a sequence window of L1 blocks, to speed up later handleEpoch calls if len(s.l1WindowBuf) < int(s.Config.SeqWindowSize) { - // attempt to buffer up to 2x the size of a sequence window of L1 blocks, to speed up later handleEpoch calls nexts, err := s.l1.L1Range(ctx, s.l1WindowBufEnd(), 2*s.Config.SeqWindowSize) if err != nil { s.log.Error("Could not extend the cached L1 window", "err", err, "l2Head", s.l2Head, "l2SafeHead", s.l2SafeHead, "l1Head", s.l1Head, "window_end", s.l1WindowBufEnd()) @@ -391,9 +394,11 @@ func (s *state) loop() { select { case <-l2BlockCreationTickerCh: s.log.Trace("L2 Creation Ticker") + s.snapshot("L2 Creation Ticker") reqL2BlockCreation() case <-l2BlockCreationReqCh: + s.snapshot("L2 Block Creation Request") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) err := s.createNewL2Block(ctx) cancel() @@ -418,6 +423,7 @@ func (s *state) loop() { } case newL1Head := <-s.l1Heads: + s.snapshot("New L1 Head") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) err := s.handleNewL1Block(ctx, newL1Head) cancel() @@ -436,6 +442,7 @@ func (s *state) loop() { } case <-stepReqCh: + s.snapshot("Step Request") ctx, cancel := context.WithTimeout(ctx, 10*time.Second) reorg, err := s.handleEpoch(ctx) cancel() @@ -469,3 +476,19 @@ func (s *state) loop() { } } } + +func (s *state) snapshot(event string) { + l1HeadJSON, _ := json.Marshal(s.l1Head) + l2HeadJSON, _ := json.Marshal(s.l2Head) + l2SafeHeadJSON, _ := json.Marshal(s.l2SafeHead) + l2FinalizedHeadJSON, _ := json.Marshal(s.l2Finalized) + l1WindowBufJSON, _ := json.Marshal(s.l1WindowBuf) + + s.snapshotLog.Info("Rollup State Snapshot", + "event", event, + "l1Head", string(l1HeadJSON), + "l2Head", string(l2HeadJSON), + "l2SafeHead", string(l2SafeHeadJSON), + "l2FinalizedHead", string(l2FinalizedHeadJSON), + "l1WindowBuf", string(l1WindowBufJSON)) +} diff --git a/opnode/rollup/driver/state_test.go b/opnode/rollup/driver/state_test.go index f7527d242621..edc4c745ccf1 100644 --- a/opnode/rollup/driver/state_test.go +++ b/opnode/rollup/driver/state_test.go @@ -151,7 +151,7 @@ func (tc *stateTestCase) Run(t *testing.T) { return r.l2Head, r.l2Head, false, r.err } config := rollup.Config{SeqWindowSize: uint64(tc.seqWindow), Genesis: tc.genesis, BlockTime: 2} - state := NewState(log, config, chainSource, chainSource, outputHandlerFn(outputHandler), nil, false) + state := NewState(log, log, config, chainSource, chainSource, outputHandlerFn(outputHandler), nil, false) defer func() { assert.NoError(t, state.Close(), "Error closing state") }() diff --git a/opnode/service.go b/opnode/service.go index 9459d36e7542..bfe74f27bb7d 100644 --- a/opnode/service.go +++ b/opnode/service.go @@ -5,6 +5,8 @@ import ( "fmt" "os" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimistic-specs/opnode/flags" "github.com/ethereum-optimism/optimistic-specs/opnode/node" "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" @@ -80,3 +82,19 @@ func NewLogConfig(ctx *cli.Context) (node.LogConfig, error) { } return cfg, nil } + +func NewSnapshotLogger(ctx *cli.Context) (log.Logger, error) { + snapshotFile := ctx.GlobalString(flags.SnapshotLog.Name) + handler := log.DiscardHandler() + if snapshotFile != "" { + var err error + handler, err = log.FileHandler(snapshotFile, log.JSONFormat()) + if err != nil { + return nil, err + } + } + handler = log.SyncHandler(handler) + logger := log.New() + logger.SetHandler(handler) + return logger, nil +} diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 88b58aa4815f..467d687706b9 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -471,7 +471,7 @@ func (cfg SystemConfig) start() (*System, error) { } } - node, err := rollupNode.New(context.Background(), &c, cfg.Loggers[name], "") + node, err := rollupNode.New(context.Background(), &c, cfg.Loggers[name], cfg.Loggers[name], "") if err != nil { didErrAfterStart = true return nil, err diff --git a/ops/Dockerfile.stateviz b/ops/Dockerfile.stateviz new file mode 100644 index 000000000000..009a25b2bc20 --- /dev/null +++ b/ops/Dockerfile.stateviz @@ -0,0 +1,19 @@ +FROM golang:1.18.0-alpine3.15 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 -x + +COPY ./opnode /app/opnode + +RUN go build -o ./bin/stateviz ./opnode/cmd/stateviz + +FROM alpine:3.15 + +COPY --from=builder /app/bin/stateviz /usr/local/bin + +CMD ["stateviz"] diff --git a/ops/devnet-up.sh b/ops/devnet-up.sh index 5d83c9b7273b..9b3886443bf9 100755 --- a/ops/devnet-up.sh +++ b/ops/devnet-up.sh @@ -160,6 +160,10 @@ L2OO_ADDRESS="$L2OO_ADDRESS" \ SEQUENCER_GENESIS_HASH="$SEQUENCER_GENESIS_HASH" \ SEQUENCER_BATCH_INBOX_ADDRESS="$SEQUENCER_BATCH_INBOX_ADDRESS" \ docker-compose up -d l2os bss + +echo "Bringin up stateviz webserver..." +docker-compose up -d stateviz + cd ../ echo "Devnet ready." diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index ba8069bae979..dee41081873b 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -7,6 +7,8 @@ version: '3.4' volumes: l1_data: l2_data: + op_log: + services: l1: @@ -49,14 +51,16 @@ services: --p2p.listen.ip=0.0.0.0 --p2p.listen.tcp=9003 --p2p.listen.udp=9003 + --snapshotlog.file=/op_log/snapshot.log --p2p.priv.path=/config/p2p-node-key.txt ports: - - "7545:8545" - - "9003:9003" + - "7545:8545" + - "9003:9003" volumes: - ${PWD}/p2p-sequencer-key.txt:/config/p2p-sequencer-key.txt - ${PWD}/p2p-node-key.txt:/config/p2p-node-key.txt - ${PWD}/../.devnet/rollup.json:/rollup.json + - op_log:/op_log l2os: depends_on: @@ -103,3 +107,17 @@ services: BATCH_SUBMITTER_SEQUENCER_GENESIS_HASH: "${SEQUENCER_GENESIS_HASH}" BATCH_SUBMITTER_SEQUENCER_BATCH_INBOX_ADDRESS: "${SEQUENCER_BATCH_INBOX_ADDRESS}" BATCH_SUBMITTER_LOG_TERMINAL: "true" + + stateviz: + build: + context: ../ + dockerfile: ./ops/Dockerfile.stateviz + command: + - stateviz + - -addr=0.0.0.0:8080 + - -snapshot=/op_log/snapshot.log + - -refresh=10s + ports: + - "9090:8080" + volumes: + - op_log:/op_log:ro From e34ed09f83732afd2ea38fe0eee51c962dc4c906 Mon Sep 17 00:00:00 2001 From: Kelvin Fichter Date: Wed, 11 May 2022 18:47:25 -0400 Subject: [PATCH 565/585] contracts: add backup logic for deposits Introduces backup logic for deposits that prevents users from accidentally making bad deposits. Deposits that don't complete successfully will be returned back to the layer where the deposits were made. --- packages/contracts/.gas-snapshot | 28 ++--- .../contracts/L2/L2StandardBridge.sol | 49 +------- .../contracts/universal/StandardBridge.sol | 119 +++++++++++++++--- 3 files changed, 120 insertions(+), 76 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index efc7704651ef..7733691815e0 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -14,19 +14,19 @@ L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 74867) L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 66341) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 10565) L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 58335) -L1StandardBridge_Test:test_depositERC20() (gas: 373162) -L1StandardBridge_Test:test_depositERC20To() (gas: 374939) -L1StandardBridge_Test:test_depositETH() (gas: 106067) -L1StandardBridge_Test:test_depositETHTo() (gas: 112908) -L1StandardBridge_Test:test_donateETH() (gas: 17500) -L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 438858) -L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 47952) +L1StandardBridge_Test:test_depositERC20() (gas: 372347) +L1StandardBridge_Test:test_depositERC20To() (gas: 374124) +L1StandardBridge_Test:test_depositETH() (gas: 106059) +L1StandardBridge_Test:test_depositETHTo() (gas: 112878) +L1StandardBridge_Test:test_donateETH() (gas: 17523) +L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 438817) +L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 47983) L1StandardBridge_Test:test_initialize() (gas: 14863) L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 12085) L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 30637) -L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 23521) -L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 22853) -L1StandardBridge_Test:test_receive() (gas: 100261) +L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 23565) +L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 22897) +L1StandardBridge_Test:test_receive() (gas: 100257) L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10865) L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8387) L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31792) @@ -52,11 +52,11 @@ L2OutputOracleTest:test_deleteL2Output() (gas: 64320) L2OutputOracleTest:test_getL2Output() (gas: 74601) L2OutputOracleTest:test_latestBlockTimestamp() (gas: 68377) L2OutputOracleTest:test_nextTimestamp() (gas: 9236) -L2StandardBridge_Test:test_finalizeDeposit() (gas: 97520) +L2StandardBridge_Test:test_finalizeDeposit() (gas: 93169) L2StandardBridge_Test:test_initialize() (gas: 14812) -L2StandardBridge_Test:test_receive() (gas: 137222) -L2StandardBridge_Test:test_withdraw() (gas: 353410) -L2StandardBridge_Test:test_withdrawTo() (gas: 354225) +L2StandardBridge_Test:test_receive() (gas: 137218) +L2StandardBridge_Test:test_withdraw() (gas: 353494) +L2StandardBridge_Test:test_withdrawTo() (gas: 354363) L2ToL1MessagePasserTest:test_burn() (gas: 112001) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67935) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74851) diff --git a/packages/contracts/contracts/L2/L2StandardBridge.sol b/packages/contracts/contracts/L2/L2StandardBridge.sol index 578a9c981969..000234606ecc 100644 --- a/packages/contracts/contracts/L2/L2StandardBridge.sol +++ b/packages/contracts/contracts/L2/L2StandardBridge.sol @@ -109,53 +109,12 @@ contract L2StandardBridge is StandardBridge { uint256 _amount, bytes calldata _data ) external payable virtual { - // Check to see if the bridge is being used to deposit ETH. - // The `msg.value` must match the `_amount` to prevent - // ETH from getting stuck in the contract - if ( - _l1Token == address(0) && - _l2Token == Lib_PredeployAddresses.OVM_ETH && - msg.value == _amount - ) { - // An ETH deposit is being made via the Token Bridge. - // We simply forward it on. If this call fails, ETH will be stuck, but the L1Bridge - // uses onlyEOA on the receive function, so anyone sending to a contract knows - // what they are doing. + if (_l1Token == address(0) && _l2Token == Lib_PredeployAddresses.OVM_ETH) { finalizeBridgeETH(_from, _to, _amount, _data); - emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); - } else if ( - _isOptimismMintable(_l2Token, _l1Token) - ) // Check the target token is compliant and - // verify the deposited token on L1 matches the L2 deposited token representation here - // slither-disable-next-line reentrancy-events - { - // When a deposit is finalized, we credit the account on L2 with the same amount of - // tokens. - // slither-disable-next-line reentrancy-events - finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _data); - // slither-disable-next-line reentrancy-events - emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); } else { - // Either the L2 token which is being deposited-into disagrees about the correct address - // of its L1 token, or does not support the correct interface. - // This should only happen if there is a malicious L2 token, or if a user somehow - // specified the wrong L2 token address to deposit into. - // In either case, we stop the process here and construct a withdrawal - // message so that users can get their funds out in some cases. - // There is no way to prevent malicious token contracts altogether, but this does limit - // user error and mitigate some forms of malicious contract behavior. - emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data); - - // Withdraw ETH in the case that the user submitted a bad ETH - // deposit to prevent ETH from getting stuck - // TODO: can this be wrapped into _initiateWithdrawal? - // need to handle using `msg.value` here instead of `_value` - if (_l2Token == Lib_PredeployAddresses.OVM_ETH) { - _initiateBridgeETH(_from, _to, msg.value, 0, _data); - } else { - _initiateBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, 0, _data); - } + finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _data); } + emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); } /********************** @@ -176,11 +135,11 @@ contract L2StandardBridge is StandardBridge { bytes calldata _data ) internal { address l1Token = OptimismMintableERC20(_l2Token).l1Token(); - emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data); if (_l2Token == Lib_PredeployAddresses.OVM_ETH) { _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _data); } else { _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _data); } + emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data); } } diff --git a/packages/contracts/contracts/universal/StandardBridge.sol b/packages/contracts/contracts/universal/StandardBridge.sol index e6e37483558b..8b901f6c3753 100644 --- a/packages/contracts/contracts/universal/StandardBridge.sol +++ b/packages/contracts/contracts/universal/StandardBridge.sol @@ -58,6 +58,15 @@ abstract contract StandardBridge { bytes _data ); + event ERC20BridgeFailed( + address indexed _localToken, + address indexed _remoteToken, + address indexed _from, + address _to, + uint256 _amount, + bytes _data + ); + /************* * Variables * *************/ @@ -100,6 +109,11 @@ abstract contract StandardBridge { _; } + modifier onlySelf() { + require(msg.sender == address(this), "Function can only be called by self."); + _; + } + /******************** * Public Functions * ********************/ @@ -188,6 +202,7 @@ abstract contract StandardBridge { bytes calldata _data ) public payable onlyOtherBridge { require(msg.value == _amount, "Amount sent does not match amount required."); + require(_to != address(this), "Cannot send to self."); emit ETHBridgeFinalized(_from, _to, _amount, _data); (bool success, ) = _to.call{ value: _amount }(new bytes(0)); @@ -205,14 +220,45 @@ abstract contract StandardBridge { uint256 _amount, bytes calldata _data ) public onlyOtherBridge { - if (_isOptimismMintable(_localToken, _remoteToken)) { + try this.completeOutboundTransfer(_localToken, _remoteToken, _to, _amount) { + emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _data); + } catch { + // Something went wrong during the bridging process, return to sender. + // Can happen if a bridge UI specifies the wrong L2 token. + _initiateBridgeERC20Unchecked( + _remoteToken, + _localToken, + _from, + _to, + _amount, + 0, // _minGasLimit, 0 is fine here + _data + ); + emit ERC20BridgeFailed(_localToken, _remoteToken, _from, _to, _amount, _data); + } + } + + function completeOutboundTransfer( + address _localToken, + address _remoteToken, + address _to, + uint256 _amount + ) public onlySelf { + // Make sure external function calls can't be used to trigger calls to + // completeOutboundTransfer. We only make external (write) calls to _localToken. + require(_localToken != address(this), "Local token cannot be self"); + + if (_isOptimismMintableERC20(_localToken)) { + require( + _isCorrectTokenPair(_localToken, _remoteToken), + "Wrong remote token for Optimism Mintable ERC20 local token" + ); + OptimismMintableERC20(_localToken).mint(_to, _amount); } else { deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount; IERC20(_localToken).safeTransfer(_to, _amount); } - - emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _data); } /********************** @@ -262,13 +308,46 @@ abstract contract StandardBridge { uint32 _minGasLimit, bytes calldata _data ) internal { - if (_isOptimismMintable(_localToken, _remoteToken)) { + // Make sure external function calls can't be used to trigger calls to + // completeOutboundTransfer. We only make external (write) calls to _localToken. + require(_localToken != address(this), "Local token cannot be self"); + + if (_isOptimismMintableERC20(_localToken)) { + require( + _isCorrectTokenPair(_localToken, _remoteToken), + "Wrong remote token for Optimism Mintable ERC20 local token" + ); + OptimismMintableERC20(_localToken).burn(msg.sender, _amount); } else { + // TODO: Do we need to confirm that the transfer was successful? IERC20(_localToken).safeTransferFrom(_from, address(this), _amount); deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount; } + _initiateBridgeERC20Unchecked( + _localToken, + _remoteToken, + _from, + _to, + _amount, + _minGasLimit, + _data + ); + } + + /** + * @notice Bridge an ERC20 to the remote chain through the messengers + */ + function _initiateBridgeERC20Unchecked( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _data + ) internal { messenger.sendMessage( address(otherBridge), abi.encodeWithSelector( @@ -287,23 +366,29 @@ abstract contract StandardBridge { } /** - * @notice Check to make sure that the token pair is an OptimismMintable - * token pair. - * The selector 0x1d1d8b63 represents the ERC165 representation of - * the methods l1Token(), mint(address,uint256), burn(address,uint256) - * the selector 0x0bc32271 represents the ERC165 representation of - * remoteToken(), mint(address,uint256), burn(address,uint256). - * Both are required as l1Token() is a legacy function, prefer calling - * remoteToken() + * Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough. + * Just the way we like it. + * + * @param _token Address of the token to check. + * @return True if the token is an OptimismMintableERC20. + */ + function _isOptimismMintableERC20(address _token) internal view returns (bool) { + // 0x1d1d8b63 is mint ^ burn ^ l1Token + return ERC165Checker.supportsInterface(_token, 0x1d1d8b63); + } + + /** + * Checks if the "other token" is the correct pair token for the OptimismMintableERC20. + * + * @param _mintableToken OptimismMintableERC20 to check against. + * @param _otherToken Pair token to check. + * @return True if the other token is the correct pair token for the OptimismMintableERC20. */ - function _isOptimismMintable(address _localToken, address _remoteToken) + function _isCorrectTokenPair(address _mintableToken, address _otherToken) internal view returns (bool) { - return ((ERC165Checker.supportsInterface(_localToken, 0x1d1d8b63) && - _remoteToken == OptimismMintableERC20(_localToken).l1Token()) || - (ERC165Checker.supportsInterface(_localToken, 0x0bc32271) && - _remoteToken == OptimismMintableERC20(_localToken).remoteToken())); + return _otherToken == OptimismMintableERC20(_mintableToken).l1Token(); } } From 689400b775417be301584076c3ca46099adf9f4c Mon Sep 17 00:00:00 2001 From: Kelvin Fichter Date: Thu, 12 May 2022 13:34:07 -0400 Subject: [PATCH 566/585] contracts: add base gas to sent messages Introduces base gas to the CrossDomainMessenger's sendMessage function. Base gas is used to guarantee that all messages sent between messengers will at the very least be able to store the message hash on the other chain and therefore be replayable. Base gas scales dynamically with the size of the message. --- packages/contracts/.gas-snapshot | 20 +++++-------- .../test/L1CrossDomainMessenger.t.sol | 4 +-- .../test/L2CrossDomainMessenger.t.sol | 4 +-- .../universal/CrossDomainMessenger.sol | 28 +++++++++++++++++-- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 7733691815e0..964846c6d7dd 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -5,9 +5,9 @@ L1BLockTest:test_number() (gas: 7651) L1BLockTest:test_sequenceNumber() (gas: 7585) L1BLockTest:test_timestamp() (gas: 7661) L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 10909) -L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 8343) +L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 8366) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 31882) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 61062) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 61085) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 44727) L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 41564) L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 74867) @@ -32,11 +32,11 @@ L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8387) L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31792) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57407) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 24523) -L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41511) -L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 116411) -L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133114) -L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10587) -L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54749) +L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41555) +L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 120162) +L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133928) +L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10588) +L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54751) L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 18627) L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 16734) L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 18708) @@ -54,15 +54,9 @@ L2OutputOracleTest:test_latestBlockTimestamp() (gas: 68377) L2OutputOracleTest:test_nextTimestamp() (gas: 9236) L2StandardBridge_Test:test_finalizeDeposit() (gas: 93169) L2StandardBridge_Test:test_initialize() (gas: 14812) -L2StandardBridge_Test:test_receive() (gas: 137218) -L2StandardBridge_Test:test_withdraw() (gas: 353494) -L2StandardBridge_Test:test_withdrawTo() (gas: 354363) -L2ToL1MessagePasserTest:test_burn() (gas: 112001) -L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67935) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74851) OptimismMintableTokenFactory_Test:test_bridge() (gas: 9850) OptimismMintableTokenFactory_Test:test_burn() (gas: 52791) -OptimismMintableTokenFactory_Test:test_burnRevertsFromNotBridge() (gas: 13211) OptimismMintableTokenFactory_Test:test_l1Token() (gas: 9779) OptimismMintableTokenFactory_Test:test_l2Bridge() (gas: 9768) OptimismMintableTokenFactory_Test:test_mint() (gas: 65732) diff --git a/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol b/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol index b3eaf07f48e5..1fcb5bcb193c 100644 --- a/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol +++ b/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol @@ -73,7 +73,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { OptimismPortal.depositTransaction.selector, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, 0, - 100, + 100 + L1Messenger.baseGas(hex"ff"), false, CrossDomainHashing.getVersionedEncoding( L1Messenger.messageNonce(), @@ -93,7 +93,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, 0, 0, - 100, + 100 + L1Messenger.baseGas(hex"ff"), false, CrossDomainHashing.getVersionedEncoding( L1Messenger.messageNonce(), diff --git a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol index 2c427b71e99e..be3900099d5e 100644 --- a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol +++ b/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol @@ -56,7 +56,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { abi.encodeWithSelector( L2ToL1MessagePasser.initiateWithdrawal.selector, address(L1Messenger), - 100, + 100 + L2Messenger.baseGas(hex"ff"), CrossDomainHashing.getVersionedEncoding( L2Messenger.messageNonce(), alice, @@ -75,7 +75,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { address(L2Messenger), address(L1Messenger), 0, - 100, + 100 + L2Messenger.baseGas(hex"ff"), CrossDomainHashing.getVersionedEncoding( L2Messenger.messageNonce(), alice, diff --git a/packages/contracts/contracts/universal/CrossDomainMessenger.sol b/packages/contracts/contracts/universal/CrossDomainMessenger.sol index 8414145bc4e5..a96ee5b31caa 100644 --- a/packages/contracts/contracts/universal/CrossDomainMessenger.sol +++ b/packages/contracts/contracts/universal/CrossDomainMessenger.sol @@ -54,6 +54,10 @@ abstract contract CrossDomainMessenger is uint16 public constant MESSAGE_VERSION = 1; + uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD = 1; + + uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 100000; + /************* * Variables * *************/ @@ -119,6 +123,22 @@ abstract contract CrossDomainMessenger is return CrossDomainHashing.addVersionToNonce(msgNonce, MESSAGE_VERSION); } + /** + * Base amount of gas required to make sure that the message will be received without + * running out of gas. Amount of gas provided to the L2 call will be the gas requested by + * the user PLUS this gas value so that if the message is not successful, it can always be + * replayed on the other end. + * + * @param _message Message to compute base gas for. + * @return Base gas required for message. + */ + function baseGas(bytes memory _message) public pure returns (uint32) { + // TODO: Values here are meant to be good enough to get a devnet running. We need to do + // some simple experimentation with the smallest and largest possible message sizes to find + // the correct constant and dynamic overhead values. + return (uint32(_message.length) * MIN_GAS_DYNAMIC_OVERHEAD) + MIN_GAS_CONSTANT_OVERHEAD; + } + /** * @param _target Target contract address. * @param _message Message to send to the target. @@ -129,11 +149,13 @@ abstract contract CrossDomainMessenger is bytes memory _message, uint32 _minGasLimit ) external payable { - // TODO: Enforce minimum gas limit. - + // Triggers a message to the other messenger. Note that the amount of gas provided to the + // message is the amount of gas requested by the user PLUS the base gas value. We want to + // guarantee the property that the call to the target contract will always have at least + // the minimum gas limit specified by the user. _sendMessage( otherMessenger, - _minGasLimit, // TODO: Pad this value. + _minGasLimit + baseGas(_message), msg.value, CrossDomainHashing.getVersionedEncoding( messageNonce(), From 610a27466d41d71532a6fc805cd9f6f6c259bb90 Mon Sep 17 00:00:00 2001 From: Kelvin Fichter Date: Thu, 12 May 2022 13:40:42 -0400 Subject: [PATCH 567/585] contracts: use clearer message encoding Uses the clearer abi.encodeWithSelector within CrossDomainMessenger's sendMessage function. Doing this makes it much more apparent that a call to the relayMessage function is being triggered. --- packages/contracts/.gas-snapshot | 2 +- .../contracts/contracts/universal/CrossDomainMessenger.sol | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 964846c6d7dd..14353c9ce340 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -36,7 +36,7 @@ L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41 L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 120162) L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133928) L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10588) -L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54751) +L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54795) L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 18627) L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 16734) L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 18708) diff --git a/packages/contracts/contracts/universal/CrossDomainMessenger.sol b/packages/contracts/contracts/universal/CrossDomainMessenger.sol index a96ee5b31caa..e1dfe0a8d1b5 100644 --- a/packages/contracts/contracts/universal/CrossDomainMessenger.sol +++ b/packages/contracts/contracts/universal/CrossDomainMessenger.sol @@ -146,7 +146,7 @@ abstract contract CrossDomainMessenger is */ function sendMessage( address _target, - bytes memory _message, + bytes calldata _message, uint32 _minGasLimit ) external payable { // Triggers a message to the other messenger. Note that the amount of gas provided to the @@ -157,7 +157,8 @@ abstract contract CrossDomainMessenger is otherMessenger, _minGasLimit + baseGas(_message), msg.value, - CrossDomainHashing.getVersionedEncoding( + abi.encodeWithSelector( + this.relayMessage.selector, messageNonce(), msg.sender, _target, From 95857d4f2303bcd9dc4fb36f907d2fb8840f9127 Mon Sep 17 00:00:00 2001 From: Kelvin Fichter Date: Thu, 12 May 2022 16:17:05 -0400 Subject: [PATCH 568/585] contracts: add L1BlockNumber predeploy Re-introduces the L1BlockNumber predeployed contract for backwards compatibility with the previous OVM_L1BlockNumber contract. --- packages/contracts/.gas-snapshot | 59 +++++++++++-------- .../contracts/contracts/L2/L1BlockNumber.sol | 35 +++++++++++ .../contracts/contracts/test/L1Block.t.sol | 2 +- .../contracts/test/L1BlockNumber.t.sol | 36 +++++++++++ 4 files changed, 106 insertions(+), 26 deletions(-) create mode 100644 packages/contracts/contracts/L2/L1BlockNumber.sol create mode 100644 packages/contracts/contracts/test/L1BlockNumber.t.sol diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 14353c9ce340..a8e7449da38a 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,23 +1,26 @@ CrossDomainHashing_Test:test_l2TransactionHash() (gas: 78639) -L1BLockTest:test_basefee() (gas: 7575) -L1BLockTest:test_hash() (gas: 7552) -L1BLockTest:test_number() (gas: 7651) -L1BLockTest:test_sequenceNumber() (gas: 7585) -L1BLockTest:test_timestamp() (gas: 7661) +L1BlockTest:test_basefee() (gas: 7575) +L1BlockTest:test_hash() (gas: 7552) +L1BlockTest:test_number() (gas: 7651) +L1BlockTest:test_sequenceNumber() (gas: 7585) +L1BlockTest:test_timestamp() (gas: 7661) +L1BlockNumberTest:test_fallback() (gas: 10710) +L1BlockNumberTest:test_getL1BlockNumber() (gas: 10589) +L1BlockNumberTest:test_receive() (gas: 17440) L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 10909) L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 8366) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 31882) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 61085) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 44727) -L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 41564) -L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 74867) -L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 66341) -L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 10565) -L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 58335) -L1StandardBridge_Test:test_depositERC20() (gas: 372347) -L1StandardBridge_Test:test_depositERC20To() (gas: 374124) -L1StandardBridge_Test:test_depositETH() (gas: 106059) -L1StandardBridge_Test:test_depositETHTo() (gas: 112878) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 61129) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 44815) +L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 41631) +L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 78105) +L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 66345) +L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 10588) +L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 58425) +L1StandardBridge_Test:test_depositERC20() (gas: 371479) +L1StandardBridge_Test:test_depositERC20To() (gas: 373256) +L1StandardBridge_Test:test_depositETH() (gas: 105126) +L1StandardBridge_Test:test_depositETHTo() (gas: 111945) L1StandardBridge_Test:test_donateETH() (gas: 17523) L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 438817) L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 47983) @@ -26,15 +29,15 @@ L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 12085) L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 30637) L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 23565) L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 22897) -L1StandardBridge_Test:test_receive() (gas: 100257) -L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10865) -L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8387) -L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31792) -L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57407) -L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 24523) -L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41555) -L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 120162) -L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133928) +L1StandardBridge_Test:test_receive() (gas: 99476) +L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10843) +L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8410) +L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31837) +L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57429) +L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 24567) +L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41599) +L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 119681) +L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133118) L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10588) L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54795) L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 18627) @@ -54,9 +57,15 @@ L2OutputOracleTest:test_latestBlockTimestamp() (gas: 68377) L2OutputOracleTest:test_nextTimestamp() (gas: 9236) L2StandardBridge_Test:test_finalizeDeposit() (gas: 93169) L2StandardBridge_Test:test_initialize() (gas: 14812) +L2StandardBridge_Test:test_receive() (gas: 136437) +L2StandardBridge_Test:test_withdraw() (gas: 352626) +L2StandardBridge_Test:test_withdrawTo() (gas: 353495) +L2ToL1MessagePasserTest:test_burn() (gas: 112001) +L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67935) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74851) OptimismMintableTokenFactory_Test:test_bridge() (gas: 9850) OptimismMintableTokenFactory_Test:test_burn() (gas: 52791) +OptimismMintableTokenFactory_Test:test_burnRevertsFromNotBridge() (gas: 13211) OptimismMintableTokenFactory_Test:test_l1Token() (gas: 9779) OptimismMintableTokenFactory_Test:test_l2Bridge() (gas: 9768) OptimismMintableTokenFactory_Test:test_mint() (gas: 65732) diff --git a/packages/contracts/contracts/L2/L1BlockNumber.sol b/packages/contracts/contracts/L2/L1BlockNumber.sol new file mode 100644 index 000000000000..a6e396d50dfc --- /dev/null +++ b/packages/contracts/contracts/L2/L1BlockNumber.sol @@ -0,0 +1,35 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { L1Block } from "./L1Block.sol"; +import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; + +/** + * @title L1BlockNumber + * @dev L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract in + * the old version of the Optimism system. Only necessary for backwards compatibility. If you want + * to access the L1 block number going forward, you should use the L1Block contract instead. + * + * ADDRESS: 0x4200000000000000000000000000000000000013 + */ +contract L1BlockNumber { + receive() external payable { + uint256 l1BlockNumber = getL1BlockNumber(); + assembly { + mstore(0, l1BlockNumber) + return(0, 32) + } + } + + fallback() external payable { + uint256 l1BlockNumber = getL1BlockNumber(); + assembly { + mstore(0, l1BlockNumber) + return(0, 32) + } + } + + function getL1BlockNumber() public view returns (uint256) { + return L1Block(Lib_BedrockPredeployAddresses.L1_BLOCK_ATTRIBUTES).number(); + } +} diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts/contracts/test/L1Block.t.sol index 12278001dded..d3bd8cbd6860 100644 --- a/packages/contracts/contracts/test/L1Block.t.sol +++ b/packages/contracts/contracts/test/L1Block.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.10; import { CommonTest } from "./CommonTest.t.sol"; import { L1Block } from "../L2/L1Block.sol"; -contract L1BLockTest is CommonTest { +contract L1BlockTest is CommonTest { L1Block lb; address depositor; bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1)); diff --git a/packages/contracts/contracts/test/L1BlockNumber.t.sol b/packages/contracts/contracts/test/L1BlockNumber.t.sol new file mode 100644 index 000000000000..4e74234e7177 --- /dev/null +++ b/packages/contracts/contracts/test/L1BlockNumber.t.sol @@ -0,0 +1,36 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import { Test } from "forge-std/Test.sol"; +import { L1Block } from "../L2/L1Block.sol"; +import { L1BlockNumber } from "../L2/L1BlockNumber.sol"; +import { Lib_BedrockPredeployAddresses } from "../libraries/Lib_BedrockPredeployAddresses.sol"; + +contract L1BlockNumberTest is Test { + L1Block lb; + L1BlockNumber bn; + + function setUp() external { + vm.etch(Lib_BedrockPredeployAddresses.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code); + lb = L1Block(Lib_BedrockPredeployAddresses.L1_BLOCK_ATTRIBUTES); + bn = new L1BlockNumber(); + vm.prank(lb.DEPOSITOR_ACCOUNT()); + lb.setL1BlockValues(uint64(999), uint64(2), 3, keccak256(abi.encode(1)), uint64(4)); + } + + function test_getL1BlockNumber() external { + assertEq(bn.getL1BlockNumber(), 999); + } + + function test_fallback() external { + (bool success, bytes memory ret) = address(bn).call(hex""); + assertEq(success, true); + assertEq(ret, abi.encode(999)); + } + + function test_receive() external { + (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex""); + assertEq(success, true); + assertEq(ret, abi.encode(999)); + } +} From e5c87e6da82cb9744fba9dcc506407e2ea2bb98c Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 13 May 2022 00:54:39 +0200 Subject: [PATCH 569/585] opnode: p2p rpc client bindings, test update, minor p2p flag update --- opnode/flags/p2p_flags.go | 2 +- opnode/node/server.go | 6 +- opnode/p2p/rpc_api.go | 61 ++++++++++++++++ opnode/p2p/rpc_client.go | 103 +++++++++++++++++++++++++++ opnode/p2p/{api.go => rpc_server.go} | 92 +++++++++++------------- opnode/test/system_test.go | 28 ++++++-- 6 files changed, 231 insertions(+), 61 deletions(-) create mode 100644 opnode/p2p/rpc_api.go create mode 100644 opnode/p2p/rpc_client.go rename opnode/p2p/{api.go => rpc_server.go} (70%) diff --git a/opnode/flags/p2p_flags.go b/opnode/flags/p2p_flags.go index 3101fecd398a..2bf1c9083cba 100644 --- a/opnode/flags/p2p_flags.go +++ b/opnode/flags/p2p_flags.go @@ -147,7 +147,7 @@ var ( Usage: "User-agent string to share via LibP2P identify. If empty it defaults to 'optimism-VERSIONHERE'.", Hidden: true, Required: false, - Value: "", + Value: "optimism", EnvVar: p2pEnv("AGENT"), } TimeoutNegotiation = cli.DurationFlag{ diff --git a/opnode/node/server.go b/opnode/node/server.go index 97eda1155ded..2bf47312cbca 100644 --- a/opnode/node/server.go +++ b/opnode/node/server.go @@ -49,10 +49,10 @@ func newRPCServer(ctx context.Context, rpcCfg *RPCConfig, rollupCfg *rollup.Conf func (s *rpcServer) EnableP2P(backend *p2p.APIBackend) { s.apis = append(s.apis, rpc.API{ - Namespace: "", + Namespace: p2p.NamespaceRPC, Version: "", - Service: nil, - Public: false, + Service: backend, + Public: true, Authenticated: false, }) } diff --git a/opnode/p2p/rpc_api.go b/opnode/p2p/rpc_api.go new file mode 100644 index 000000000000..01f0573c9ede --- /dev/null +++ b/opnode/p2p/rpc_api.go @@ -0,0 +1,61 @@ +package p2p + +import ( + "context" + "net" + "time" + + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + ma "github.com/multiformats/go-multiaddr" +) + +type PeerInfo struct { + PeerID peer.ID `json:"peerID"` + NodeID enode.ID `json:"nodeID"` + UserAgent string `json:"userAgent"` + ProtocolVersion string `json:"protocolVersion"` + ENR string `json:"ENR"` // might not always be known, e.g. if the peer connected us instead of us discovering them + Addresses []string `json:"addresses"` // multi-addresses. may be mix of LAN / docker / external IPs. All of them are communicated. + Protocols []string `json:"protocols"` // negotiated protocols list + //GossipScore float64 + //PeerScore float64 + Connectedness network.Connectedness `json:"connectedness"` // "NotConnected", "Connected", "CanConnect" (gracefully disconnected), or "CannotConnect" (tried but failed) + Direction network.Direction `json:"direction"` // "Unknown", "Inbound" (if the peer contacted us), "Outbound" (if we connected to them) + BannedID bool `json:"bannedID"` // If the peer has been banned by peer ID + BannedIP bool `json:"bannedIP"` // If the peer has been banned by IP address + BannedSubnet bool `json:"bannedSubnet"` // If the peer has been banned as part of a whole IP subnet + Protected bool `json:"protected"` // Protected peers do not get + ChainID uint64 `json:"chainID"` // some peers might try to connect, but we figure out they are on a different chain later. This may be 0 if the peer is not an optimism node at all. + Latency time.Duration `json:"latency"` + + GossipBlocks bool `json:"gossipBlocks"` // if the peer is in our gossip topic +} + +type PeerDump struct { + TotalConnected uint `json:"totalConnected"` + Peers map[string]*PeerInfo `json:"peers"` + BannedPeers []peer.ID `json:"bannedPeers"` + BannedIPS []net.IP `json:"bannedIPS"` + BannedSubnets []*net.IPNet `json:"bannedSubnets"` +} + +type API interface { + Peers(ctx context.Context, connected bool) (*PeerDump, error) + PeerStats(ctx context.Context) (*PeerStats, error) + DiscoveryTable(ctx context.Context) ([]*enode.Node, error) + BlockPeer(ctx context.Context, p peer.ID) error + UnblockPeer(ctx context.Context, p peer.ID) error + ListBlockedPeers(ctx context.Context) ([]peer.ID, error) + BlockAddr(ctx context.Context, ip net.IP) error + UnblockAddr(ctx context.Context, ip net.IP) error + ListBlockedAddrs(ctx context.Context) ([]net.IP, error) + BlockSubnet(ctx context.Context, ipnet *net.IPNet) error + UnblockSubnet(ctx context.Context, ipnet *net.IPNet) error + ListBlockedSubnets(ctx context.Context) ([]*net.IPNet, error) + ProtectPeer(ctx context.Context, p peer.ID) error + UnprotectPeer(ctx context.Context, p peer.ID) error + ConnectPeer(ctx context.Context, addr ma.Multiaddr) error + DisconnectPeer(ctx context.Context, id peer.ID) error +} diff --git a/opnode/p2p/rpc_client.go b/opnode/p2p/rpc_client.go new file mode 100644 index 000000000000..de086ca6e4ec --- /dev/null +++ b/opnode/p2p/rpc_client.go @@ -0,0 +1,103 @@ +package p2p + +import ( + "context" + "net" + + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/rpc" + "github.com/libp2p/go-libp2p-core/peer" + ma "github.com/multiformats/go-multiaddr" +) + +var NamespaceRPC = "opp2p" + +type Client struct { + c *rpc.Client +} + +var _ API = (*Client)(nil) + +func NewClient(c *rpc.Client) *Client { + return &Client{c: c} +} + +func prefixRPC(method string) string { + return NamespaceRPC + "_" + method +} + +func (c *Client) Peers(ctx context.Context, connected bool) (*PeerDump, error) { + var out *PeerDump + err := c.c.CallContext(ctx, &out, prefixRPC("peers"), connected) + return out, err +} + +func (c *Client) PeerStats(ctx context.Context) (*PeerStats, error) { + var out *PeerStats + err := c.c.CallContext(ctx, &out, prefixRPC("peerStats")) + return out, err +} + +func (c *Client) DiscoveryTable(ctx context.Context) ([]*enode.Node, error) { + var out []*enode.Node + err := c.c.CallContext(ctx, &out, prefixRPC("discoveryTable")) + return out, err +} + +func (c *Client) BlockPeer(ctx context.Context, p peer.ID) error { + return c.c.CallContext(ctx, nil, prefixRPC("blockPeer"), p) +} + +func (c *Client) UnblockPeer(ctx context.Context, p peer.ID) error { + return c.c.CallContext(ctx, nil, prefixRPC("unblockPeer"), p) +} + +func (c *Client) ListBlockedPeers(ctx context.Context) ([]peer.ID, error) { + var out []peer.ID + err := c.c.CallContext(ctx, &out, prefixRPC("listBlockedPeers")) + return out, err +} + +func (c *Client) BlockAddr(ctx context.Context, ip net.IP) error { + return c.c.CallContext(ctx, nil, prefixRPC("blockAddr"), ip) +} + +func (c *Client) UnblockAddr(ctx context.Context, ip net.IP) error { + return c.c.CallContext(ctx, nil, prefixRPC("unblockAddr"), ip) +} + +func (c *Client) ListBlockedAddrs(ctx context.Context) ([]net.IP, error) { + var out []net.IP + err := c.c.CallContext(ctx, &out, prefixRPC("listBlockedAddrs")) + return out, err +} + +func (c *Client) BlockSubnet(ctx context.Context, ipnet *net.IPNet) error { + return c.c.CallContext(ctx, nil, prefixRPC("blockSubnet"), ipnet) +} + +func (c *Client) UnblockSubnet(ctx context.Context, ipnet *net.IPNet) error { + return c.c.CallContext(ctx, nil, prefixRPC("unblockSubnet"), ipnet) +} + +func (c *Client) ListBlockedSubnets(ctx context.Context) ([]*net.IPNet, error) { + var out []*net.IPNet + err := c.c.CallContext(ctx, &out, prefixRPC("listBlockedSubnets")) + return out, err +} + +func (c *Client) ProtectPeer(ctx context.Context, p peer.ID) error { + return c.c.CallContext(ctx, nil, prefixRPC("protectPeer"), p) +} + +func (c *Client) UnprotectPeer(ctx context.Context, p peer.ID) error { + return c.c.CallContext(ctx, nil, prefixRPC("unprotectPeer"), p) +} + +func (c *Client) ConnectPeer(ctx context.Context, addr ma.Multiaddr) error { + return c.c.CallContext(ctx, nil, prefixRPC("connectPeer"), addr) +} + +func (c *Client) DisconnectPeer(ctx context.Context, id peer.ID) error { + return c.c.CallContext(ctx, nil, prefixRPC("disconnectPeer"), id) +} diff --git a/opnode/p2p/api.go b/opnode/p2p/rpc_server.go similarity index 70% rename from opnode/p2p/api.go rename to opnode/p2p/rpc_server.go index 97a9460f0acf..797b7ade7aa4 100644 --- a/opnode/p2p/api.go +++ b/opnode/p2p/rpc_server.go @@ -8,6 +8,7 @@ import ( "net" "time" + gcrypto "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" @@ -18,6 +19,7 @@ import ( "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p-testing/netutil" ma "github.com/multiformats/go-multiaddr" ) @@ -56,6 +58,8 @@ type APIBackend struct { log log.Logger } +var _ API = (*APIBackend)(nil) + func NewP2PAPIBackend(node Node, log log.Logger) *APIBackend { return &APIBackend{ node: node, @@ -63,28 +67,6 @@ func NewP2PAPIBackend(node Node, log log.Logger) *APIBackend { } } -type PeerInfo struct { - PeerID peer.ID `json:"peerID"` - NodeID enode.ID `json:"nodeID"` - UserAgent string `json:"userAgent"` - ProtocolVersion string `json:"protocolVersion"` - ENR string `json:"ENR"` // might not always be known, e.g. if the peer connected us instead of us discovering them - Addresses []ma.Multiaddr `json:"addresses"` // may be mix of LAN / docker / external IPs. All of them are communicated. - Protocols []string `json:"protocols"` // negotiated protocols list - //GossipScore float64 - //PeerScore float64 - Connectedness network.Connectedness `json:"connectedness"` // "NotConnected", "Connected", "CanConnect" (gracefully disconnected), or "CannotConnect" (tried but failed) - Direction network.Direction `json:"direction"` // "Unknown", "Inbound" (if the peer contacted us), "Outbound" (if we connected to them) - BannedID bool `json:"bannedID"` // If the peer has been banned by peer ID - BannedIP bool `json:"bannedIP"` // If the peer has been banned by IP address - BannedSubnet bool `json:"bannedSubnet"` // If the peer has been banned as part of a whole IP subnet - Protected bool `json:"protected"` // Protected peers do not get - ChainID uint64 `json:"chainID"` // some peers might try to connect, but we figure out they are on a different chain later. This may be 0 if the peer is not an optimism node at all. - Latency time.Duration `json:"latency"` - - GossipBlocks bool `json:"gossipBlocks"` // if the peer is in our gossip topic -} - func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMgr connmgr.ConnManager) (*PeerInfo, error) { info := &PeerInfo{ PeerID: id, @@ -93,11 +75,15 @@ func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMg // we might not have the pubkey if it's from a multi-addr and if we never discovered/connected them pub := pstore.PubKey(id) if pub != nil { - typedPub, ok := pub.(*crypto.Secp256k1PublicKey) - if !ok { - return nil, fmt.Errorf("unexpected pubkey type: %T", pub) + if testPub, ok := pub.(netutil.TestBogusPublicKey); ok { + info.NodeID = enode.ID(gcrypto.Keccak256Hash(testPub)) + } else { + typedPub, ok := pub.(*crypto.Secp256k1PublicKey) + if !ok { + return nil, fmt.Errorf("unexpected pubkey type: %T", pub) + } + info.NodeID = enode.PubkeyToIDV4((*ecdsa.PublicKey)(typedPub)) } - info.NodeID = enode.PubkeyToIDV4((*ecdsa.PublicKey)(typedPub)) } if dat, err := pstore.Get(id, "ProtocolVersion"); err != nil { protocolVersion, ok := dat.(string) @@ -117,7 +103,13 @@ func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMg info.ENR = enodeData.String() } } - info.Addresses = pstore.Addrs(id) + // include the /p2p/ address component in all of the addresses for convenience of the API user. + p2pAddrs, err := peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: id, Addrs: pstore.Addrs(id)}) + if err != nil { + for _, addr := range p2pAddrs { + info.Addresses = append(info.Addresses, addr.String()) + } + } info.Connectedness = nw.Connectedness(id) if protocols, err := pstore.GetProtocols(id); err != nil { info.Protocols = protocols @@ -141,14 +133,6 @@ func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMg return info, nil } -type PeerDump struct { - TotalConnected uint `json:"totalConnected"` - Peers map[peer.ID]*PeerInfo `json:"peers"` - BannedPeers []peer.ID `json:"bannedPeers"` - BannedIPS []net.IP `json:"bannedIPS"` - BannedSubnets []*net.IPNet `json:"bannedSubnets"` -} - // Peers lists information of peers. Optionally filter to only retrieve connected peers. func (s *APIBackend) Peers(ctx context.Context, connected bool) (*PeerDump, error) { h := s.node.Host() @@ -165,18 +149,22 @@ func (s *APIBackend) Peers(ctx context.Context, connected bool) (*PeerDump, erro peers = pstore.Peers() } - dump := &PeerDump{Peers: make(map[peer.ID]*PeerInfo)} + dump := &PeerDump{Peers: make(map[string]*PeerInfo)} for _, id := range peers { peerInfo, err := dumpPeer(id, nw, pstore, s.node.ConnectionManager()) if err != nil { - dump.Peers[id] = peerInfo + s.log.Debug("failed to dump peer info in RPC request", "peer", id, "err", err) + continue } + // We don't use the peer.ID type as key, + // since JSON decoding can't use the provided json unmarshaler (on *string type). + dump.Peers[id.String()] = peerInfo if peerInfo.Connectedness == network.Connected { dump.TotalConnected += 1 } } for _, id := range s.node.GossipTopicInfo().BlocksTopicPeers() { - if p, ok := dump.Peers[id]; ok { + if p, ok := dump.Peers[id.String()]; ok { p.GossipBlocks = true } } @@ -196,7 +184,7 @@ type PeerStats struct { Known uint `json:"known"` } -func (s *APIBackend) PeerStats() (*PeerStats, error) { +func (s *APIBackend) PeerStats(_ context.Context) (*PeerStats, error) { h := s.node.Host() if h == nil { return nil, DisabledP2P @@ -221,7 +209,7 @@ func (s *APIBackend) PeerStats() (*PeerStats, error) { return stats, nil } -func (s *APIBackend) DiscoveryTable() ([]*enode.Node, error) { +func (s *APIBackend) DiscoveryTable(_ context.Context) ([]*enode.Node, error) { if dv5 := s.node.Dv5Udp(); dv5 != nil { return dv5.AllNodes(), nil } else { @@ -229,7 +217,7 @@ func (s *APIBackend) DiscoveryTable() ([]*enode.Node, error) { } } -func (s *APIBackend) BlockPeer(p peer.ID) error { +func (s *APIBackend) BlockPeer(_ context.Context, p peer.ID) error { if gater := s.node.ConnectionGater(); gater == nil { return NoConnectionGater } else { @@ -237,7 +225,7 @@ func (s *APIBackend) BlockPeer(p peer.ID) error { } } -func (s *APIBackend) UnblockPeer(p peer.ID) error { +func (s *APIBackend) UnblockPeer(_ context.Context, p peer.ID) error { if gater := s.node.ConnectionGater(); gater == nil { return NoConnectionGater } else { @@ -245,7 +233,7 @@ func (s *APIBackend) UnblockPeer(p peer.ID) error { } } -func (s *APIBackend) ListBlockedPeers() ([]peer.ID, error) { +func (s *APIBackend) ListBlockedPeers(_ context.Context) ([]peer.ID, error) { if gater := s.node.ConnectionGater(); gater == nil { return nil, NoConnectionGater } else { @@ -255,7 +243,7 @@ func (s *APIBackend) ListBlockedPeers() ([]peer.ID, error) { // BlockAddr adds an IP address to the set of blocked addresses. // Note: active connections to the IP address are not automatically closed. -func (s *APIBackend) BlockAddr(ip net.IP) error { +func (s *APIBackend) BlockAddr(_ context.Context, ip net.IP) error { if gater := s.node.ConnectionGater(); gater == nil { return NoConnectionGater } else { @@ -263,7 +251,7 @@ func (s *APIBackend) BlockAddr(ip net.IP) error { } } -func (s *APIBackend) UnblockAddr(ip net.IP) error { +func (s *APIBackend) UnblockAddr(_ context.Context, ip net.IP) error { if gater := s.node.ConnectionGater(); gater == nil { return NoConnectionGater } else { @@ -271,7 +259,7 @@ func (s *APIBackend) UnblockAddr(ip net.IP) error { } } -func (s *APIBackend) ListBlockedAddrs() ([]net.IP, error) { +func (s *APIBackend) ListBlockedAddrs(_ context.Context) ([]net.IP, error) { if gater := s.node.ConnectionGater(); gater == nil { return nil, NoConnectionGater } else { @@ -281,7 +269,7 @@ func (s *APIBackend) ListBlockedAddrs() ([]net.IP, error) { // BlockSubnet adds an IP subnet to the set of blocked addresses. // Note: active connections to the IP subnet are not automatically closed. -func (s *APIBackend) BlockSubnet(ipnet *net.IPNet) error { +func (s *APIBackend) BlockSubnet(_ context.Context, ipnet *net.IPNet) error { if gater := s.node.ConnectionGater(); gater == nil { return NoConnectionGater } else { @@ -289,7 +277,7 @@ func (s *APIBackend) BlockSubnet(ipnet *net.IPNet) error { } } -func (s *APIBackend) UnblockSubnet(ipnet *net.IPNet) error { +func (s *APIBackend) UnblockSubnet(_ context.Context, ipnet *net.IPNet) error { if gater := s.node.ConnectionGater(); gater == nil { return NoConnectionGater } else { @@ -297,7 +285,7 @@ func (s *APIBackend) UnblockSubnet(ipnet *net.IPNet) error { } } -func (s *APIBackend) ListBlockedSubnets() ([]*net.IPNet, error) { +func (s *APIBackend) ListBlockedSubnets(_ context.Context) ([]*net.IPNet, error) { if gater := s.node.ConnectionGater(); gater == nil { return nil, NoConnectionGater } else { @@ -305,7 +293,7 @@ func (s *APIBackend) ListBlockedSubnets() ([]*net.IPNet, error) { } } -func (s *APIBackend) ProtectPeer(p peer.ID) error { +func (s *APIBackend) ProtectPeer(_ context.Context, p peer.ID) error { if manager := s.node.ConnectionManager(); manager == nil { return NoConnectionManager } else { @@ -314,7 +302,7 @@ func (s *APIBackend) ProtectPeer(p peer.ID) error { } } -func (s *APIBackend) UnprotectPeer(p peer.ID) error { +func (s *APIBackend) UnprotectPeer(_ context.Context, p peer.ID) error { if manager := s.node.ConnectionManager(); manager == nil { return NoConnectionManager } else { @@ -339,7 +327,7 @@ func (s *APIBackend) ConnectPeer(ctx context.Context, addr ma.Multiaddr) error { return h.Connect(ctx, *addrInfo) } -func (s *APIBackend) DisconnectPeer(id peer.ID) error { +func (s *APIBackend) DisconnectPeer(_ context.Context, id peer.ID) error { h := s.node.Host() if h == nil { return DisabledP2P diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index e7f0c047f18a..260e96c73299 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -8,16 +8,15 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/libp2p/go-libp2p-core/peer" - "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/node" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" @@ -30,6 +29,8 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" "github.com/stretchr/testify/require" ) @@ -540,8 +541,25 @@ func TestSystemMockP2P(t *testing.T) { // Verify that the tx was received via p2p require.Contains(t, published, receiptVerif.BlockHash) - // Try get p2p debug info from the RPC - // TODO: RPC client bindings for p2p api + // The more efficient way for testing would be to directly call the server + // (construct a backend that wraps the rollup node of choice), + // or to Dial in-process to the RPC server. + // But we want to test the P2P RPC at least once in this test here. + rollupRPCClient, err := rpc.DialContext(context.Background(), + fmt.Sprintf("http://%s:%d", + cfg.Nodes["sequencer"].RPC.ListenAddr, + cfg.Nodes["sequencer"].RPC.ListenPort)) + require.Nil(t, err) + + rollupP2P := p2p.NewClient(rollupRPCClient) + // Ask the sequencer for all peer information they have + peerDump, err := rollupP2P.Peers(context.Background(), false) + require.Nil(t, err) + // Check if the verifier data is in there + verifierID := sys.rollupNodes["verifier"].Host().ID() + require.Contains(t, peerDump.Peers, verifierID.String()) + data := peerDump.Peers[verifierID.String()] + require.Equal(t, data.Direction, network.DirInbound) } func TestL1InfoContract(t *testing.T) { From d6f518228971767209c4a9f69122e014a4e06d7b Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 13 May 2022 01:00:44 +0200 Subject: [PATCH 570/585] opnode/p2p: set up connection notification before starting host B --- opnode/p2p/host_test.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/opnode/p2p/host_test.go b/opnode/p2p/host_test.go index e2db746ae702..06bb7f6d4891 100644 --- a/opnode/p2p/host_test.go +++ b/opnode/p2p/host_test.go @@ -119,15 +119,17 @@ func TestP2PFull(t *testing.T) { require.NoError(t, err) defer hostA.Close() + conns := make(chan network.Conn, 1) + hostA.Network().Notify(&network.NotifyBundle{ + ConnectedF: func(n network.Network, conn network.Conn) { + conns <- conn + t.Log("connected") + }}) + // Set up B to connect statically confB.StaticPeers, err = peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: hostA.ID(), Addrs: hostA.Addrs()}) require.NoError(t, err) - conns := make(chan network.Conn, 1) - hostA.Network().Notify(&network.NotifyBundle{ConnectedF: func(n network.Network, conn network.Conn) { - conns <- conn - }}) - hostB, err := confB.Host(testlog.Logger(t, log.LvlError).New("host", "B")) require.NoError(t, err) defer hostB.Close() @@ -135,10 +137,9 @@ func TestP2PFull(t *testing.T) { select { case <-time.After(time.Second): t.Fatal("failed to connect new host") - case <-conns: + case c := <-conns: + require.Equal(t, hostB.ID(), c.RemotePeer()) } - require.NoError(t, err, "failed to connect to peer B from peer A") - require.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) } // Most tests should use mocknets instead of using the actual local host network From 283cc70a76eb06782ecafea852d7e182abf2fe37 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 13 May 2022 02:55:23 +0200 Subject: [PATCH 571/585] opnode/p2p: bundle p2p components into p2p node for separate testing --- opnode/node/node.go | 108 +++++------------------------- opnode/p2p/host.go | 11 +++- opnode/p2p/host_test.go | 87 ++++++++++++++++++++++-- opnode/p2p/node.go | 132 +++++++++++++++++++++++++++++++++++++ opnode/p2p/rpc_api.go | 3 +- opnode/p2p/rpc_client.go | 3 +- opnode/p2p/rpc_server.go | 37 ++++------- opnode/test/setup.go | 1 + opnode/test/system_test.go | 29 ++------ 9 files changed, 257 insertions(+), 154 deletions(-) create mode 100644 opnode/p2p/node.go diff --git a/opnode/node/node.go b/opnode/node/node.go index 7779f1e62a64..aa7c578c2af5 100644 --- a/opnode/node/node.go +++ b/opnode/node/node.go @@ -6,18 +6,10 @@ import ( "sync" "time" - "github.com/libp2p/go-libp2p-core/connmgr" - "github.com/libp2p/go-libp2p/p2p/protocol/identify" - "github.com/libp2p/go-libp2p-core/peer" "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" - "github.com/ethereum/go-ethereum/p2p/discover" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/libp2p/go-libp2p-core/host" - pubsub "github.com/libp2p/go-libp2p-pubsub" - multierror "github.com/hashicorp/go-multierror" "github.com/ethereum-optimism/optimistic-specs/opnode/backoff" @@ -42,13 +34,7 @@ type OpNode struct { l2Engines []*driver.Driver // engines to keep synced l2Nodes []*rpc.Client // L2 Execution Engines to close at shutdown server *rpcServer // RPC server hosting the rollup-node API - host host.Host // p2p host (optional, may be nil) - gater p2p.ConnectionGater // p2p gater, to ban/unban peers with, may be nil even with p2p enabled - connMgr connmgr.ConnManager // p2p conn manager, to keep a reliable number of peers, may be nil even with p2p enabled - dv5Local *enode.LocalNode // p2p discovery identity (optional, may be nil) - dv5Udp *discover.UDPv5 // p2p discovery service (optional, may be nil) - gs *pubsub.PubSub // p2p gossip router (optional, may be nil) - gsOut p2p.GossipOut // p2p gossip application interface for publishing (optional, may be nil) + p2pNode p2p.Node // P2P node functionality p2pSigner p2p.Signer // p2p gogssip application messages will be signed with this signer tracer Tracer // tracer to get events for testing/debugging @@ -216,8 +202,8 @@ func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error { if err != nil { return err } - if n.host != nil { - n.server.EnableP2P(p2p.NewP2PAPIBackend(n, n.log)) + if n.p2pNode != nil { + n.server.EnableP2P(p2p.NewP2PAPIBackend(n.p2pNode, n.log)) } n.log.Info("Starting JSON-RPC server") if err := n.server.Start(); err != nil { @@ -227,43 +213,12 @@ func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error { } func (n *OpNode) initP2P(ctx context.Context, cfg *Config) error { - // the p2p setup is optional - if cfg.P2P == nil { - return nil - } - var err error - // All nil if disabled. - n.dv5Local, n.dv5Udp, err = cfg.P2P.Discovery(n.log.New("p2p", "discv5")) - if err != nil { - return fmt.Errorf("failed to start discv5: %v", err) - } - - // nil if disabled. - n.host, err = cfg.P2P.Host(n.log) - if err != nil { - return fmt.Errorf("failed to start p2p host: %v", err) - } - - if n.host != nil { - // Enable extra features, if any. During testing we don't setup the most advanced host all the time. - if extra, ok := n.host.(p2p.ExtraHostFeatures); ok { - n.gater = extra.ConnectionGater() - n.connMgr = extra.ConnectionManager() - } - // notify of any new connections/streams/etc. - n.host.Network().Notify(p2p.NewNetworkNotifier(n.log)) - // unregister identify-push handler. Only identifying on dial is fine, and more robust against spam - n.host.RemoveStreamHandler(identify.IDDelta) - n.gs, err = p2p.NewGossipSub(n.resourcesCtx, n.host, &cfg.Rollup) + if cfg.P2P != nil { + p2pNode, err := p2p.NewNodeP2P(n.resourcesCtx, &cfg.Rollup, n.log, cfg.P2P, n) if err != nil { - return fmt.Errorf("failed to start gossipsub router: %v", err) - } - - n.gsOut, err = p2p.JoinGossip(n.resourcesCtx, n.host.ID(), n.gs, n.log, &cfg.Rollup, n) - if err != nil { - return fmt.Errorf("failed to join blocks gossip topic: %v", err) + return err } - n.log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().Pretty()) + n.p2pNode = p2pNode } return nil } @@ -318,12 +273,12 @@ func (n *OpNode) PublishL2Payload(ctx context.Context, payload *l2.ExecutionPayl n.tracer.OnPublishL2Payload(ctx, payload) // publish to p2p, if we are running p2p at all - if n.gsOut != nil { + if n.p2pNode != nil { if n.p2pSigner == nil { return fmt.Errorf("node has no p2p signer, payload %s cannot be published", payload.ID()) } n.log.Info("Publishing signed execution payload on p2p", "id", payload.ID()) - return n.gsOut.PublishL2Payload(ctx, payload, n.p2pSigner) + return n.p2pNode.GossipOut().PublishL2Payload(ctx, payload, n.p2pSigner) } // if p2p is not enabled then we just don't publish the payload return nil @@ -334,7 +289,7 @@ func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, payload *l defer n.l2Lock.Unlock() // ignore if it's from ourselves - if from == n.host.ID() { + if n.p2pNode != nil && from == n.p2pNode.Host().ID() { return nil } @@ -355,32 +310,8 @@ func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, payload *l return nil } -func (n *OpNode) Host() host.Host { - return n.host -} - -func (n *OpNode) Dv5Local() *enode.LocalNode { - return n.dv5Local -} - -func (n *OpNode) Dv5Udp() *discover.UDPv5 { - return n.dv5Udp -} - -func (n *OpNode) GossipSub() *pubsub.PubSub { - return n.gs -} - -func (n *OpNode) GossipTopicInfo() p2p.GossipTopicInfo { - return n.gsOut -} - -func (n *OpNode) ConnectionGater() p2p.ConnectionGater { - return n.gater -} - -func (n *OpNode) ConnectionManager() connmgr.ConnManager { - return n.connMgr +func (n *OpNode) P2P() p2p.Node { + return n.p2pNode } // Close closes all resources. @@ -390,12 +321,9 @@ func (n *OpNode) Close() error { if n.server != nil { n.server.Stop() } - if n.dv5Udp != nil { - n.dv5Udp.Close() - } - if n.gsOut != nil { - if err := n.gsOut.Close(); err != nil { - result = multierror.Append(result, fmt.Errorf("failed to close gossip cleanly: %v", err)) + if n.p2pNode != nil { + if err := n.p2pNode.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close p2p node: %v", err)) } } if n.p2pSigner != nil { @@ -403,11 +331,7 @@ func (n *OpNode) Close() error { result = multierror.Append(result, fmt.Errorf("failed to close p2p signer: %v", err)) } } - if n.host != nil { - if err := n.host.Close(); err != nil { - result = multierror.Append(result, fmt.Errorf("failed to close p2p host cleanly: %v", err)) - } - } + if n.resourcesClose != nil { n.resourcesClose() } diff --git a/opnode/p2p/host.go b/opnode/p2p/host.go index 08d836a5f4d2..f5b1af92fb26 100644 --- a/opnode/p2p/host.go +++ b/opnode/p2p/host.go @@ -21,6 +21,7 @@ import ( ) type ExtraHostFeatures interface { + host.Host ConnectionGater() ConnectionGater ConnectionManager() connmgr.ConnManager } @@ -31,7 +32,15 @@ type extraHost struct { connMgr connmgr.ConnManager } -var _ host.Host = (*extraHost)(nil) +func (e *extraHost) ConnectionGater() ConnectionGater { + return e.gater +} + +func (e *extraHost) ConnectionManager() connmgr.ConnManager { + return e.connMgr +} + +var _ ExtraHostFeatures = (*extraHost)(nil) func (conf *Config) Host(log log.Logger) (host.Host, error) { if conf.DisableP2P { diff --git a/opnode/p2p/host_test.go b/opnode/p2p/host_test.go index 06bb7f6d4891..a1e0d470d4d3 100644 --- a/opnode/p2p/host_test.go +++ b/opnode/p2p/host_test.go @@ -9,8 +9,10 @@ import ( "time" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum/go-ethereum/log" - + "github.com/ethereum/go-ethereum/rpc" ds "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/sync" "github.com/libp2p/go-libp2p-core/connmgr" @@ -71,6 +73,17 @@ func TestP2PSimple(t *testing.T) { require.Equal(t, hostB.Network().Connectedness(hostA.ID()), network.Connected) } +type mockGossipIn struct { + OnUnsafeL2PayloadFn func(ctx context.Context, from peer.ID, msg *l2.ExecutionPayload) error +} + +func (m *mockGossipIn) OnUnsafeL2Payload(ctx context.Context, from peer.ID, msg *l2.ExecutionPayload) error { + if m.OnUnsafeL2PayloadFn != nil { + return m.OnUnsafeL2PayloadFn(ctx, from, msg) + } + return nil +} + // Full setup, using negotiated transport security and muxes func TestP2PFull(t *testing.T) { pA, _, err := crypto.GenerateSecp256k1Key(rand.Reader) @@ -115,24 +128,34 @@ func TestP2PFull(t *testing.T) { confB.Store = sync.MutexWrap(ds.NewMapDatastore()) // TODO: maybe swap the order of sec/mux preferences, to test that negotiation works - hostA, err := confA.Host(testlog.Logger(t, log.LvlError).New("host", "A")) + logA := testlog.Logger(t, log.LvlError).New("host", "A") + nodeA, err := NewNodeP2P(context.Background(), &rollup.Config{}, logA, &confA, &mockGossipIn{}) require.NoError(t, err) - defer hostA.Close() + defer nodeA.Close() conns := make(chan network.Conn, 1) + hostA := nodeA.Host() hostA.Network().Notify(&network.NotifyBundle{ ConnectedF: func(n network.Network, conn network.Conn) { conns <- conn - t.Log("connected") }}) + backend := NewP2PAPIBackend(nodeA, logA) + srv := rpc.NewServer() + require.NoError(t, srv.RegisterName("opp2p", backend)) + client := rpc.DialInProc(srv) + p2pClientA := NewClient(client) + // Set up B to connect statically confB.StaticPeers, err = peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: hostA.ID(), Addrs: hostA.Addrs()}) require.NoError(t, err) - hostB, err := confB.Host(testlog.Logger(t, log.LvlError).New("host", "B")) + logB := testlog.Logger(t, log.LvlError).New("host", "B") + + nodeB, err := NewNodeP2P(context.Background(), &rollup.Config{}, logB, &confB, &mockGossipIn{}) require.NoError(t, err) - defer hostB.Close() + defer nodeB.Close() + hostB := nodeB.Host() select { case <-time.After(time.Second): @@ -140,6 +163,58 @@ func TestP2PFull(t *testing.T) { case c := <-conns: require.Equal(t, hostB.ID(), c.RemotePeer()) } + + ctx := context.Background() + _, err = p2pClientA.DiscoveryTable(ctx) + // rpc does not preserve error type + require.Equal(t, err.Error(), DisabledDiscovery.Error(), "expecting discv5 to be disabled") + + require.NoError(t, p2pClientA.BlockPeer(ctx, hostB.ID())) + blockedPeers, err := p2pClientA.ListBlockedPeers(ctx) + require.NoError(t, err) + require.Equal(t, []peer.ID{hostB.ID()}, blockedPeers) + require.NoError(t, p2pClientA.UnblockPeer(ctx, hostB.ID())) + + require.NoError(t, p2pClientA.BlockAddr(ctx, net.IP{123, 123, 123, 123})) + blockedIPs, err := p2pClientA.ListBlockedAddrs(ctx) + require.NoError(t, err) + require.Len(t, blockedIPs, 1) + require.Equal(t, net.IP{123, 123, 123, 123}, blockedIPs[0].To4()) + require.NoError(t, p2pClientA.UnblockAddr(ctx, net.IP{123, 123, 123, 123})) + + subnet := &net.IPNet{IP: net.IP{123, 0, 0, 0}.To16(), Mask: net.IPMask{0xff, 0, 0, 0}} + require.NoError(t, p2pClientA.BlockSubnet(ctx, subnet)) + blockedSubnets, err := p2pClientA.ListBlockedSubnets(ctx) + require.NoError(t, err) + require.Len(t, blockedSubnets, 1) + require.Equal(t, subnet, blockedSubnets[0]) + require.NoError(t, p2pClientA.UnblockSubnet(ctx, subnet)) + + // Ask host A for all peer information they have + peerDump, err := p2pClientA.Peers(ctx, false) + require.Nil(t, err) + require.Contains(t, peerDump.Peers, hostB.ID().String()) + data := peerDump.Peers[hostB.ID().String()] + require.Equal(t, data.Direction, network.DirInbound) + + stats, err := p2pClientA.PeerStats(ctx) + require.Nil(t, err) + require.Equal(t, uint(1), stats.Connected) + + // disconnect + require.NoError(t, p2pClientA.DisconnectPeer(ctx, hostB.ID())) + peerDump, err = p2pClientA.Peers(ctx, false) + require.Nil(t, err) + data = peerDump.Peers[hostB.ID().String()] + require.Equal(t, data.Connectedness, network.NotConnected) + + // reconnect + addrsB, err := peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) + require.NoError(t, err) + require.NoError(t, p2pClientA.ConnectPeer(ctx, addrsB[0].String())) + + require.NoError(t, p2pClientA.ProtectPeer(ctx, hostB.ID())) + require.NoError(t, p2pClientA.UnprotectPeer(ctx, hostB.ID())) } // Most tests should use mocknets instead of using the actual local host network diff --git a/opnode/p2p/node.go b/opnode/p2p/node.go new file mode 100644 index 000000000000..a9be4c2b2d39 --- /dev/null +++ b/opnode/p2p/node.go @@ -0,0 +1,132 @@ +package p2p + +import ( + "context" + "errors" + "fmt" + + "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/hashicorp/go-multierror" + "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p-core/host" + pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p/p2p/protocol/identify" +) + +type NodeP2P struct { + host host.Host // p2p host (optional, may be nil) + gater ConnectionGater // p2p gater, to ban/unban peers with, may be nil even with p2p enabled + connMgr connmgr.ConnManager // p2p conn manager, to keep a reliable number of peers, may be nil even with p2p enabled + dv5Local *enode.LocalNode // p2p discovery identity (optional, may be nil) + dv5Udp *discover.UDPv5 // p2p discovery service (optional, may be nil) + gs *pubsub.PubSub // p2p gossip router (optional, may be nil) + gsOut GossipOut // p2p gossip application interface for publishing (optional, may be nil) +} + +func NewNodeP2P(resourcesCtx context.Context, rollupCfg *rollup.Config, log log.Logger, setup SetupP2P, gossipIn GossipIn) (*NodeP2P, error) { + if setup == nil { + return nil, errors.New("p2p node cannot be created without setup") + } + var n NodeP2P + if err := n.init(resourcesCtx, rollupCfg, log, setup, gossipIn); err != nil { + closeErr := n.Close() + if closeErr != nil { + log.Error("failed to close p2p after starting with err", "closeErr", closeErr, "err", err) + } + return nil, err + } + if n.host == nil { + return nil, nil + } + return &n, nil +} + +func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, log log.Logger, setup SetupP2P, gossipIn GossipIn) error { + var err error + // All nil if disabled. + n.dv5Local, n.dv5Udp, err = setup.Discovery(log.New("p2p", "discv5")) + if err != nil { + return fmt.Errorf("failed to start discv5: %v", err) + } + + // nil if disabled. + n.host, err = setup.Host(log) + if err != nil { + if n.dv5Udp != nil { + n.dv5Udp.Close() + } + return fmt.Errorf("failed to start p2p host: %v", err) + } + + if n.host != nil { + // Enable extra features, if any. During testing we don't setup the most advanced host all the time. + if extra, ok := n.host.(ExtraHostFeatures); ok { + n.gater = extra.ConnectionGater() + n.connMgr = extra.ConnectionManager() + } + // notify of any new connections/streams/etc. + n.host.Network().Notify(NewNetworkNotifier(log)) + // unregister identify-push handler. Only identifying on dial is fine, and more robust against spam + n.host.RemoveStreamHandler(identify.IDDelta) + n.gs, err = NewGossipSub(resourcesCtx, n.host, rollupCfg) + if err != nil { + return fmt.Errorf("failed to start gossipsub router: %v", err) + } + + n.gsOut, err = JoinGossip(resourcesCtx, n.host.ID(), n.gs, log, rollupCfg, gossipIn) + if err != nil { + return fmt.Errorf("failed to join blocks gossip topic: %v", err) + } + log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().Pretty()) + } + return nil +} + +func (n *NodeP2P) Host() host.Host { + return n.host +} + +func (n *NodeP2P) Dv5Local() *enode.LocalNode { + return n.dv5Local +} + +func (n *NodeP2P) Dv5Udp() *discover.UDPv5 { + return n.dv5Udp +} + +func (n *NodeP2P) GossipSub() *pubsub.PubSub { + return n.gs +} + +func (n *NodeP2P) GossipOut() GossipOut { + return n.gsOut +} + +func (n *NodeP2P) ConnectionGater() ConnectionGater { + return n.gater +} + +func (n *NodeP2P) ConnectionManager() connmgr.ConnManager { + return n.connMgr +} + +func (n *NodeP2P) Close() error { + var result *multierror.Error + if n.dv5Udp != nil { + n.dv5Udp.Close() + } + if n.gsOut != nil { + if err := n.gsOut.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close gossip cleanly: %v", err)) + } + } + if n.host != nil { + if err := n.host.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close p2p host cleanly: %v", err)) + } + } + return result.ErrorOrNil() +} diff --git a/opnode/p2p/rpc_api.go b/opnode/p2p/rpc_api.go index 01f0573c9ede..9c865cebdaac 100644 --- a/opnode/p2p/rpc_api.go +++ b/opnode/p2p/rpc_api.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" - ma "github.com/multiformats/go-multiaddr" ) type PeerInfo struct { @@ -56,6 +55,6 @@ type API interface { ListBlockedSubnets(ctx context.Context) ([]*net.IPNet, error) ProtectPeer(ctx context.Context, p peer.ID) error UnprotectPeer(ctx context.Context, p peer.ID) error - ConnectPeer(ctx context.Context, addr ma.Multiaddr) error + ConnectPeer(ctx context.Context, addr string) error DisconnectPeer(ctx context.Context, id peer.ID) error } diff --git a/opnode/p2p/rpc_client.go b/opnode/p2p/rpc_client.go index de086ca6e4ec..49871b524ec6 100644 --- a/opnode/p2p/rpc_client.go +++ b/opnode/p2p/rpc_client.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/rpc" "github.com/libp2p/go-libp2p-core/peer" - ma "github.com/multiformats/go-multiaddr" ) var NamespaceRPC = "opp2p" @@ -94,7 +93,7 @@ func (c *Client) UnprotectPeer(ctx context.Context, p peer.ID) error { return c.c.CallContext(ctx, nil, prefixRPC("unprotectPeer"), p) } -func (c *Client) ConnectPeer(ctx context.Context, addr ma.Multiaddr) error { +func (c *Client) ConnectPeer(ctx context.Context, addr string) error { return c.c.CallContext(ctx, nil, prefixRPC("connectPeer"), addr) } diff --git a/opnode/p2p/rpc_server.go b/opnode/p2p/rpc_server.go index 797b7ade7aa4..f1ce0642a289 100644 --- a/opnode/p2p/rpc_server.go +++ b/opnode/p2p/rpc_server.go @@ -5,6 +5,7 @@ import ( "crypto/ecdsa" "errors" "fmt" + "io" "net" "time" @@ -20,7 +21,6 @@ import ( "github.com/libp2p/go-libp2p-core/peerstore" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p-testing/netutil" - ma "github.com/multiformats/go-multiaddr" ) // TODO: dynamic peering @@ -30,14 +30,13 @@ import ( // - peers must be tagged with the "optimism" tag and marked with high value if the chain ID matches var ( - DisabledP2P = errors.New("p2p is disabled") DisabledDiscovery = errors.New("discovery disabled") NoConnectionManager = errors.New("no connection manager") NoConnectionGater = errors.New("no connection gater") ) type Node interface { - // Host returns the libp2p host, nil if disabled + // Host returns the libp2p host Host() host.Host // Dv5Local returns the control over the Discv5 data of the local node, nil if disabled Dv5Local() *enode.LocalNode @@ -45,12 +44,13 @@ type Node interface { Dv5Udp() *discover.UDPv5 // GossipSub returns the gossip router GossipSub() *pubsub.PubSub - // GossipTopicInfo returns the gossip topic info handle - GossipTopicInfo() GossipTopicInfo + // GossipOut returns the gossip output/info control + GossipOut() GossipOut // ConnectionGater returns the connection gater, to ban/unban peers with, may be nil ConnectionGater() ConnectionGater // ConnectionManager returns the connection manager, to protect peers with, may be nil ConnectionManager() connmgr.ConnManager + io.Closer } type APIBackend struct { @@ -105,7 +105,7 @@ func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMg } // include the /p2p/ address component in all of the addresses for convenience of the API user. p2pAddrs, err := peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: id, Addrs: pstore.Addrs(id)}) - if err != nil { + if err == nil { for _, addr := range p2pAddrs { info.Addresses = append(info.Addresses, addr.String()) } @@ -136,10 +136,6 @@ func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMg // Peers lists information of peers. Optionally filter to only retrieve connected peers. func (s *APIBackend) Peers(ctx context.Context, connected bool) (*PeerDump, error) { h := s.node.Host() - if h == nil { - return nil, DisabledP2P - } - nw := h.Network() pstore := h.Peerstore() var peers []peer.ID @@ -163,7 +159,7 @@ func (s *APIBackend) Peers(ctx context.Context, connected bool) (*PeerDump, erro dump.TotalConnected += 1 } } - for _, id := range s.node.GossipTopicInfo().BlocksTopicPeers() { + for _, id := range s.node.GossipOut().BlocksTopicPeers() { if p, ok := dump.Peers[id.String()]; ok { p.GossipBlocks = true } @@ -186,17 +182,13 @@ type PeerStats struct { func (s *APIBackend) PeerStats(_ context.Context) (*PeerStats, error) { h := s.node.Host() - if h == nil { - return nil, DisabledP2P - } - nw := h.Network() pstore := h.Peerstore() stats := &PeerStats{ Connected: uint(len(nw.Peers())), Table: 0, - BlocksTopic: uint(len(s.node.GossipTopicInfo().BlocksTopicPeers())), + BlocksTopic: uint(len(s.node.GossipOut().BlocksTopicPeers())), Banned: 0, Known: uint(len(pstore.Peers())), } @@ -312,12 +304,9 @@ func (s *APIBackend) UnprotectPeer(_ context.Context, p peer.ID) error { } // ConnectPeer connects to a given peer address, and wait for protocol negotiation & identification of the peer -func (s *APIBackend) ConnectPeer(ctx context.Context, addr ma.Multiaddr) error { +func (s *APIBackend) ConnectPeer(ctx context.Context, addr string) error { h := s.node.Host() - if h == nil { - return DisabledP2P - } - addrInfo, err := peer.AddrInfoFromP2pAddr(addr) + addrInfo, err := peer.AddrInfoFromString(addr) if err != nil { return fmt.Errorf("bad peer address: %v", err) } @@ -328,9 +317,5 @@ func (s *APIBackend) ConnectPeer(ctx context.Context, addr ma.Multiaddr) error { } func (s *APIBackend) DisconnectPeer(_ context.Context, id peer.ID) error { - h := s.node.Host() - if h == nil { - return DisabledP2P - } - return h.Network().ClosePeer(id) + return s.node.Host().Network().ClosePeer(id) } diff --git a/opnode/test/setup.go b/opnode/test/setup.go index 88b58aa4815f..9c6bee551860 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -425,6 +425,7 @@ func (cfg SystemConfig) start() (*System, error) { if err != nil { return nil, fmt.Errorf("failed to init p2p host for node %s", name) } + h.Network() _, ok := cfg.Nodes[name] if !ok { return nil, fmt.Errorf("node %s from p2p topology not found in actual nodes map", name) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 260e96c73299..8e240a035242 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -16,7 +16,6 @@ import ( "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/node" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" @@ -29,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" - "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" "github.com/stretchr/testify/require" ) @@ -535,31 +533,12 @@ func TestSystemMockP2P(t *testing.T) { require.Equal(t, receiptSeq, receiptVerif) - // Verify that everything that was published was received - require.Equal(t, published, received) + // Verify that everything that was received was published + require.GreaterOrEqual(t, len(published), len(received)) + require.Equal(t, received, published[:len(received)]) // Verify that the tx was received via p2p - require.Contains(t, published, receiptVerif.BlockHash) - - // The more efficient way for testing would be to directly call the server - // (construct a backend that wraps the rollup node of choice), - // or to Dial in-process to the RPC server. - // But we want to test the P2P RPC at least once in this test here. - rollupRPCClient, err := rpc.DialContext(context.Background(), - fmt.Sprintf("http://%s:%d", - cfg.Nodes["sequencer"].RPC.ListenAddr, - cfg.Nodes["sequencer"].RPC.ListenPort)) - require.Nil(t, err) - - rollupP2P := p2p.NewClient(rollupRPCClient) - // Ask the sequencer for all peer information they have - peerDump, err := rollupP2P.Peers(context.Background(), false) - require.Nil(t, err) - // Check if the verifier data is in there - verifierID := sys.rollupNodes["verifier"].Host().ID() - require.Contains(t, peerDump.Peers, verifierID.String()) - data := peerDump.Peers[verifierID.String()] - require.Equal(t, data.Direction, network.DirInbound) + require.Contains(t, received, receiptVerif.BlockHash) } func TestL1InfoContract(t *testing.T) { From 3ecf669f03480c098d05c7075009afbe99bcefa8 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 13 May 2022 03:01:25 +0200 Subject: [PATCH 572/585] opnode/p2p: minor style fix + rename --- opnode/p2p/{notifee.go => notifications.go} | 1 - 1 file changed, 1 deletion(-) rename opnode/p2p/{notifee.go => notifications.go} (99%) diff --git a/opnode/p2p/notifee.go b/opnode/p2p/notifications.go similarity index 99% rename from opnode/p2p/notifee.go rename to opnode/p2p/notifications.go index 611caa9342b9..f815626a4ae9 100644 --- a/opnode/p2p/notifee.go +++ b/opnode/p2p/notifications.go @@ -19,7 +19,6 @@ func (notif *notifications) ListenClose(n network.Network, a ma.Multiaddr) { notif.log.Info("stopped listening network address", "addr", a) } func (notif *notifications) Connected(n network.Network, v network.Conn) { - notif.log.Info("connected to peer", "peer", v.RemotePeer(), "addr", v.RemoteMultiaddr()) } func (notif *notifications) Disconnected(n network.Network, v network.Conn) { From a8243cb54ef08bbf127a021516ca0d129cb51c69 Mon Sep 17 00:00:00 2001 From: protolambda Date: Fri, 13 May 2022 04:50:26 +0200 Subject: [PATCH 573/585] opnode/p2p: add method to get peer info about self --- opnode/p2p/host_test.go | 5 +++++ opnode/p2p/rpc_api.go | 4 +--- opnode/p2p/rpc_client.go | 6 ++++++ opnode/p2p/rpc_server.go | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/opnode/p2p/host_test.go b/opnode/p2p/host_test.go index a1e0d470d4d3..ba5fb71fdf37 100644 --- a/opnode/p2p/host_test.go +++ b/opnode/p2p/host_test.go @@ -165,6 +165,11 @@ func TestP2PFull(t *testing.T) { } ctx := context.Background() + + selfInfoA, err := p2pClientA.Self(ctx) + require.NoError(t, err) + require.Equal(t, selfInfoA.PeerID, hostA.ID()) + _, err = p2pClientA.DiscoveryTable(ctx) // rpc does not preserve error type require.Equal(t, err.Error(), DisabledDiscovery.Error(), "expecting discv5 to be disabled") diff --git a/opnode/p2p/rpc_api.go b/opnode/p2p/rpc_api.go index 9c865cebdaac..0e6a5831946f 100644 --- a/opnode/p2p/rpc_api.go +++ b/opnode/p2p/rpc_api.go @@ -22,9 +22,6 @@ type PeerInfo struct { //PeerScore float64 Connectedness network.Connectedness `json:"connectedness"` // "NotConnected", "Connected", "CanConnect" (gracefully disconnected), or "CannotConnect" (tried but failed) Direction network.Direction `json:"direction"` // "Unknown", "Inbound" (if the peer contacted us), "Outbound" (if we connected to them) - BannedID bool `json:"bannedID"` // If the peer has been banned by peer ID - BannedIP bool `json:"bannedIP"` // If the peer has been banned by IP address - BannedSubnet bool `json:"bannedSubnet"` // If the peer has been banned as part of a whole IP subnet Protected bool `json:"protected"` // Protected peers do not get ChainID uint64 `json:"chainID"` // some peers might try to connect, but we figure out they are on a different chain later. This may be 0 if the peer is not an optimism node at all. Latency time.Duration `json:"latency"` @@ -41,6 +38,7 @@ type PeerDump struct { } type API interface { + Self(ctx context.Context) (*PeerInfo, error) Peers(ctx context.Context, connected bool) (*PeerDump, error) PeerStats(ctx context.Context) (*PeerStats, error) DiscoveryTable(ctx context.Context) ([]*enode.Node, error) diff --git a/opnode/p2p/rpc_client.go b/opnode/p2p/rpc_client.go index 49871b524ec6..375bd48a413c 100644 --- a/opnode/p2p/rpc_client.go +++ b/opnode/p2p/rpc_client.go @@ -25,6 +25,12 @@ func prefixRPC(method string) string { return NamespaceRPC + "_" + method } +func (c *Client) Self(ctx context.Context) (*PeerInfo, error) { + var out *PeerInfo + err := c.c.CallContext(ctx, &out, prefixRPC("self")) + return out, err +} + func (c *Client) Peers(ctx context.Context, connected bool) (*PeerDump, error) { var out *PeerDump err := c.c.CallContext(ctx, &out, prefixRPC("peers"), connected) diff --git a/opnode/p2p/rpc_server.go b/opnode/p2p/rpc_server.go index f1ce0642a289..e0f2c0d4419a 100644 --- a/opnode/p2p/rpc_server.go +++ b/opnode/p2p/rpc_server.go @@ -67,6 +67,22 @@ func NewP2PAPIBackend(node Node, log log.Logger) *APIBackend { } } +func (s *APIBackend) Self(ctx context.Context) (*PeerInfo, error) { + h := s.node.Host() + nw := h.Network() + pstore := h.Peerstore() + info, err := dumpPeer(h.ID(), nw, pstore, s.node.ConnectionManager()) + if err != nil { + return nil, err + } + info.GossipBlocks = true + info.Latency = 0 + if local := s.node.Dv5Local(); local != nil { + info.ENR = local.Node().String() + } + return info, nil +} + func dumpPeer(id peer.ID, nw network.Network, pstore peerstore.Peerstore, connMgr connmgr.ConnManager) (*PeerInfo, error) { info := &PeerInfo{ PeerID: id, From 81a15bec063a722a9af44736ae46ebf90b5b4f65 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 13 May 2022 09:53:26 -0600 Subject: [PATCH 574/585] Fix SRI on stateviz (#440) --- opnode/cmd/stateviz/assets/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opnode/cmd/stateviz/assets/index.html b/opnode/cmd/stateviz/assets/index.html index 486a47395e44..5d2d37eb1a39 100644 --- a/opnode/cmd/stateviz/assets/index.html +++ b/opnode/cmd/stateviz/assets/index.html @@ -17,7 +17,7 @@ + integrity="sha512-1zzZ0ynR2KXnFskJ1C2s+7TIEewmkB2y+5o/+ahF7mwNj9n3PnzARpqalvtjSbUETwx6yuxP5AJXZCpnjEJkQw==" crossorigin="anonymous"> From fb044a6e79d38db4a656f9b362849eccf681b25c Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 13 May 2022 09:54:46 -0700 Subject: [PATCH 575/585] Fix L2 Output Timestamps (#416) There was an off by one error in the L2 Output Oracle contract in the timestamp to block number conversion. In addition, the L2 Output Submitter (op proposer) did not recognize that there was a mismatch between the timestamp/block number in the header and the timestamp/block number from the contract. This bug causes problems when trying to do withdrawals. Fixes ENG-2128 --- l2os/bindings/l2oo/l2_output_oracle.go | 2 +- l2os/drivers/l2output/driver.go | 9 +++++++++ opnode/rollup/driver/step.go | 2 +- opnode/test/system_test.go | 9 +++++++++ packages/contracts/.gas-snapshot | 2 +- packages/contracts/contracts/L1/L2OutputOracle.sol | 1 - packages/contracts/contracts/test/L2OutputOracle.t.sol | 6 +++--- 7 files changed, 24 insertions(+), 7 deletions(-) diff --git a/l2os/bindings/l2oo/l2_output_oracle.go b/l2os/bindings/l2oo/l2_output_oracle.go index d2d9386b688a..c0cef403c622 100644 --- a/l2os/bindings/l2oo/l2_output_oracle.go +++ b/l2os/bindings/l2oo/l2_output_oracle.go @@ -37,7 +37,7 @@ type L2OutputOracleOutputProposal struct { // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"_proposal\",\"type\":\"tuple\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x61010060405234801561001157600080fd5b50604051610fa1380380610fa183398101604081905261003091610164565b61003933610114565b61004385876101c8565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052604080518082018252858152426020808301918252600086815260029091529290922090518155905160019182015560c084905282905560e082905261010981610114565b5050505050506101ea565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561017d57600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ba57600080fd5b809150509295509295509295565b6000826101e557634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610d5561024c600039600081816101af0152818161031b01526103f10152600081816102d5015261042201526000818160e801526103d00152600081816101e301528181610625015261095a0152610d556000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad146102c3578063f2fde38b146102f757600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b80630c1952d3116100b05780630c1952d31461015f5780632518810414610175578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d578063093b3d901461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610bbd565b610317565b34801561014957600080fd5b5061015d610158366004610bd6565b61044c565b005b34801561016b57600080fd5b5061010a60015481565b61015d610183366004610c4c565b610651565b34801561019457600080fd5b5061010a610956565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b5061015d61098b565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b506102a861026a366004610bbd565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b60408051825181526020928301519281019290925201610114565b3480156102cf57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561030357600080fd5b5061015d610312366004610c7e565b610a18565b60007f00000000000000000000000000000000000000000000000000000000000000008210156103ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161041f5761041f610cbb565b047f0000000000000000000000000000000000000000000000000000000000000000600101019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b6001805460009081526002602090815260409182902082518084019093528054808452930154908201528251909114610588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e0000000000000000000000000000000000000000000000000060648201526084016103c5565b80602001518260200151146105d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044016103c5565b600154602082015182516040517f6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c700990600090a46001805460009081526002602052604081208181558201555461064a907f000000000000000000000000000000000000000000000000000000000000000090610d19565b6001555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b428310610761576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016103c5565b610769610956565b83146107f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d7000000000000000000000000000000000000060648201526084016103c5565b8361085e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f757470757400000060448201526064016103c5565b81156108f457818140146108f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e0000000000000060648201526084016103c5565b60408051808201825285815242602080830182815260008881526002909252848220935184555160019384015591869055915185929187917f54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba9190a450505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546109869190610d30565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b610a166000610b48565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b73ffffffffffffffffffffffffffffffffffffffff8116610b3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103c5565b610b4581610b48565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610bcf57600080fd5b5035919050565b600060408284031215610be857600080fd5b6040516040810181811067ffffffffffffffff82111715610c32577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b60008060008060808587031215610c6257600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610c9057600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610cb457600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610d2b57610d2b610cea565b500390565b60008219821115610d4357610d43610cea565b50019056fea164736f6c634300080a000a", + Bin: "0x61010060405234801561001157600080fd5b50604051610f9e380380610f9e83398101604081905261003091610164565b61003933610114565b61004385876101c8565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052604080518082018252858152426020808301918252600086815260029091529290922090518155905160019182015560c084905282905560e082905261010981610114565b5050505050506101ea565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561017d57600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ba57600080fd5b809150509295509295509295565b6000826101e557634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610d5261024c600039600081816101af0152818161031b01526103f10152600081816102d5015261042201526000818160e801526103d00152600081816101e30152818161062201526109570152610d526000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad146102c3578063f2fde38b146102f757600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b80630c1952d3116100b05780630c1952d31461015f5780632518810414610175578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d578063093b3d901461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610bba565b610317565b34801561014957600080fd5b5061015d610158366004610bd3565b610449565b005b34801561016b57600080fd5b5061010a60015481565b61015d610183366004610c49565b61064e565b34801561019457600080fd5b5061010a610953565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b5061015d610988565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b506102a861026a366004610bba565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b60408051825181526020928301519281019290925201610114565b3480156102cf57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561030357600080fd5b5061015d610312366004610c7b565b610a15565b60007f00000000000000000000000000000000000000000000000000000000000000008210156103ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161041f5761041f610cb8565b047f0000000000000000000000000000000000000000000000000000000000000000019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b6001805460009081526002602090815260409182902082518084019093528054808452930154908201528251909114610585576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e0000000000000000000000000000000000000000000000000060648201526084016103c5565b80602001518260200151146105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044016103c5565b600154602082015182516040517f6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c700990600090a460018054600090815260026020526040812081815582015554610647907f000000000000000000000000000000000000000000000000000000000000000090610d16565b6001555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b42831061075e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016103c5565b610766610953565b83146107f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d7000000000000000000000000000000000000060648201526084016103c5565b8361085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f757470757400000060448201526064016103c5565b81156108f157818140146108f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e0000000000000060648201526084016103c5565b60408051808201825285815242602080830182815260008881526002909252848220935184555160019384015591869055915185929187917f54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba9190a450505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546109839190610d2d565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b610a136000610b45565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b73ffffffffffffffffffffffffffffffffffffffff8116610b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103c5565b610b4281610b45565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610bcc57600080fd5b5035919050565b600060408284031215610be557600080fd5b6040516040810181811067ffffffffffffffff82111715610c2f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b60008060008060808587031215610c5f57600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610c8d57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610cb157600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610d2857610d28610ce7565b500390565b60008219821115610d4057610d40610ce7565b50019056fea164736f6c634300080a000a", } // L2OutputOracleABI is the input ABI used to generate the binding from. diff --git a/l2os/drivers/l2output/driver.go b/l2os/drivers/l2output/driver.go index 350d103a09ce..b38759d23f54 100644 --- a/l2os/drivers/l2output/driver.go +++ b/l2os/drivers/l2output/driver.go @@ -207,6 +207,15 @@ func (d *Driver) CraftTx( return nil, fmt.Errorf("error resolving checkpoint block: %v", err) } + l2Header, err := d.cfg.L2Client.HeaderByNumber(ctx, nextCheckpointBlock) + if err != nil { + return nil, fmt.Errorf("error resolving checkpoint block: %v", err) + } + + if l2Header.Time != timestamp.Uint64() { + return nil, fmt.Errorf("invalid timestamp: next timestamp is %v, timestamp of block is %v", timestamp, l2Header.Time) + } + opts, err := bind.NewKeyedTransactorWithChainID( d.cfg.PrivKey, d.cfg.ChainID, ) diff --git a/opnode/rollup/driver/step.go b/opnode/rollup/driver/step.go index ca9bba78029b..e5f915cc9f83 100644 --- a/opnode/rollup/driver/step.go +++ b/opnode/rollup/driver/step.go @@ -297,7 +297,7 @@ func attributesMatchBlock(attrs *l2.PayloadAttributes, parentHash common.Hash, b } for i, otx := range attrs.Transactions { if expect := block.Transactions[i]; !bytes.Equal(otx, expect) { - return fmt.Errorf("transaction %d does not match. expected: %x. got: %x", i, expect, otx) + return fmt.Errorf("transaction %d does not match. expected: %v. got: %v", i, expect, otx) } } return nil diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index 0a8488b7eaf5..a4220ded4b18 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -155,6 +155,15 @@ func TestL2OutputSubmitter(t *testing.T) { initialSroTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{}) require.Nil(t, err) + // Wait until the second output submission from L2. The output submitter submits outputs from the + // unsafe portion of the chain which gets reorged on startup. The sequencer has an out of date view + // when it creates it's first block and uses and old L1 Origin. It then does not submit a batch + // 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.RollupConfig.BlockTime)*time.Second) + require.Nil(t, err) + // Wait for batch submitter to update L2 output oracle. timeoutCh := time.After(15 * time.Second) for { diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index a8e7449da38a..9e060ccc87d7 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -49,7 +49,7 @@ L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 11093) L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18793) L2OutputOracleTest:testCannot_deleteWrongL2Output() (gas: 77307) L2OutputOracleTest:test_appendingAnotherOutput() (gas: 68605) -L2OutputOracleTest:test_computeL2BlockNumber() (gas: 15003) +L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14755) L2OutputOracleTest:test_constructor() (gas: 33752) L2OutputOracleTest:test_deleteL2Output() (gas: 64320) L2OutputOracleTest:test_getL2Output() (gas: 74601) diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts/contracts/L1/L2OutputOracle.sol index c3703ce44d2c..a02d5a255b54 100644 --- a/packages/contracts/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts/contracts/L1/L2OutputOracle.sol @@ -198,7 +198,6 @@ contract L2OutputOracle is Ownable { unchecked { return HISTORICAL_TOTAL_BLOCKS + - 1 + ((_l2timestamp - STARTING_BLOCK_TIMESTAMP) / L2_BLOCK_TIME); } } diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index b012189c8cea..ece6719d8a06 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -70,17 +70,17 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { function test_computeL2BlockNumber() external { // Test with the timestamp of the very first appended block uint256 argTimestamp = startingBlockTimestamp; - uint256 expected = historicalTotalBlocks + 1; + uint256 expected = historicalTotalBlocks; assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); // Test with an integer multiple of the l2BlockTime argTimestamp = startingBlockTimestamp + 20; - expected = historicalTotalBlocks + 1 + (20 / l2BlockTime); + expected = historicalTotalBlocks + (20 / l2BlockTime); assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); // Test with a remainder argTimestamp = startingBlockTimestamp + 33; - expected = historicalTotalBlocks + 1 + (33 / l2BlockTime); + expected = historicalTotalBlocks + (33 / l2BlockTime); assertEq(oracle.computeL2BlockNumber(argTimestamp), expected); } From 92fccc27c5d84a52651d28feb19f92229e78d9f7 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Fri, 13 May 2022 11:16:45 -0700 Subject: [PATCH 576/585] opnode: Withdrawal E2E test in go (#423) This does the following: - Adds withdrawal utilities (to opnode/withdrawals) - Adds an end to end test in go of withdrawals - Adds the L2 withdrawer contract - Updates to a newer version of reference-go-ethereum Fixes ENG-2202 --- go.mod | 4 +- go.sum | 14 +- opnode/contracts/Makefile | 44 +- .../withdrawer/withdrawer_deployed.go | 5 + opnode/contracts/withdrawer/withdrawer_raw.go | 636 ++++++++++++++++++ opnode/test/geth.go | 1 + opnode/test/setup.go | 11 +- opnode/test/system_test.go | 197 ++++++ opnode/withdrawals/proof.go | 100 +++ opnode/withdrawals/utils.go | 266 ++++++++ 10 files changed, 1259 insertions(+), 19 deletions(-) create mode 100644 opnode/contracts/withdrawer/withdrawer_deployed.go create mode 100644 opnode/contracts/withdrawer/withdrawer_raw.go create mode 100644 opnode/withdrawals/proof.go create mode 100644 opnode/withdrawals/utils.go diff --git a/go.mod b/go.mod index 810faac0d8ee..adaf52484915 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/btcsuite/btcd/btcec/v2 v2.1.2 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cheekybits/genny v1.0.0 // indirect @@ -173,7 +173,7 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818 // For local debugging: // replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/go.sum b/go.sum index b3fcf12cfed1..0d5c50ae89bf 100644 --- a/go.sum +++ b/go.sum @@ -123,9 +123,10 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btcd/btcec/v2 v2.1.2 h1:YoYoC9J0jwfukodSBMzZYUVQ8PTiYg4BnOWiJVzTmLs= -github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= @@ -241,10 +242,11 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead h1:AiLggtwXHmAGxNusOEH7edb83TtJnavtR2uY1z6YzYc= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818 h1:oIqbYtUOntLsTfmbmOxj73nuQLkDHxp2KhNj+AWv32s= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -259,6 +261,7 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= @@ -557,6 +560,7 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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 v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 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= @@ -855,6 +859,7 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= 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= @@ -1411,6 +1416,7 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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= diff --git a/opnode/contracts/Makefile b/opnode/contracts/Makefile index 7b9e9becf4c5..afd8f2ad3b20 100644 --- a/opnode/contracts/Makefile +++ b/opnode/contracts/Makefile @@ -1,11 +1,14 @@ SHELL := /bin/bash - CONTRACTS_PATH := "../../packages/contracts/" -bindings: bindings-l1-block-info bindings-optimism-portal deployed-bin-l1-block-info deployed-bin-optimism-portal -# Split up b/c I don't know how to include this step in the L1 Block Info Bindings -# What is occuring is that the `temp` variable is hard to pull into the `eval` +all: bindings deployed + +bindings: bindings-l1-block-info bindings-optimism-portal bindings-L2ToL1MessagePasser +deployed: deployed-bin-l1-block-info deployed-bin-optimism-portal deployed-bin-L2ToL1MessagePasser + +# Deployed bindings are split because they depend on the bin file +# TODO: Can probably do this with recipes deployed-bin-l1-block-info: bindings-l1-block-info $(eval deployedBytecode := $(shell cat bin/l1block_deployed.hex)) echo "// Code generated - DO NOT EDIT." > l1block/l1_block_info_deployed.go @@ -14,8 +17,6 @@ deployed-bin-l1-block-info: bindings-l1-block-info echo "var L1blockDeployedBin = \"$(deployedBytecode)\"" >> l1block/l1_block_info_deployed.go gofmt -s -w l1block/l1_block_info_deployed.go -# Split up b/c I don't know how to include this step in the L1 Block Info Bindings -# What is occuring is that the `temp` variable is hard to pull into the `eval` deployed-bin-optimism-portal: bindings-optimism-portal $(eval deployedBytecode := $(shell cat bin/portal_deployed.hex)) echo "// Code generated - DO NOT EDIT." > deposit/optimism_portal_deployed.go @@ -24,11 +25,19 @@ deployed-bin-optimism-portal: bindings-optimism-portal echo "var OptimismPortalDeployedBin = \"$(deployedBytecode)\"" >> deposit/optimism_portal_deployed.go gofmt -s -w deposit/optimism_portal_deployed.go +deployed-bin-L2ToL1MessagePasser: bindings-L2ToL1MessagePasser + $(eval deployedBytecode := $(shell cat bin/l2_to_l1_message_passer.hex)) + echo "// Code generated - DO NOT EDIT." > withdrawer/withdrawer_deployed.go + echo "// This file is a generated binding and any manual changes will be lost." >> withdrawer/withdrawer_deployed.go + echo "package withdrawer" >> withdrawer/withdrawer_deployed.go + echo "var WithdrawerDeployedBin = \"$(deployedBytecode)\"" >> withdrawer/withdrawer_deployed.go + gofmt -s -w withdrawer/withdrawer_deployed.go + bindings-l1-block-info: $(eval temp := $(shell mktemp -d)) $(eval cwd := $(shell pwd)) mkdir -p bin - cd ../../packages/contracts; \ + cd $(CONTRACTS_PATH); \ forge build \ && forge inspect L1Block abi > $(temp)/L1Block.abi \ && forge inspect L1Block bytecode > $(temp)/L1Block.bin \ @@ -40,11 +49,29 @@ bindings-l1-block-info: --type L1Block \ --out ./l1block/l1_block_info_raw.go +bindings-L2ToL1MessagePasser: + $(eval temp := $(shell mktemp -d)) + $(eval cwd := $(shell pwd)) + mkdir -p bin + cd $(CONTRACTS_PATH); \ + forge build \ + && forge inspect L2ToL1MessagePasser abi > $(temp)/Withdrawer.abi \ + && forge inspect L2ToL1MessagePasser bytecode > $(temp)/Withdrawer.bin \ + && forge inspect L2ToL1MessagePasser deployedBytecode > $(cwd)/bin/l2_to_l1_message_passer.hex + abigen \ + --abi $(temp)/Withdrawer.abi \ + --bin $(temp)/Withdrawer.bin \ + --pkg withdrawer \ + --type Withdrawer \ + --out ./withdrawer/withdrawer_raw.go + + + bindings-optimism-portal: $(eval temp := $(shell mktemp -d)) $(eval cwd := $(shell pwd)) mkdir -p bin - cd ../../packages/contracts; \ + cd $(CONTRACTS_PATH); \ forge build \ && forge inspect OptimismPortal abi > $(temp)/OptimismPortal.abi \ && forge inspect OptimismPortal bytecode > $(temp)/OptimismPortal.bin \ @@ -55,3 +82,4 @@ bindings-optimism-portal: --pkg deposit \ --type OptimismPortal \ --out ./deposit/deposit_feed_raw.go + diff --git a/opnode/contracts/withdrawer/withdrawer_deployed.go b/opnode/contracts/withdrawer/withdrawer_deployed.go new file mode 100644 index 000000000000..ce0f048b865f --- /dev/null +++ b/opnode/contracts/withdrawer/withdrawer_deployed.go @@ -0,0 +1,5 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. +package withdrawer + +var WithdrawerDeployedBin = "0x6080604052600436106100435760003560e01c806344df8e701461006c57806382e3702d14610081578063affed0e0146100c6578063c2b3e5ac146100ea57600080fd5b366100675761006533620186a0604051806020016040528060008152506100f8565b005b600080fd5b34801561007857600080fd5b506100656101ae565b34801561008d57600080fd5b506100b161009c366004610256565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100dc60015481565b6040519081526020016100bd565b6100656100f836600461029e565b600061010a600154338634878761020b565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136906101989034908990899061040d565b60405180910390a4505060018054810190555050565b604051479081906101be9061024a565b6040518091039082f09050801580156101db573d6000803e3d6000fd5b505060405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b600086868686868660405160200161022896959493929190610435565b6040516020818303038152906040528051906020012090509695505050505050565b60088061048d83390190565b60006020828403121561026857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156102b357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146102d757600080fd5b925060208401359150604084013567ffffffffffffffff808211156102fb57600080fd5b818601915086601f83011261030f57600080fd5b8135818111156103215761032161026f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156103675761036761026f565b8160405282815289602084870101111561038057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b818110156103c8576020818501810151868301820152016103ac565b818111156103da576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b83815282602082015260606040820152600061042c60608301846103a2565b95945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261048060c08301846103a2565b9897505050505050505056fe608060405230fffea164736f6c634300080a000a" diff --git a/opnode/contracts/withdrawer/withdrawer_raw.go b/opnode/contracts/withdrawer/withdrawer_raw.go new file mode 100644 index 000000000000..691377e17818 --- /dev/null +++ b/opnode/contracts/withdrawer/withdrawer_raw.go @@ -0,0 +1,636 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package withdrawer + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// WithdrawerMetaData contains all meta data concerning the Withdrawer contract. +var WithdrawerMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"WithdrawalInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrawerBalanceBurnt\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"initiateWithdrawal\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"sentMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x608060405234801561001057600080fd5b506104a1806100206000396000f3fe6080604052600436106100435760003560e01c806344df8e701461006c57806382e3702d14610081578063affed0e0146100c6578063c2b3e5ac146100ea57600080fd5b366100675761006533620186a0604051806020016040528060008152506100f8565b005b600080fd5b34801561007857600080fd5b506100656101ae565b34801561008d57600080fd5b506100b161009c366004610256565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100dc60015481565b6040519081526020016100bd565b6100656100f836600461029e565b600061010a600154338634878761020b565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136906101989034908990899061040d565b60405180910390a4505060018054810190555050565b604051479081906101be9061024a565b6040518091039082f09050801580156101db573d6000803e3d6000fd5b505060405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b600086868686868660405160200161022896959493929190610435565b6040516020818303038152906040528051906020012090509695505050505050565b60088061048d83390190565b60006020828403121561026857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156102b357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146102d757600080fd5b925060208401359150604084013567ffffffffffffffff808211156102fb57600080fd5b818601915086601f83011261030f57600080fd5b8135818111156103215761032161026f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156103675761036761026f565b8160405282815289602084870101111561038057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b818110156103c8576020818501810151868301820152016103ac565b818111156103da576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b83815282602082015260606040820152600061042c60608301846103a2565b95945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261048060c08301846103a2565b9897505050505050505056fe608060405230fffea164736f6c634300080a000a", +} + +// WithdrawerABI is the input ABI used to generate the binding from. +// Deprecated: Use WithdrawerMetaData.ABI instead. +var WithdrawerABI = WithdrawerMetaData.ABI + +// WithdrawerBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use WithdrawerMetaData.Bin instead. +var WithdrawerBin = WithdrawerMetaData.Bin + +// DeployWithdrawer deploys a new Ethereum contract, binding an instance of Withdrawer to it. +func DeployWithdrawer(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Withdrawer, error) { + parsed, err := WithdrawerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(WithdrawerBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Withdrawer{WithdrawerCaller: WithdrawerCaller{contract: contract}, WithdrawerTransactor: WithdrawerTransactor{contract: contract}, WithdrawerFilterer: WithdrawerFilterer{contract: contract}}, nil +} + +// Withdrawer is an auto generated Go binding around an Ethereum contract. +type Withdrawer struct { + WithdrawerCaller // Read-only binding to the contract + WithdrawerTransactor // Write-only binding to the contract + WithdrawerFilterer // Log filterer for contract events +} + +// WithdrawerCaller is an auto generated read-only Go binding around an Ethereum contract. +type WithdrawerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type WithdrawerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type WithdrawerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// WithdrawerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type WithdrawerSession struct { + Contract *Withdrawer // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WithdrawerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type WithdrawerCallerSession struct { + Contract *WithdrawerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// WithdrawerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type WithdrawerTransactorSession struct { + Contract *WithdrawerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// WithdrawerRaw is an auto generated low-level Go binding around an Ethereum contract. +type WithdrawerRaw struct { + Contract *Withdrawer // Generic contract binding to access the raw methods on +} + +// WithdrawerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type WithdrawerCallerRaw struct { + Contract *WithdrawerCaller // Generic read-only contract binding to access the raw methods on +} + +// WithdrawerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type WithdrawerTransactorRaw struct { + Contract *WithdrawerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewWithdrawer creates a new instance of Withdrawer, bound to a specific deployed contract. +func NewWithdrawer(address common.Address, backend bind.ContractBackend) (*Withdrawer, error) { + contract, err := bindWithdrawer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Withdrawer{WithdrawerCaller: WithdrawerCaller{contract: contract}, WithdrawerTransactor: WithdrawerTransactor{contract: contract}, WithdrawerFilterer: WithdrawerFilterer{contract: contract}}, nil +} + +// NewWithdrawerCaller creates a new read-only instance of Withdrawer, bound to a specific deployed contract. +func NewWithdrawerCaller(address common.Address, caller bind.ContractCaller) (*WithdrawerCaller, error) { + contract, err := bindWithdrawer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &WithdrawerCaller{contract: contract}, nil +} + +// NewWithdrawerTransactor creates a new write-only instance of Withdrawer, bound to a specific deployed contract. +func NewWithdrawerTransactor(address common.Address, transactor bind.ContractTransactor) (*WithdrawerTransactor, error) { + contract, err := bindWithdrawer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &WithdrawerTransactor{contract: contract}, nil +} + +// NewWithdrawerFilterer creates a new log filterer instance of Withdrawer, bound to a specific deployed contract. +func NewWithdrawerFilterer(address common.Address, filterer bind.ContractFilterer) (*WithdrawerFilterer, error) { + contract, err := bindWithdrawer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &WithdrawerFilterer{contract: contract}, nil +} + +// bindWithdrawer binds a generic wrapper to an already deployed contract. +func bindWithdrawer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(WithdrawerABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Withdrawer *WithdrawerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Withdrawer.Contract.WithdrawerCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Withdrawer *WithdrawerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Withdrawer.Contract.WithdrawerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Withdrawer *WithdrawerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Withdrawer.Contract.WithdrawerTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Withdrawer *WithdrawerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Withdrawer.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Withdrawer *WithdrawerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Withdrawer.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Withdrawer *WithdrawerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Withdrawer.Contract.contract.Transact(opts, method, params...) +} + +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// +// Solidity: function nonce() view returns(uint256) +func (_Withdrawer *WithdrawerCaller) Nonce(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Withdrawer.contract.Call(opts, &out, "nonce") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// +// Solidity: function nonce() view returns(uint256) +func (_Withdrawer *WithdrawerSession) Nonce() (*big.Int, error) { + return _Withdrawer.Contract.Nonce(&_Withdrawer.CallOpts) +} + +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// +// Solidity: function nonce() view returns(uint256) +func (_Withdrawer *WithdrawerCallerSession) Nonce() (*big.Int, error) { + return _Withdrawer.Contract.Nonce(&_Withdrawer.CallOpts) +} + +// SentMessages is a free data retrieval call binding the contract method 0x82e3702d. +// +// Solidity: function sentMessages(bytes32 ) view returns(bool) +func (_Withdrawer *WithdrawerCaller) SentMessages(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _Withdrawer.contract.Call(opts, &out, "sentMessages", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SentMessages is a free data retrieval call binding the contract method 0x82e3702d. +// +// Solidity: function sentMessages(bytes32 ) view returns(bool) +func (_Withdrawer *WithdrawerSession) SentMessages(arg0 [32]byte) (bool, error) { + return _Withdrawer.Contract.SentMessages(&_Withdrawer.CallOpts, arg0) +} + +// SentMessages is a free data retrieval call binding the contract method 0x82e3702d. +// +// Solidity: function sentMessages(bytes32 ) view returns(bool) +func (_Withdrawer *WithdrawerCallerSession) SentMessages(arg0 [32]byte) (bool, error) { + return _Withdrawer.Contract.SentMessages(&_Withdrawer.CallOpts, arg0) +} + +// Burn is a paid mutator transaction binding the contract method 0x44df8e70. +// +// Solidity: function burn() returns() +func (_Withdrawer *WithdrawerTransactor) Burn(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Withdrawer.contract.Transact(opts, "burn") +} + +// Burn is a paid mutator transaction binding the contract method 0x44df8e70. +// +// Solidity: function burn() returns() +func (_Withdrawer *WithdrawerSession) Burn() (*types.Transaction, error) { + return _Withdrawer.Contract.Burn(&_Withdrawer.TransactOpts) +} + +// Burn is a paid mutator transaction binding the contract method 0x44df8e70. +// +// Solidity: function burn() returns() +func (_Withdrawer *WithdrawerTransactorSession) Burn() (*types.Transaction, error) { + return _Withdrawer.Contract.Burn(&_Withdrawer.TransactOpts) +} + +// InitiateWithdrawal is a paid mutator transaction binding the contract method 0xc2b3e5ac. +// +// Solidity: function initiateWithdrawal(address _target, uint256 _gasLimit, bytes _data) payable returns() +func (_Withdrawer *WithdrawerTransactor) InitiateWithdrawal(opts *bind.TransactOpts, _target common.Address, _gasLimit *big.Int, _data []byte) (*types.Transaction, error) { + return _Withdrawer.contract.Transact(opts, "initiateWithdrawal", _target, _gasLimit, _data) +} + +// InitiateWithdrawal is a paid mutator transaction binding the contract method 0xc2b3e5ac. +// +// Solidity: function initiateWithdrawal(address _target, uint256 _gasLimit, bytes _data) payable returns() +func (_Withdrawer *WithdrawerSession) InitiateWithdrawal(_target common.Address, _gasLimit *big.Int, _data []byte) (*types.Transaction, error) { + return _Withdrawer.Contract.InitiateWithdrawal(&_Withdrawer.TransactOpts, _target, _gasLimit, _data) +} + +// InitiateWithdrawal is a paid mutator transaction binding the contract method 0xc2b3e5ac. +// +// Solidity: function initiateWithdrawal(address _target, uint256 _gasLimit, bytes _data) payable returns() +func (_Withdrawer *WithdrawerTransactorSession) InitiateWithdrawal(_target common.Address, _gasLimit *big.Int, _data []byte) (*types.Transaction, error) { + return _Withdrawer.Contract.InitiateWithdrawal(&_Withdrawer.TransactOpts, _target, _gasLimit, _data) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Withdrawer *WithdrawerTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Withdrawer.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Withdrawer *WithdrawerSession) Receive() (*types.Transaction, error) { + return _Withdrawer.Contract.Receive(&_Withdrawer.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Withdrawer *WithdrawerTransactorSession) Receive() (*types.Transaction, error) { + return _Withdrawer.Contract.Receive(&_Withdrawer.TransactOpts) +} + +// WithdrawerWithdrawalInitiatedIterator is returned from FilterWithdrawalInitiated and is used to iterate over the raw logs and unpacked data for WithdrawalInitiated events raised by the Withdrawer contract. +type WithdrawerWithdrawalInitiatedIterator struct { + Event *WithdrawerWithdrawalInitiated // 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 *WithdrawerWithdrawalInitiatedIterator) 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(WithdrawerWithdrawalInitiated) + 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(WithdrawerWithdrawalInitiated) + 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 *WithdrawerWithdrawalInitiatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *WithdrawerWithdrawalInitiatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// WithdrawerWithdrawalInitiated represents a WithdrawalInitiated event raised by the Withdrawer contract. +type WithdrawerWithdrawalInitiated struct { + Nonce *big.Int + Sender common.Address + Target common.Address + Value *big.Int + GasLimit *big.Int + Data []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawalInitiated is a free log retrieval operation binding the contract event 0x87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136. +// +// Solidity: event WithdrawalInitiated(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) +func (_Withdrawer *WithdrawerFilterer) FilterWithdrawalInitiated(opts *bind.FilterOpts, nonce []*big.Int, sender []common.Address, target []common.Address) (*WithdrawerWithdrawalInitiatedIterator, error) { + + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var targetRule []interface{} + for _, targetItem := range target { + targetRule = append(targetRule, targetItem) + } + + logs, sub, err := _Withdrawer.contract.FilterLogs(opts, "WithdrawalInitiated", nonceRule, senderRule, targetRule) + if err != nil { + return nil, err + } + return &WithdrawerWithdrawalInitiatedIterator{contract: _Withdrawer.contract, event: "WithdrawalInitiated", logs: logs, sub: sub}, nil +} + +// WatchWithdrawalInitiated is a free log subscription operation binding the contract event 0x87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136. +// +// Solidity: event WithdrawalInitiated(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) +func (_Withdrawer *WithdrawerFilterer) WatchWithdrawalInitiated(opts *bind.WatchOpts, sink chan<- *WithdrawerWithdrawalInitiated, nonce []*big.Int, sender []common.Address, target []common.Address) (event.Subscription, error) { + + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var targetRule []interface{} + for _, targetItem := range target { + targetRule = append(targetRule, targetItem) + } + + logs, sub, err := _Withdrawer.contract.WatchLogs(opts, "WithdrawalInitiated", nonceRule, senderRule, targetRule) + 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(WithdrawerWithdrawalInitiated) + if err := _Withdrawer.contract.UnpackLog(event, "WithdrawalInitiated", 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 +} + +// ParseWithdrawalInitiated is a log parse operation binding the contract event 0x87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136. +// +// Solidity: event WithdrawalInitiated(uint256 indexed nonce, address indexed sender, address indexed target, uint256 value, uint256 gasLimit, bytes data) +func (_Withdrawer *WithdrawerFilterer) ParseWithdrawalInitiated(log types.Log) (*WithdrawerWithdrawalInitiated, error) { + event := new(WithdrawerWithdrawalInitiated) + if err := _Withdrawer.contract.UnpackLog(event, "WithdrawalInitiated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// WithdrawerWithdrawerBalanceBurntIterator is returned from FilterWithdrawerBalanceBurnt and is used to iterate over the raw logs and unpacked data for WithdrawerBalanceBurnt events raised by the Withdrawer contract. +type WithdrawerWithdrawerBalanceBurntIterator struct { + Event *WithdrawerWithdrawerBalanceBurnt // 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 *WithdrawerWithdrawerBalanceBurntIterator) 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(WithdrawerWithdrawerBalanceBurnt) + 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(WithdrawerWithdrawerBalanceBurnt) + 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 *WithdrawerWithdrawerBalanceBurntIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *WithdrawerWithdrawerBalanceBurntIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// WithdrawerWithdrawerBalanceBurnt represents a WithdrawerBalanceBurnt event raised by the Withdrawer contract. +type WithdrawerWithdrawerBalanceBurnt struct { + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawerBalanceBurnt is a free log retrieval operation binding the contract event 0x7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f. +// +// Solidity: event WithdrawerBalanceBurnt(uint256 indexed amount) +func (_Withdrawer *WithdrawerFilterer) FilterWithdrawerBalanceBurnt(opts *bind.FilterOpts, amount []*big.Int) (*WithdrawerWithdrawerBalanceBurntIterator, error) { + + var amountRule []interface{} + for _, amountItem := range amount { + amountRule = append(amountRule, amountItem) + } + + logs, sub, err := _Withdrawer.contract.FilterLogs(opts, "WithdrawerBalanceBurnt", amountRule) + if err != nil { + return nil, err + } + return &WithdrawerWithdrawerBalanceBurntIterator{contract: _Withdrawer.contract, event: "WithdrawerBalanceBurnt", logs: logs, sub: sub}, nil +} + +// WatchWithdrawerBalanceBurnt is a free log subscription operation binding the contract event 0x7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f. +// +// Solidity: event WithdrawerBalanceBurnt(uint256 indexed amount) +func (_Withdrawer *WithdrawerFilterer) WatchWithdrawerBalanceBurnt(opts *bind.WatchOpts, sink chan<- *WithdrawerWithdrawerBalanceBurnt, amount []*big.Int) (event.Subscription, error) { + + var amountRule []interface{} + for _, amountItem := range amount { + amountRule = append(amountRule, amountItem) + } + + logs, sub, err := _Withdrawer.contract.WatchLogs(opts, "WithdrawerBalanceBurnt", amountRule) + 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(WithdrawerWithdrawerBalanceBurnt) + if err := _Withdrawer.contract.UnpackLog(event, "WithdrawerBalanceBurnt", 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 +} + +// ParseWithdrawerBalanceBurnt is a log parse operation binding the contract event 0x7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f. +// +// Solidity: event WithdrawerBalanceBurnt(uint256 indexed amount) +func (_Withdrawer *WithdrawerFilterer) ParseWithdrawerBalanceBurnt(log types.Log) (*WithdrawerWithdrawerBalanceBurnt, error) { + event := new(WithdrawerWithdrawerBalanceBurnt) + if err := _Withdrawer.contract.UnpackLog(event, "WithdrawerBalanceBurnt", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/opnode/test/geth.go b/opnode/test/geth.go index 31e4c1a67cf8..4281af900cb2 100644 --- a/opnode/test/geth.go +++ b/opnode/test/geth.go @@ -134,6 +134,7 @@ func initL2Geth(name, addr string, l2ChainID *big.Int, genesis *core.Genesis) (* // 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) (*node.Node, *eth.Ethereum, error) { + ethCfg.NoPruning = true // force everything to be an archive node n, err := node.New(nodeCfg) if err != nil { n.Close() diff --git a/opnode/test/setup.go b/opnode/test/setup.go index db2a96ab1bbc..32a4025597cb 100644 --- a/opnode/test/setup.go +++ b/opnode/test/setup.go @@ -12,14 +12,14 @@ import ( "github.com/ethereum-optimism/optimistic-specs/bss" "github.com/ethereum-optimism/optimistic-specs/l2os" "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" - mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/withdrawer" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -31,7 +31,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" - + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" hdwallet "github.com/miguelmota/go-ethereum-hdwallet" ) @@ -234,7 +234,7 @@ func (cfg SystemConfig) start() (*System, error) { } l2Alloc[cfg.L1InfoPredeployAddress] = core.GenesisAccount{Code: common.FromHex(l1block.L1blockDeployedBin), Balance: common.Big0} - l2Alloc[predeploy.WithdrawalContractAddress] = core.GenesisAccount{Code: []byte{}, Balance: common.Big0} + l2Alloc[predeploy.WithdrawalContractAddress] = core.GenesisAccount{Code: common.FromHex(withdrawer.WithdrawerDeployedBin), Balance: common.Big0} genesisTimestamp := uint64(time.Now().Unix()) @@ -407,6 +407,7 @@ func (cfg SystemConfig) start() (*System, error) { if err != nil { return nil, err } + _, err = waitForTransaction(tx.Hash(), l1Client, time.Duration(cfg.L1BlockTime)*time.Second*2) if err != nil { return nil, fmt.Errorf("waiting for OptimismPortal: %w", err) diff --git a/opnode/test/system_test.go b/opnode/test/system_test.go index b04b87754cad..84ad9c5d1efb 100644 --- a/opnode/test/system_test.go +++ b/opnode/test/system_test.go @@ -12,12 +12,15 @@ import ( "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/withdrawer" "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" "github.com/ethereum-optimism/optimistic-specs/opnode/l2" "github.com/ethereum-optimism/optimistic-specs/opnode/node" rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimistic-specs/opnode/withdrawals" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" @@ -25,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" @@ -641,3 +645,196 @@ func TestL1InfoContract(t *testing.T) { checkInfoList("On verifier with state", l1InfosFromVerifierState) } + +// calcGasFees determines the actual cost of the transaction given a specific basefee +func calcGasFees(gasUsed uint64, gasTipCap *big.Int, gasFeeCap *big.Int, baseFee *big.Int) *big.Int { + x := new(big.Int).Add(gasTipCap, baseFee) + // If tip + basefee > gas fee cap, clamp it to the gas fee cap + if x.Cmp(gasFeeCap) > 0 { + x = gasFeeCap + } + return x.Mul(x, new(big.Int).SetUint64(gasUsed)) +} + +// TestWithdrawals checks that a deposit and then withdrawal execution succeeds. It verifies the +// balance changes on L1 and L2 and has to include gas fees in the balance checks. +// It does not check that the withdrawal can be executed prior to the end of the finality period. +func TestWithdrawals(t *testing.T) { + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } + + cfg := defaultSystemConfig(t) + cfg.DepositCFG.FinalizationPeriod = big.NewInt(2) // 2s finalization period + + sys, err := cfg.start() + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + l2Seq := sys.Clients["sequencer"] + l2Verif := sys.Clients["verifier"] + + // Transactor Account + ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: transactorHDPath, + }, + }) + require.Nil(t, err) + fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey) + + // Find deposit contract + depositContract, err := deposit.NewOptimismPortal(sys.DepositContractAddr, l1Client) + require.Nil(t, err) + + // Create L1 signer + opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainID) + require.Nil(t, err) + + // Start L2 balance + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + // Finally send TX + mintAmount := big.NewInt(1_000_000_000_000) + opts.Value = mintAmount + tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, 1_000_000, false, nil) + require.Nil(t, err, "with deposit tx") + + receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) + require.Nil(t, err, "Waiting for deposit tx on L1") + + // Bind L2 Withdrawer Contract + l2withdrawer, err := withdrawer.NewWithdrawer(predeploy.WithdrawalContractAddress, l2Seq) + require.Nil(t, err, "binding withdrawer on L2") + + // Wait for deposit to arrive + reconstructedDep, err := derive.UnmarshalLogEvent(receipt.Logs[0]) + require.NoError(t, err, "Could not reconstruct L2 Deposit") + tx = types.NewTx(reconstructedDep) + receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second) + require.NoError(t, err) + require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) + + // Confirm L2 balance + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + endBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + diff := new(big.Int) + diff = diff.Sub(endBalance, startBalance) + require.Equal(t, mintAmount, diff, "Did not get expected balance change after mint") + + // Start L2 balance for withdrawal + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + startBalance, err = l2Seq.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + // Intiate Withdrawal + withdrawAmount := big.NewInt(500_000_000_000) + l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainID) + require.Nil(t, err) + l2opts.Value = withdrawAmount + tx, err = l2withdrawer.InitiateWithdrawal(l2opts, fromAddr, big.NewInt(21000), nil) + require.Nil(t, err, "sending initiate withdraw tx") + + receipt, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second) + require.Nil(t, err, "withdrawal initiated on L2 sequencer") + require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") + + // Verify L2 balance after withdrawal + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + header, err := l2Seq.HeaderByNumber(ctx, receipt.BlockNumber) + require.Nil(t, err) + + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + endBalance, err = l2Seq.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + // Take fee into account + diff = new(big.Int).Sub(startBalance, endBalance) + fees := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + diff = diff.Sub(diff, fees) + require.Equal(t, withdrawAmount, diff) + + // Take start balance on L1 + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + startBalance, err = l1Client.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + // Wait for finalization and then create the Finalized Withdrawal Transaction + l2OutputOracle, err := l2oo.NewL2OutputOracleCaller(sys.L2OOContractAddr, l1Client) + require.Nil(t, err) + + ctx, cancel = context.WithTimeout(context.Background(), 10*time.Duration(cfg.L1BlockTime)*time.Second) + defer cancel() + timestamp, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, sys.DepositContractAddr, header.Time) + require.Nil(t, err) + + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + blockNumber, err := l2OutputOracle.ComputeL2BlockNumber(&bind.CallOpts{Context: ctx}, new(big.Int).SetUint64(timestamp)) + require.Nil(t, err) + + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + header, err = l2Seq.HeaderByNumber(ctx, blockNumber) + require.Nil(t, err) + + rpc, err := rpc.Dial(cfg.Nodes["sequencer"].L2NodeAddr) + require.Nil(t, err) + l2client := withdrawals.NewClient(rpc) + + // Now create withdrawal + params, err := withdrawals.FinalizeWithdrawalParameters(context.Background(), l2client, tx.Hash(), header) + require.Nil(t, err) + + portal, err := deposit.NewOptimismPortal(sys.DepositContractAddr, l1Client) + require.Nil(t, err) + + opts.Value = nil + tx, err = portal.FinalizeWithdrawalTransaction( + opts, + params.Nonce, + params.Sender, + params.Target, + params.Value, + params.GasLimit, + params.Data, + params.Timestamp, + params.OutputRootProof, + params.WithdrawalProof, + ) + + require.Nil(t, err) + + receipt, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second) + require.Nil(t, err, "finalize withdrawal") + require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) + + // Verify balance after withdrawal + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + header, err = l1Client.HeaderByNumber(ctx, receipt.BlockNumber) + require.Nil(t, err) + + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + endBalance, err = l1Client.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + // Ensure that withdrawal - gas fees are added to the L1 balance + // Fun fact, the fee is greater than the withdrawal amount + diff = new(big.Int).Sub(endBalance, startBalance) + fees = calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + withdrawAmount = withdrawAmount.Sub(withdrawAmount, fees) + require.Equal(t, withdrawAmount, diff) +} diff --git a/opnode/withdrawals/proof.go b/opnode/withdrawals/proof.go new file mode 100644 index 000000000000..070282aa5b33 --- /dev/null +++ b/opnode/withdrawals/proof.go @@ -0,0 +1,100 @@ +package withdrawals + +import ( + "bytes" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient/gethclient" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +type proofDB struct { + m map[string][]byte +} + +func (p *proofDB) Has(key []byte) (bool, error) { + _, ok := p.m[string(key)] + return ok, nil +} + +func (p *proofDB) Get(key []byte) ([]byte, error) { + v, ok := p.m[string(key)] + if !ok { + return nil, errors.New("not found") + } + return v, nil +} + +func GenerateProofDB(proof []string) *proofDB { + p := proofDB{m: make(map[string][]byte)} + for _, s := range proof { + value := common.FromHex(s) + key := crypto.Keccak256(value) + p.m[string(key)] = value + } + return &p +} + +func VerifyAccountProof(root common.Hash, address common.Address, account types.StateAccount, proof []string) error { + expected, err := rlp.EncodeToBytes(&account) + if err != nil { + return fmt.Errorf("failed to encode rlp: %w", err) + } + secureKey := crypto.Keccak256(address[:]) + db := GenerateProofDB(proof) + value, err := trie.VerifyProof(root, secureKey, db) + if err != nil { + return fmt.Errorf("failed to verify proof: %w", err) + } + + if bytes.Equal(value, expected) { + return nil + } else { + return errors.New("proved value is not the same as the expected value") + } +} + +func VerifyStorageProof(root common.Hash, proof gethclient.StorageResult) error { + secureKey := crypto.Keccak256(common.FromHex(proof.Key)) + db := GenerateProofDB(proof.Proof) + value, err := trie.VerifyProof(root, secureKey, db) + if err != nil { + return fmt.Errorf("failed to verify proof: %w", err) + } + + expected := proof.Value.Bytes() + if bytes.Equal(value, expected) { + return nil + } else { + return errors.New("proved value is not the same as the expected value") + } +} + +func VerifyProof(stateRoot common.Hash, proof *gethclient.AccountResult) error { + err := VerifyAccountProof( + stateRoot, + proof.Address, + types.StateAccount{ + Nonce: proof.Nonce, + Balance: proof.Balance, + Root: proof.StorageHash, + CodeHash: proof.CodeHash[:], + }, + proof.AccountProof, + ) + if err != nil { + return fmt.Errorf("failed to validate account: %w", err) + } + for i, storageProof := range proof.StorageProof { + err = VerifyStorageProof(proof.StorageHash, storageProof) + if err != nil { + return fmt.Errorf("failed to validate storage proof %d: %w", i, err) + } + } + return nil +} diff --git a/opnode/withdrawals/utils.go b/opnode/withdrawals/utils.go new file mode 100644 index 000000000000..9fc475a348cb --- /dev/null +++ b/opnode/withdrawals/utils.go @@ -0,0 +1,266 @@ +package withdrawals + +import ( + "context" + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" + "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/withdrawer" + "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethclient/gethclient" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" +) + +// WaitForFinalizationPeriod waits until the timestamp has been submitted to the L2 Output Oracle on L1 and +// then waits for the finalization period to be up. +// This functions polls and can block for a very long time if used on mainnet. +// This returns the timestamp to use for the proof generation. +func WaitForFinalizationPeriod(ctx context.Context, client *ethclient.Client, portalAddr common.Address, timestamp uint64) (uint64, error) { + opts := &bind.CallOpts{Context: ctx} + timestampBig := new(big.Int).SetUint64(timestamp) + + portal, err := deposit.NewOptimismPortalCaller(portalAddr, client) + if err != nil { + return 0, err + } + l2OOAddress, err := portal.L2ORACLE(opts) + if err != nil { + return 0, err + } + l2OO, err := l2oo.NewL2OutputOracleCaller(l2OOAddress, client) + if err != nil { + return 0, err + } + + finalizationPeriod, err := portal.FINALIZATIONPERIOD(opts) + if err != nil { + return 0, err + } + + next, err := l2OO.LatestBlockTimestamp(opts) + if err != nil { + return 0, err + } + + // Now poll + var ticker *time.Ticker + diff := new(big.Int).Sub(timestampBig, next) + if diff.Cmp(big.NewInt(60)) > 0 { + ticker = time.NewTicker(time.Minute) + } else { + ticker = time.NewTicker(time.Second) + } + +loop: + for { + select { + case <-ticker.C: + next, err = l2OO.LatestBlockTimestamp(opts) + if err != nil { + return 0, err + } + // Already passed next + if next.Cmp(timestampBig) > 0 { + break loop + } + case <-ctx.Done(): + return 0, ctx.Err() + } + } + + // Now wait for it to be finalized + output, err := l2OO.GetL2Output(opts, next) + if err != nil { + return 0, err + } + targetTimestamp := new(big.Int).Add(output.Timestamp, finalizationPeriod) + targetTime := time.Unix(targetTimestamp.Int64(), 0) + // Assume clock is relatively correct + time.Sleep(time.Until(targetTime)) + // Poll for L1 Block to have a time greater than the target time + ticker = time.NewTicker(time.Second) + for { + select { + case <-ticker.C: + header, err := client.HeaderByNumber(ctx, nil) + if err != nil { + return 0, err + } + if header.Time > targetTimestamp.Uint64() { + return next.Uint64(), nil + } + case <-ctx.Done(): + return 0, ctx.Err() + } + } + +} + +type ProofClient interface { + TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) + GetProof(context.Context, common.Address, []string, *big.Int) (*gethclient.AccountResult, error) +} + +type ec = *ethclient.Client +type gc = *gethclient.Client + +type Client struct { + ec + gc +} + +// Ensure that ProofClient and Client interfaces are valid +var _ ProofClient = Client{} + +// NewClient wraps a RPC client with both ethclient and gethclient methods. +// Implements ProofClient +func NewClient(client *rpc.Client) *Client { + return &Client{ + ethclient.NewClient(client), + gethclient.New(client), + } + +} + +// FinalizedWithdrawalParameters is the set of paramets to pass to the FinalizedWithdrawal function +type FinalizedWithdrawalParameters struct { + Nonce *big.Int + Sender common.Address + Target common.Address + Value *big.Int + GasLimit *big.Int + Timestamp *big.Int + Data []byte + OutputRootProof deposit.WithdrawalVerifierOutputRootProof + WithdrawalProof []byte // RLP Encoded list of trie nodes to prove L2 storage +} + +// FinalizeWithdrawalParameters queries L2 to generate all withdrawal parameters and proof necessary to finalize an withdrawal on L1. +// The header provided is very imporant. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle +// contract. If not, the withdrawal will fail as it the storage proof cannot be verified if there is no submitted state root. +func FinalizeWithdrawalParameters(ctx context.Context, l2client ProofClient, txHash common.Hash, header *types.Header) (FinalizedWithdrawalParameters, error) { + // Transaction receipt + receipt, err := l2client.TransactionReceipt(ctx, txHash) + if err != nil { + return FinalizedWithdrawalParameters{}, err + } + // Parse the receipt + ev, err := ParseWithdrawalInitiated(receipt) + if err != nil { + return FinalizedWithdrawalParameters{}, err + } + // Generate then verify the withdrawal proof + withdrawalHash, err := WithdrawalHash(ev) + if err != nil { + return FinalizedWithdrawalParameters{}, err + } + slot := StorageSlotOfWithdrawalHash(withdrawalHash) + p, err := l2client.GetProof(ctx, predeploy.WithdrawalContractAddress, []string{slot.String()}, header.Number) + if err != nil { + return FinalizedWithdrawalParameters{}, err + } + // TODO: Could skip this step, but it's nice to double check it + err = VerifyProof(header.Root, p) + if err != nil { + return FinalizedWithdrawalParameters{}, err + } + if len(p.StorageProof) != 1 { + return FinalizedWithdrawalParameters{}, errors.New("invalid amount of storage proofs") + } + + // Encode it as expected by the contract + trieNodes := make([][]byte, len(p.StorageProof[0].Proof)) + for i, s := range p.StorageProof[0].Proof { + trieNodes[i] = common.FromHex(s) + } + + withdrawalProof, err := rlp.EncodeToBytes(trieNodes) + if err != nil { + return FinalizedWithdrawalParameters{}, err + } + + return FinalizedWithdrawalParameters{ + Nonce: ev.Nonce, + Sender: ev.Sender, + Target: ev.Target, + Value: ev.Value, + GasLimit: ev.GasLimit, + Timestamp: new(big.Int).SetUint64(header.Time), + Data: ev.Data, + OutputRootProof: deposit.WithdrawalVerifierOutputRootProof{ + Version: [32]byte{}, // Empty for version 1 + StateRoot: header.Root, + WithdrawerStorageRoot: p.StorageHash, + LatestBlockhash: header.Hash(), + }, + WithdrawalProof: withdrawalProof, + }, nil +} + +// Standard ABI types copied from golang ABI tests +var ( + Uint256Type, _ = abi.NewType("uint256", "", nil) + BytesType, _ = abi.NewType("bytes", "", nil) + AddressType, _ = abi.NewType("address", "", nil) +) + +// WithdrawalHash computes the hash of the withdrawal that was stored in the L2 withdrawal contract state. +// TODO: +// - I don't like having to use the ABI Generated struct +// - There should be a better way to run the ABI encoding +// - These needs to be fuzzed against the solidity +func WithdrawalHash(ev *withdrawer.WithdrawerWithdrawalInitiated) (common.Hash, error) { + // abi.encode(nonce, msg.sender, _target, msg.value, _gasLimit, _data) + args := abi.Arguments{ + {Name: "nonce", Type: Uint256Type}, + {Name: "sender", Type: AddressType}, + {Name: "target", Type: AddressType}, + {Name: "value", Type: Uint256Type}, + {Name: "gasLimit", Type: Uint256Type}, + {Name: "data", Type: BytesType}, + } + enc, err := args.Pack(ev.Nonce, ev.Sender, ev.Target, ev.Value, ev.GasLimit, ev.Data) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to pack for withdrawal hash: %w", err) + } + return crypto.Keccak256Hash(enc), nil +} + +// ParseWithdrawalInitiated parses +func ParseWithdrawalInitiated(receipt *types.Receipt) (*withdrawer.WithdrawerWithdrawalInitiated, error) { + contract, err := withdrawer.NewWithdrawer(common.Address{}, nil) + if err != nil { + return nil, err + } + if len(receipt.Logs) != 1 { + return nil, errors.New("invalid length of logs") + } + ev, err := contract.ParseWithdrawalInitiated(*receipt.Logs[0]) + if err != nil { + return nil, fmt.Errorf("failed to parse log: %w", err) + } + return ev, nil +} + +// StorageSlotOfWithdrawalHash determines the storage slot of the Withdrawer contract to look at +// given a WithdrawalHash +func StorageSlotOfWithdrawalHash(hash common.Hash) common.Hash { + // The withdrawals mapping is the second (0 indexed) storage element in the Withdrawer contract. + // To determine the storage slot, use keccak256(withdrawalHash ++ p) + // Where p is the 32 byte value of the storage slot and ++ is concatenation + buf := make([]byte, 64) + copy(buf, hash[:]) + buf[63] = 1 + return crypto.Keccak256Hash(buf) +} From b37e6587f0a16989126dd0c8b18b2148d87d010d Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 13 May 2022 16:02:35 -0600 Subject: [PATCH 577/585] Adopt go.work, rename modules to prep for monorepo (#441) Co-Authored-By: Matthew Slipper Co-authored-by: protolambda --- .circleci/config.yml | 23 +- .github/workflows/go-ci.yml | 63 +- .github/workflows/markdown-ci.yml | 2 +- .gitignore | 2 + Makefile | 39 +- go.work | 13 + go.work.sum | 9 + meta/linting.md | 6 +- meta/releases.md | 6 +- op-batcher/Makefile | 26 + {bss => op-batcher}/batch_submitter.go | 16 +- {bss/cmd/bss => op-batcher/cmd}/main.go | 8 +- {bss => op-batcher}/config.go | 4 +- {bss => op-batcher}/db/history_db.go | 2 +- {bss => op-batcher}/db/history_db_test.go | 4 +- {bss => op-batcher}/flags/flags.go | 0 op-batcher/go.mod | 161 ++ op-batcher/go.sum | 1610 ++++++++++++++++ {bss => op-batcher}/sequencer/driver.go | 10 +- op-e2e/Makefile | 9 + {opnode/test => op-e2e}/geth.go | 5 +- op-e2e/go.mod | 168 ++ go.sum => op-e2e/go.sum | 16 +- {opnode/test => op-e2e}/setup.go | 22 +- {opnode/test => op-e2e}/system_test.go | 28 +- {opnode/test => op-e2e}/tracer.go | 8 +- {opnode => op-node}/.gitignore | 0 {opnode => op-node}/LICENSE | 0 {opnode => op-node}/Makefile | 12 +- {opnode => op-node}/README.md | 4 +- {opnode => op-node}/backoff/operation.go | 0 {opnode => op-node}/backoff/operation_test.go | 0 {opnode => op-node}/backoff/strategies.go | 0 .../backoff/strategies_test.go | 0 {opnode => op-node}/cmd/main.go | 9 +- .../cmd/stateviz/assets/index.html | 0 .../cmd/stateviz/assets/main.js | 0 {opnode => op-node}/cmd/stateviz/main.go | 2 +- {opnode => op-node}/contracts/Makefile | 0 .../contracts/deposit/deposit_feed_raw.go | 0 .../deposit/optimism_portal_deployed.go | 0 {opnode => op-node}/contracts/doc.go | 0 .../l1block/l1_block_info_deployed.go | 0 .../contracts/l1block/l1_block_info_raw.go | 0 .../withdrawer/withdrawer_deployed.go | 0 .../contracts/withdrawer/withdrawer_raw.go | 0 {opnode => op-node}/eth/heads.go | 0 {opnode => op-node}/eth/id.go | 0 {opnode => op-node}/flags/flags.go | 0 {opnode => op-node}/flags/flags_test.go | 0 {opnode => op-node}/flags/p2p_flags.go | 0 go.mod => op-node/go.mod | 10 +- op-node/go.sum | 1587 ++++++++++++++++ {opnode => op-node}/l1/batching.go | 0 {opnode => op-node}/l1/batching_test.go | 3 +- {opnode => op-node}/l1/receipts.go | 2 +- {opnode => op-node}/l1/request_sema.go | 0 {opnode => op-node}/l1/source.go | 9 +- {opnode => op-node}/l1/source_test.go | 7 +- {opnode => op-node}/l1/types.go | 4 +- {opnode => op-node}/l2/api.go | 2 +- {opnode => op-node}/l2/source.go | 6 +- {opnode => op-node}/l2/ssz.go | 0 {opnode => op-node}/l2/ssz_test.go | 0 {opnode => op-node}/l2/util.go | 4 +- {opnode => op-node}/node/api.go | 12 +- {opnode => op-node}/node/bundle_builder.go | 4 +- .../node/bundle_builder_test.go | 6 +- {opnode => op-node}/node/comms.go | 4 +- {opnode => op-node}/node/config.go | 4 +- {opnode => op-node}/node/log.go | 0 {opnode => op-node}/node/node.go | 12 +- {opnode => op-node}/node/server.go | 6 +- {opnode => op-node}/node/server_test.go | 13 +- {opnode => op-node}/p2p/config.go | 2 +- {opnode => op-node}/p2p/discovery.go | 0 {opnode => op-node}/p2p/gossip.go | 4 +- {opnode => op-node}/p2p/host.go | 0 {opnode => op-node}/p2p/host_test.go | 6 +- {opnode => op-node}/p2p/node.go | 2 +- {opnode => op-node}/p2p/notifications.go | 0 {opnode => op-node}/p2p/prepared.go | 0 {opnode => op-node}/p2p/rpc_api.go | 0 {opnode => op-node}/p2p/rpc_client.go | 0 {opnode => op-node}/p2p/rpc_server.go | 0 {opnode => op-node}/p2p/signer.go | 4 +- {opnode => op-node}/predeploy/predeploy.go | 0 {opnode => op-node}/rollup/derive/batch.go | 2 +- .../rollup/derive/batch_test.go | 2 +- {opnode => op-node}/rollup/derive/doc.go | 0 .../rollup/derive/fuzz_parsers_test.go | 4 +- .../rollup/derive/l1_block_info.go | 0 .../rollup/derive/l1_block_info_test.go | 2 +- .../rollup/derive/payload_attributes.go | 4 +- .../rollup/derive/payload_attributes_test.go | 2 +- {opnode => op-node}/rollup/driver/driver.go | 10 +- {opnode => op-node}/rollup/driver/state.go | 8 +- .../rollup/driver/state_test.go | 10 +- {opnode => op-node}/rollup/driver/step.go | 8 +- {opnode => op-node}/rollup/sync/start.go | 12 +- {opnode => op-node}/rollup/sync/start_test.go | 9 +- {opnode => op-node}/rollup/types.go | 2 +- {opnode => op-node}/rollup/types_test.go | 2 +- {opnode => op-node}/service.go | 8 +- {opnode/internal => op-node}/testlog/LICENSE | 0 .../internal => op-node}/testlog/README.md | 0 .../internal => op-node}/testlog/testlog.go | 0 .../testutils/fake_chain.go | 7 +- {opnode => op-node}/version/version.go | 0 {opnode => op-node}/withdrawals/proof.go | 0 {opnode => op-node}/withdrawals/utils.go | 10 +- {l2os => op-proposer}/.gitignore | 0 {l2os => op-proposer}/Makefile | 8 +- .../bindings/l2oo/l2_output_oracle.go | 0 {l2os/cmd/l2os => op-proposer/cmd}/main.go | 9 +- {l2os => op-proposer}/config.go | 4 +- {l2os => op-proposer}/drivers/interface.go | 0 .../drivers/l2output/driver.go | 6 +- {l2os => op-proposer}/flags/flags.go | 0 {l2os => op-proposer}/flags/flags_test.go | 0 op-proposer/go.mod | 157 ++ op-proposer/go.sum | 1611 +++++++++++++++++ {l2os => op-proposer}/l2_output_submitter.go | 8 +- {l2os => op-proposer}/mock/l1client.go | 0 .../rollupclient/rollupclient.go | 4 +- {l2os => op-proposer}/service.go | 4 +- {l2os => op-proposer}/txmgr/send_state.go | 0 .../txmgr/send_state_test.go | 2 +- {l2os => op-proposer}/txmgr/txmgr.go | 0 {l2os => op-proposer}/txmgr/txmgr_test.go | 2 +- ops-bedrock/Dockerfile.batcher | 17 + {ops => ops-bedrock}/Dockerfile.l1 | 0 {ops => ops-bedrock}/Dockerfile.l2 | 0 ops-bedrock/Dockerfile.node | 19 + ops-bedrock/Dockerfile.proposer | 16 + {ops => ops-bedrock}/Dockerfile.stateviz | 8 +- {ops => ops-bedrock}/devnet-up.sh | 16 +- {ops => ops-bedrock}/docker-compose.yml | 24 +- {ops => ops-bedrock}/entrypoint.sh | 0 {ops => ops-bedrock}/genesis-l1.json | 0 {ops => ops-bedrock}/genesis-l2.json | 0 .../op-batcher-entrypoint.sh | 2 +- ops-bedrock/op-batcher-key.txt | 1 + {ops => ops-bedrock}/p2p-node-key.txt | 0 {ops => ops-bedrock}/p2p-sequencer-key.txt | 0 {ops => ops-bedrock}/rollup.json | 0 {ops => ops-bedrock}/test-integration.sh | 0 ops/Dockerfile.bss | 22 - ops/Dockerfile.l2os | 21 - ops/Dockerfile.opnode | 20 - package.json | 6 +- specs/proposals.md | 4 +- 152 files changed, 5747 insertions(+), 346 deletions(-) create mode 100644 go.work create mode 100644 go.work.sum create mode 100644 op-batcher/Makefile rename {bss => op-batcher}/batch_submitter.go (93%) rename {bss/cmd/bss => op-batcher/cmd}/main.go (81%) rename {bss => op-batcher}/config.go (97%) rename {bss => op-batcher}/db/history_db.go (97%) rename {bss => op-batcher}/db/history_db_test.go (96%) rename {bss => op-batcher}/flags/flags.go (100%) create mode 100644 op-batcher/go.mod create mode 100644 op-batcher/go.sum rename {bss => op-batcher}/sequencer/driver.go (95%) create mode 100644 op-e2e/Makefile rename {opnode/test => op-e2e}/geth.go (98%) create mode 100644 op-e2e/go.mod rename go.sum => op-e2e/go.sum (99%) rename {opnode/test => op-e2e}/setup.go (96%) rename {opnode/test => op-e2e}/system_test.go (97%) rename {opnode/test => op-e2e}/tracer.go (81%) rename {opnode => op-node}/.gitignore (100%) rename {opnode => op-node}/LICENSE (100%) rename {opnode => op-node}/Makefile (73%) rename {opnode => op-node}/README.md (95%) rename {opnode => op-node}/backoff/operation.go (100%) rename {opnode => op-node}/backoff/operation_test.go (100%) rename {opnode => op-node}/backoff/strategies.go (100%) rename {opnode => op-node}/backoff/strategies_test.go (100%) rename {opnode => op-node}/cmd/main.go (90%) rename {opnode => op-node}/cmd/stateviz/assets/index.html (100%) rename {opnode => op-node}/cmd/stateviz/assets/main.js (100%) rename {opnode => op-node}/cmd/stateviz/main.go (98%) rename {opnode => op-node}/contracts/Makefile (100%) rename {opnode => op-node}/contracts/deposit/deposit_feed_raw.go (100%) rename {opnode => op-node}/contracts/deposit/optimism_portal_deployed.go (100%) rename {opnode => op-node}/contracts/doc.go (100%) rename {opnode => op-node}/contracts/l1block/l1_block_info_deployed.go (100%) rename {opnode => op-node}/contracts/l1block/l1_block_info_raw.go (100%) rename {opnode => op-node}/contracts/withdrawer/withdrawer_deployed.go (100%) rename {opnode => op-node}/contracts/withdrawer/withdrawer_raw.go (100%) rename {opnode => op-node}/eth/heads.go (100%) rename {opnode => op-node}/eth/id.go (100%) rename {opnode => op-node}/flags/flags.go (100%) rename {opnode => op-node}/flags/flags_test.go (100%) rename {opnode => op-node}/flags/p2p_flags.go (100%) rename go.mod => op-node/go.mod (96%) create mode 100644 op-node/go.sum rename {opnode => op-node}/l1/batching.go (100%) rename {opnode => op-node}/l1/batching_test.go (98%) rename {opnode => op-node}/l1/receipts.go (98%) rename {opnode => op-node}/l1/request_sema.go (100%) rename {opnode => op-node}/l1/source.go (98%) rename {opnode => op-node}/l1/source_test.go (96%) rename {opnode => op-node}/l1/types.go (96%) rename {opnode => op-node}/l2/api.go (99%) rename {opnode => op-node}/l2/source.go (98%) rename {opnode => op-node}/l2/ssz.go (100%) rename {opnode => op-node}/l2/ssz_test.go (100%) rename {opnode => op-node}/l2/util.go (96%) rename {opnode => op-node}/node/api.go (96%) rename {opnode => op-node}/node/bundle_builder.go (95%) rename {opnode => op-node}/node/bundle_builder_test.go (96%) rename {opnode => op-node}/node/comms.go (85%) rename {opnode => op-node}/node/config.go (91%) rename {opnode => op-node}/node/log.go (100%) rename {opnode => op-node}/node/node.go (96%) rename {opnode => op-node}/node/server.go (93%) rename {opnode => op-node}/node/server_test.go (96%) rename {opnode => op-node}/p2p/config.go (99%) rename {opnode => op-node}/p2p/discovery.go (100%) rename {opnode => op-node}/p2p/gossip.go (99%) rename {opnode => op-node}/p2p/host.go (100%) rename {opnode => op-node}/p2p/host_test.go (97%) rename {opnode => op-node}/p2p/node.go (98%) rename {opnode => op-node}/p2p/notifications.go (100%) rename {opnode => op-node}/p2p/prepared.go (100%) rename {opnode => op-node}/p2p/rpc_api.go (100%) rename {opnode => op-node}/p2p/rpc_client.go (100%) rename {opnode => op-node}/p2p/rpc_server.go (100%) rename {opnode => op-node}/p2p/signer.go (95%) rename {opnode => op-node}/predeploy/predeploy.go (100%) rename {opnode => op-node}/rollup/derive/batch.go (98%) rename {opnode => op-node}/rollup/derive/batch_test.go (93%) rename {opnode => op-node}/rollup/derive/doc.go (100%) rename {opnode => op-node}/rollup/derive/fuzz_parsers_test.go (97%) rename {opnode => op-node}/rollup/derive/l1_block_info.go (100%) rename {opnode => op-node}/rollup/derive/l1_block_info_test.go (98%) rename {opnode => op-node}/rollup/derive/payload_attributes.go (98%) rename {opnode => op-node}/rollup/derive/payload_attributes_test.go (99%) rename {opnode => op-node}/rollup/driver/driver.go (92%) rename {opnode => op-node}/rollup/driver/state.go (98%) rename {opnode => op-node}/rollup/driver/state_test.go (96%) rename {opnode => op-node}/rollup/driver/step.go (98%) rename {opnode => op-node}/rollup/sync/start.go (98%) rename {opnode => op-node}/rollup/sync/start_test.go (95%) rename {opnode => op-node}/rollup/types.go (97%) rename {opnode => op-node}/rollup/types_test.go (94%) rename {opnode => op-node}/service.go (91%) rename {opnode/internal => op-node}/testlog/LICENSE (100%) rename {opnode/internal => op-node}/testlog/README.md (100%) rename {opnode/internal => op-node}/testlog/testlog.go (100%) rename {opnode/internal => op-node}/testutils/fake_chain.go (97%) rename {opnode => op-node}/version/version.go (100%) rename {opnode => op-node}/withdrawals/proof.go (100%) rename {opnode => op-node}/withdrawals/utils.go (96%) rename {l2os => op-proposer}/.gitignore (100%) rename {l2os => op-proposer}/Makefile (88%) rename {l2os => op-proposer}/bindings/l2oo/l2_output_oracle.go (100%) rename {l2os/cmd/l2os => op-proposer/cmd}/main.go (81%) rename {l2os => op-proposer}/config.go (97%) rename {l2os => op-proposer}/drivers/interface.go (100%) rename {l2os => op-proposer}/drivers/l2output/driver.go (97%) rename {l2os => op-proposer}/flags/flags.go (100%) rename {l2os => op-proposer}/flags/flags_test.go (100%) create mode 100644 op-proposer/go.mod create mode 100644 op-proposer/go.sum rename {l2os => op-proposer}/l2_output_submitter.go (96%) rename {l2os => op-proposer}/mock/l1client.go (100%) rename {l2os => op-proposer}/rollupclient/rollupclient.go (87%) rename {l2os => op-proposer}/service.go (98%) rename {l2os => op-proposer}/txmgr/send_state.go (100%) rename {l2os => op-proposer}/txmgr/send_state_test.go (98%) rename {l2os => op-proposer}/txmgr/txmgr.go (100%) rename {l2os => op-proposer}/txmgr/txmgr_test.go (99%) create mode 100644 ops-bedrock/Dockerfile.batcher rename {ops => ops-bedrock}/Dockerfile.l1 (100%) rename {ops => ops-bedrock}/Dockerfile.l2 (100%) create mode 100644 ops-bedrock/Dockerfile.node create mode 100644 ops-bedrock/Dockerfile.proposer rename {ops => ops-bedrock}/Dockerfile.stateviz (64%) rename {ops => ops-bedrock}/devnet-up.sh (94%) rename {ops => ops-bedrock}/docker-compose.yml (89%) rename {ops => ops-bedrock}/entrypoint.sh (100%) rename {ops => ops-bedrock}/genesis-l1.json (100%) rename {ops => ops-bedrock}/genesis-l2.json (100%) rename ops/bss-entrypoint.sh => ops-bedrock/op-batcher-entrypoint.sh (94%) create mode 100644 ops-bedrock/op-batcher-key.txt rename {ops => ops-bedrock}/p2p-node-key.txt (100%) rename {ops => ops-bedrock}/p2p-sequencer-key.txt (100%) rename {ops => ops-bedrock}/rollup.json (100%) rename {ops => ops-bedrock}/test-integration.sh (100%) delete mode 100644 ops/Dockerfile.bss delete mode 100644 ops/Dockerfile.l2os delete mode 100644 ops/Dockerfile.opnode diff --git a/.circleci/config.yml b/.circleci/config.yml index 9a7fe3d476b1..06af510c357d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -40,10 +40,10 @@ workflows: branches: only: - main - image-name: opnode + image-name: op-node image-tag: develop - dockerfile: ops/Dockerfile.opnode - name: Build opnode + dockerfile: ops-bedrock/Dockerfile.node + name: Build op-node - build-dockerfile: context: - optimism @@ -51,7 +51,18 @@ workflows: branches: only: - main - image-name: l2os + image-name: op-proposer image-tag: develop - dockerfile: ops/Dockerfile.l2os - name: Build L2 output submitter + dockerfile: ops-bedrock/Dockerfile.proposer + name: Build op-proposer + - build-dockerfile: + context: + - optimism + filters: + branches: + only: + - main + image-name: op-batcher + image-tag: develop + dockerfile: ops-bedrock/Dockerfile.batcher + name: Build op-batcher diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 878dc7550300..8aaf5f9ab63d 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -19,17 +19,56 @@ jobs: go-version: 1.18 - name: Checkout code uses: actions/checkout@v2 - - name: golangci-lint - uses: golangci/golangci-lint-action@v2 + + - name: golangci-lint op-node + uses: golangci/golangci-lint-action@v3 with: - version: v1.45.0 # version of golangci-lint, not the action - skip-go-installation: true + version: v1.45.2 # version of golangci-lint, not the action + working-directory: op-node # rules: https://golangci-lint.run/usage/quick-start/ args: -E asciicheck,goimports,misspell - - name: Test and generate coverage - run: go test -coverpkg=./... -coverprofile=coverage.out -covermode=atomic ./... + - name: golangci-lint op-proposer + uses: golangci/golangci-lint-action@v3 + with: + version: v1.45.2 # version of golangci-lint, not the action + working-directory: op-proposer + args: -E asciicheck,goimports,misspell + - name: golangci-lint op-batcher + uses: golangci/golangci-lint-action@v3 + with: + version: v1.45.2 # version of golangci-lint, not the action + working-directory: op-batcher + args: -E asciicheck,goimports,misspell + - name: golangci-lint op-e2e + uses: golangci/golangci-lint-action@v3 + with: + version: v1.45.2 # version of golangci-lint, not the action + working-directory: op-e2e + args: -E asciicheck,goimports,misspell + - name: Test op-node + run: | + cd op-node + go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + - name: Test op-proposer + run: | + cd op-proposer + go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + - name: Test op-batcher + run: | + cd op-batcher + go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + - name: Test op-e2e + run: | + cd op-e2e + go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + - name: Upload coverage output uses: codecov/codecov-action@v2 + with: + files: ./op-node/coverage.out,./op-proposer/coverage.out,./op-batcher/coverage.out,./op-e2e/coverage.out + flags: unittests + name: codecov-umbrella + verbose: true build: runs-on: ubuntu-latest @@ -65,19 +104,19 @@ jobs: cd packages/contracts yarn install - - name: opnode Contracts + - name: op-node Contracts run: | - cd opnode/contracts + cd op-node/contracts make git diff --exit-code - - name: l2os Bindings + - name: op-proposer Bindings run: | - cd l2os + cd op-proposer make bindings git diff --exit-code - opnode-fuzz: + op-node-fuzz: runs-on: ubuntu-latest name: Fuzz parsers in the opnode steps: @@ -89,5 +128,5 @@ jobs: uses: actions/checkout@v2 - name: Fuzz run: | - cd opnode + cd op-node make fuzz diff --git a/.github/workflows/markdown-ci.yml b/.github/workflows/markdown-ci.yml index 4c5374bbbc29..fc91f0134a1c 100644 --- a/.github/workflows/markdown-ci.yml +++ b/.github/workflows/markdown-ci.yml @@ -53,5 +53,5 @@ jobs: - name: Link Checker uses: lycheeverse/lychee-action@v1.2.0 with: - args: --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude-mail README.md "./specs/**/*.md" "./meta/**/*.md" "./opnode/**/*.md" + args: --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude-mail README.md "./specs/**/*.md" "./meta/**/*.md" "./op-node/**/*.md" fail: true diff --git a/.gitignore b/.gitignore index 6866feb22c82..95c7479a15bb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ integration-tests/artifacts/ # Ignore local fuzzing results **/testdata/fuzz/ + +coverage.out \ No newline at end of file diff --git a/Makefile b/Makefile index 4423dac26711..8eef1d869235 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ITESTS_L2_HOST=http://localhost:9545 build: build-go contracts integration-tests .PHONY: build -build-go: submodules opnode l2os bss +build-go: submodules op-node op-proposer op-batcher .PHONY: build-go build-ts: submodules contracts integration-tests @@ -18,9 +18,17 @@ submodules: fi .PHONY: submodules -opnode: - go build -o ./bin/op ./opnode/cmd -.PHONY: opnode +op-node: + make -C ./op-node op-node +.PHONY: op-node + +op-batcher: + make -C ./op-batcher op-batcher +.PHONY: op-batcher + +op-proposer: + make -C ./op-proposer op-proposer +.PHONY: op-proposer contracts: cd ./packages/contracts && yarn install && yarn build @@ -35,39 +43,34 @@ clean: .PHONY: clean devnet-up: - @bash ./ops/devnet-up.sh + @bash ./ops-bedrock/devnet-up.sh .PHONY: devnet-up devnet-down: - @(cd ./ops && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose stop) + @(cd ./ops-bedrock && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose stop) .PHONY: devnet-down devnet-clean: rm -rf ./packages/contracts/deployments/devnetL1 rm -rf ./.devnet - cd ./ops && docker-compose down + cd ./ops-bedrock && docker-compose down docker volume rm ops_l1_data docker volume rm ops_l2_data .PHONY: devnet-clean test-unit: - cd ./opnode && make test + make -C ./op-node test + make -C ./op-proposer test + make -C ./op-batcher test + make -C ./op-e2e test cd ./packages/contracts && yarn test .PHONY: test-unit test-integration: - bash ./ops/test-integration.sh \ + bash ./ops-bedrock/test-integration.sh \ ./packages/contracts/deployments/devnetL1 .PHONY: test-integration devnet-genesis: - bash ./ops/devnet-genesis.sh + bash ./ops-bedrock/devnet-genesis.sh .PHONY: devnet-genesis - -bss: - go build -o ./bin/bss ./bss/cmd/bss -.PHONY: bss - -l2os: - go build -o ./bin/l2os ./l2os/cmd/l2os -.PHONY: l2os diff --git a/go.work b/go.work new file mode 100644 index 000000000000..de3336197b46 --- /dev/null +++ b/go.work @@ -0,0 +1,13 @@ +go 1.18 + +use ( + ./op-batcher + ./op-e2e + ./op-node + ./op-proposer +) + +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce + +// For local debugging: +// replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 000000000000..339aba62148f --- /dev/null +++ b/go.work.sum @@ -0,0 +1,9 @@ +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce h1:Wa0BVNdeyzIoJkrZtI7o2NEw8F98vVIzkPpiFACbdCA= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= +github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= diff --git a/meta/linting.md b/meta/linting.md index c356d1c85504..f6e317db1542 100644 --- a/meta/linting.md +++ b/meta/linting.md @@ -59,7 +59,9 @@ Justification for linting rules: ```shell # Install linter globally (should not affect go.mod) -go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.0 +go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.2 +# Disabling goanalysis_metalinter +# See https://github.com/golangci/golangci-lint/issues/2788 # run linter, add --fix option to fix problems (where supported) -golangci-lint run -E asciicheck,goimports,misspell +golangci-lint run -E asciicheck,goimports,misspell -D goanalysis_metalinter ``` diff --git a/meta/releases.md b/meta/releases.md index 0167d8fe25c1..8c93b042d61b 100644 --- a/meta/releases.md +++ b/meta/releases.md @@ -15,13 +15,13 @@ yarn build yarn test cd ../.. - + # 2.2: Confirm contract bindings are up-to-date - cd opnode/contracts + cd op-node/contracts make abi make binding cd ../.. - + # 2.3: Run Go tests (including end-to-end tests) go test -v ../.. ``` diff --git a/op-batcher/Makefile b/op-batcher/Makefile new file mode 100644 index 000000000000..3984219f257c --- /dev/null +++ b/op-batcher/Makefile @@ -0,0 +1,26 @@ +GITCOMMIT := $(shell git rev-parse HEAD) +GITDATE := $(shell git show -s --format='%ct') +VERSION := v0.0.0 + +LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) +LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) +LDFLAGSSTRING +=-X main.Version=$(VERSION) +LDFLAGS := -ldflags "$(LDFLAGSSTRING)" + +op-batcher: + env GO111MODULE=on go build -v $(LDFLAGS) -o ./bin/op-batcher ./cmd + +clean: + rm bin/op-batcher + +test: + go test -v ./... + +lint: + golangci-lint run -E asciicheck,goimports,misspell ./... + +.PHONY: \ + op-batcher \ + clean \ + test \ + lint diff --git a/bss/batch_submitter.go b/op-batcher/batch_submitter.go similarity index 93% rename from bss/batch_submitter.go rename to op-batcher/batch_submitter.go index 986c0d703e37..f9b86c8af820 100644 --- a/bss/batch_submitter.go +++ b/op-batcher/batch_submitter.go @@ -1,4 +1,4 @@ -package bss +package op_batcher import ( "context" @@ -8,11 +8,11 @@ import ( "syscall" "time" - "github.com/ethereum-optimism/optimistic-specs/bss/db" - "github.com/ethereum-optimism/optimistic-specs/bss/sequencer" - "github.com/ethereum-optimism/optimistic-specs/l2os" - "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" - "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum-optimism/optimism/op-batcher/db" + "github.com/ethereum-optimism/optimism/op-batcher/sequencer" + proposer "github.com/ethereum-optimism/optimism/op-proposer" + "github.com/ethereum-optimism/optimism/op-proposer/rollupclient" + "github.com/ethereum-optimism/optimism/op-proposer/txmgr" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" @@ -87,7 +87,7 @@ func Main(version string) func(ctx *cli.Context) error { // batches to L1 for availability. type BatchSubmitter struct { ctx context.Context - sequencerService *l2os.Service + sequencerService *proposer.Service } // NewBatchSubmitter initializes the BatchSubmitter, gathering any resources @@ -178,7 +178,7 @@ func NewBatchSubmitter( return nil, err } - sequencerService := l2os.NewService(l2os.ServiceConfig{ + sequencerService := proposer.NewService(proposer.ServiceConfig{ Log: l, Context: ctx, Driver: sequencerDriver, diff --git a/bss/cmd/bss/main.go b/op-batcher/cmd/main.go similarity index 81% rename from bss/cmd/bss/main.go rename to op-batcher/cmd/main.go index 64f7b57e7014..6a1bcab2682a 100644 --- a/bss/cmd/bss/main.go +++ b/op-batcher/cmd/main.go @@ -7,8 +7,8 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/urfave/cli" - "github.com/ethereum-optimism/optimistic-specs/bss" - "github.com/ethereum-optimism/optimistic-specs/bss/flags" + batcher "github.com/ethereum-optimism/optimism/op-batcher" + "github.com/ethereum-optimism/optimism/op-batcher/flags" ) var ( @@ -30,12 +30,12 @@ func main() { app := cli.NewApp() app.Flags = flags.Flags app.Version = fmt.Sprintf("%s-%s-%s", Version, GitCommit, GitDate) - app.Name = "bss" + app.Name = "op-batcher" app.Usage = "Batch Submitter Service" app.Description = "Service for generating and submitting L2 tx batches " + "to L1" - app.Action = bss.Main(Version) + app.Action = batcher.Main(Version) err := app.Run(os.Args) if err != nil { log.Crit("Application failed", "message", err) diff --git a/bss/config.go b/op-batcher/config.go similarity index 97% rename from bss/config.go rename to op-batcher/config.go index f5e5cdf047fb..99484a218a28 100644 --- a/bss/config.go +++ b/op-batcher/config.go @@ -1,11 +1,11 @@ -package bss +package op_batcher import ( "time" "github.com/urfave/cli" - "github.com/ethereum-optimism/optimistic-specs/bss/flags" + "github.com/ethereum-optimism/optimism/op-batcher/flags" ) type Config struct { diff --git a/bss/db/history_db.go b/op-batcher/db/history_db.go similarity index 97% rename from bss/db/history_db.go rename to op-batcher/db/history_db.go index f59b7969cc33..b3c1e260abde 100644 --- a/bss/db/history_db.go +++ b/op-batcher/db/history_db.go @@ -6,7 +6,7 @@ import ( "os" "sort" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/common" ) diff --git a/bss/db/history_db_test.go b/op-batcher/db/history_db_test.go similarity index 96% rename from bss/db/history_db_test.go rename to op-batcher/db/history_db_test.go index 1f590410863c..2d7b3d906e51 100644 --- a/bss/db/history_db_test.go +++ b/op-batcher/db/history_db_test.go @@ -5,8 +5,8 @@ import ( "os" "testing" - "github.com/ethereum-optimism/optimistic-specs/bss/db" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-batcher/db" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) diff --git a/bss/flags/flags.go b/op-batcher/flags/flags.go similarity index 100% rename from bss/flags/flags.go rename to op-batcher/flags/flags.go diff --git a/op-batcher/go.mod b/op-batcher/go.mod new file mode 100644 index 000000000000..8afa38d99742 --- /dev/null +++ b/op-batcher/go.mod @@ -0,0 +1,161 @@ +module github.com/ethereum-optimism/optimism/op-batcher + +go 1.18 + +require ( + github.com/ethereum-optimism/optimism/op-node v0.0.0 + github.com/ethereum-optimism/optimism/op-proposer v0.0.0 + github.com/ethereum/go-ethereum v1.10.16 + github.com/miguelmota/go-ethereum-hdwallet v0.1.1 + github.com/stretchr/testify v1.7.0 + github.com/urfave/cli v1.22.5 +) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/benbjohnson/clock v1.1.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 // indirect + github.com/coreos/go-systemd/v22 v22.1.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/flynn/noise v1.0.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/godbus/dbus/v5 v5.0.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.3.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/gopacket v1.1.19 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/hashicorp/go-multierror v1.0.0 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/ipfs/go-cid v0.0.7 // indirect + github.com/ipfs/go-datastore v0.5.0 // indirect + github.com/ipfs/go-ds-leveldb v0.5.0 // indirect + github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/ipfs/go-log v1.0.5 // indirect + github.com/ipfs/go-log/v2 v2.5.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/koron/go-ssdp v0.0.2 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/libp2p/go-cidranger v1.1.0 // indirect + github.com/libp2p/go-conn-security-multistream v0.3.0 // indirect + github.com/libp2p/go-eventbus v0.2.1 // indirect + github.com/libp2p/go-flow-metrics v0.0.3 // indirect + github.com/libp2p/go-libp2p v0.18.1 // indirect + github.com/libp2p/go-libp2p-asn-util v0.1.0 // indirect + github.com/libp2p/go-libp2p-blankhost v0.3.0 // indirect + github.com/libp2p/go-libp2p-core v0.15.0 // indirect + github.com/libp2p/go-libp2p-discovery v0.6.0 // indirect + github.com/libp2p/go-libp2p-mplex v0.6.0 // indirect + github.com/libp2p/go-libp2p-nat v0.1.0 // indirect + github.com/libp2p/go-libp2p-noise v0.3.0 // indirect + github.com/libp2p/go-libp2p-peerstore v0.6.0 // indirect + github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect + github.com/libp2p/go-libp2p-pubsub v0.6.1 // indirect + github.com/libp2p/go-libp2p-swarm v0.10.2 // indirect + github.com/libp2p/go-libp2p-testing v0.9.2 // indirect + github.com/libp2p/go-libp2p-tls v0.3.1 // indirect + github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 // indirect + github.com/libp2p/go-libp2p-yamux v0.9.0 // indirect + github.com/libp2p/go-mplex v0.6.0 // indirect + github.com/libp2p/go-msgio v0.1.0 // indirect + github.com/libp2p/go-nat v0.1.0 // indirect + github.com/libp2p/go-netroute v0.2.0 // indirect + github.com/libp2p/go-openssl v0.0.7 // indirect + github.com/libp2p/go-reuseport v0.1.0 // indirect + github.com/libp2p/go-reuseport-transport v0.1.0 // indirect + github.com/libp2p/go-stream-muxer-multistream v0.4.0 // indirect + github.com/libp2p/go-tcp-transport v0.5.1 // indirect + github.com/libp2p/go-yamux/v3 v3.1.0 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/miekg/dns v1.1.43 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr v0.5.0 // indirect + github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.0.3 // indirect + github.com/multiformats/go-multicodec v0.4.1 // indirect + github.com/multiformats/go-multihash v0.0.15 // indirect + github.com/multiformats/go-multistream v0.2.2 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.11.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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/raulk/clock v1.1.0 // indirect + github.com/raulk/go-watchdog v1.2.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect + github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.19.1 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + google.golang.org/grpc v1.40.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/urfave/cli.v1 v1.20.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) + +replace ( + github.com/ethereum-optimism/optimism/op-node v0.0.0 => ../op-node + github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer +) + +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead diff --git a/op-batcher/go.sum b/op-batcher/go.sum new file mode 100644 index 000000000000..532503582af4 --- /dev/null +++ b/op-batcher/go.sum @@ -0,0 +1,1610 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.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.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +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/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +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/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +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/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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +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/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +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/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +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/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +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/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +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/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 h1:7grrpcfCtbZLsjtB0DgMuzs1umsJmpzaHMZ6cO6iAWw= +github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= +github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +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/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= +github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= +github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +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-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +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/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead h1:AiLggtwXHmAGxNusOEH7edb83TtJnavtR2uY1z6YzYc= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= +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/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= +github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +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/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +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/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +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-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +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 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +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/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +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= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +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.2/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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +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.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= +github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/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/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +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/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= +github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-datastore v0.5.0 h1:rQicVCEacWyk4JZ6G5bD9TKR7lZEG1MWcG7UdWYrFAU= +github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= +github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= +github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= +github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= +github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= +github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= +github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= +github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= +github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= +github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +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/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= +github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= +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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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/libp2p/go-addr-util v0.1.0/go.mod h1:6I3ZYuFr2O/9D+SoyM0zEw0EF3YkldtTX406BpdQMqw= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= +github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= +github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= +github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= +github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-libp2p v0.18.1 h1:IK9EOGNO2ZghU4F+dx9c4xfhMNZr45x06CijJaZE/ms= +github.com/libp2p/go-libp2p v0.18.1/go.mod h1:ll44MqmrIFKpL3BwCexxzm+7RZ8exEtN96V1rRdMG7Y= +github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= +github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= +github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= +github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= +github.com/libp2p/go-libp2p-circuit v0.6.0 h1:rw/HlhmUB3OktS/Ygz6+2XABOmHKzZpPUuMNUMosj8w= +github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= +github.com/libp2p/go-libp2p-connmgr v0.2.4 h1:TMS0vc0TCBomtQJyWr7fYxcVYYhx+q/2gF++G5Jkl/w= +github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJfdCGv51mTmdpmM= +github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.11.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= +github.com/libp2p/go-libp2p-core v0.15.0 h1:hKpgy/bRVwO7Ah5x9u92Vo+gogAaOolafZF5kW0rVm0= +github.com/libp2p/go-libp2p-core v0.15.0/go.mod h1:agSaboYM4hzB1cWekgVReqV5M4g5M+2eNNejV+1EEhs= +github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= +github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= +github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= +github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= +github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= +github.com/libp2p/go-libp2p-nat v0.1.0 h1:vigUi2MEN+fwghe5ijpScxtbbDz+L/6y8XwlzYOJgSY= +github.com/libp2p/go-libp2p-nat v0.1.0/go.mod h1:DQzAG+QbDYjN1/C3B6vXucLtz3u9rEonLVPtZVzQqks= +github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= +github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= +github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= +github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnHd/VBjL4mY5A= +github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= +github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= +github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= +github.com/libp2p/go-libp2p-pubsub v0.6.1 h1:wycbV+f4rreCoVY61Do6g/BUk0RIrbNRcYVbn+QkjGk= +github.com/libp2p/go-libp2p-pubsub v0.6.1/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= +github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= +github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-quic-transport v0.16.1 h1:N/XqYXHurphPLDfXYhll8NyqzdZYQqAF4GIr7+SmLV8= +github.com/libp2p/go-libp2p-quic-transport v0.16.1/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-resource-manager v0.2.0 h1:Ul/k5d5StIpAtq7IapAEGh/2+0rwsJGXYJ6Kbzeedtc= +github.com/libp2p/go-libp2p-resource-manager v0.2.0/go.mod h1:K+eCkiapf+ey/LADO4TaMpMTP9/Qde/uLlrnRqV4PLQ= +github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= +github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= +github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= +github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= +github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= +github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= +github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= +github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= +github.com/libp2p/go-libp2p-testing v0.9.2 h1:dCpODRtRaDZKF8HXT9qqqgON+OMEB423Knrgeod8j84= +github.com/libp2p/go-libp2p-testing v0.9.2/go.mod h1:Td7kbdkWqYTJYQGTwzlgXwaqldraIanyjuRiAbK/XQU= +github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= +github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 h1:MSMe+tUfxpC9GArTz7a4G5zQKQgGh00Vio87d3j3xIg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= +github.com/libp2p/go-libp2p-yamux v0.8.1/go.mod h1:rUozF8Jah2dL9LLGyBaBeTQeARdwhefMCTQVQt6QobE= +github.com/libp2p/go-libp2p-yamux v0.9.0 h1:j+gnKykADCI/3cZlacOYBjQXDsncxgcwzJ1zw6Z6pts= +github.com/libp2p/go-libp2p-yamux v0.9.0/go.mod h1:tpJKkRH9LlHj0VQh9Y9RP1pmF7yCS9ixxY/oSv+hhhQ= +github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= +github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= +github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= +github.com/libp2p/go-msgio v0.1.0 h1:8Q7g/528ivAlfXTFWvWhVjTE8XG8sDTkRUKPYh9+5Q8= +github.com/libp2p/go-msgio v0.1.0/go.mod h1:eNlv2vy9V2X/kNldcZ+SShFE++o2Yjxwx6RAYsmgJnE= +github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= +github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= +github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= +github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= +github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-reuseport v0.1.0 h1:0ooKOx2iwyIkf339WCZ2HN3ujTDbkK0PjC7JVoP1AiM= +github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= +github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7CyD1zuN7xQT8gc= +github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= +github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= +github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= +github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= +github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-tcp-transport v0.5.1 h1:edOOs688VLZAozWC7Kj5/6HHXKNwi9M6wgRmmLa8M6Q= +github.com/libp2p/go-tcp-transport v0.5.1/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-ws-transport v0.6.0 h1:326XBL6Q+5CQ2KtjXz32+eGu02W/Kz2+Fm4SpXdr0q4= +github.com/libp2p/go-ws-transport v0.6.0/go.mod h1:dXqtI9e2JV9FtF1NOtWVZSKXh5zXvnuwPXfj8GPBbYU= +github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.1.0 h1:2johPiST4xsXsqQ/38C2MAERw0hJ+t8oehHWA8F2R3Q= +github.com/libp2p/go-yamux/v3 v3.1.0/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4= +github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= +github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= +github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +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/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= +github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= +github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= +github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= +github.com/miguelmota/go-ethereum-hdwallet v0.1.1/go.mod h1:f9m9uXokAHA6WNoYOPjj4AqjJS5pquQRiYYj/XSyPYc= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= +github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= +github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= +github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= +github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= +github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= +github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= +github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= +github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= +github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= +github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= +github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +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/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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +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.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +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/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/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-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/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-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +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-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/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/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= +github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= +github.com/raulk/go-watchdog v1.2.0 h1:konN75pw2BMmZ+AfuAm5rtFsWcJpKF3m02rKituuXNo= +github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +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/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sirupsen/logrus v1.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/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/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +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/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +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/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= +github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +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= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-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/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +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= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20200904194848-62affa334b73/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +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.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190219092855-153ac476189d/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-20190228124157-a34e9553db1e/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-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/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-20200124204421-9fbb57f87de9/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-20200602225109-6fdc65e7d980/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-20201214210602-f9fddec55a1e/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-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/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-20181130052023-1c3d964395ce/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= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-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-20200103221440-774c71fcf114/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= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +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.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +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= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +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/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-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +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= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +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-20200513103714-09dca8ec2884/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.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/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.28.1/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/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +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= +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= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +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= +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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/bss/sequencer/driver.go b/op-batcher/sequencer/driver.go similarity index 95% rename from bss/sequencer/driver.go rename to op-batcher/sequencer/driver.go index 7f8f9e776541..f8558192ae64 100644 --- a/bss/sequencer/driver.go +++ b/op-batcher/sequencer/driver.go @@ -5,11 +5,11 @@ import ( "crypto/ecdsa" "math/big" - "github.com/ethereum-optimism/optimistic-specs/bss/db" - "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" - "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimism/op-batcher/db" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-proposer/rollupclient" + "github.com/ethereum-optimism/optimism/op-proposer/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" diff --git a/op-e2e/Makefile b/op-e2e/Makefile new file mode 100644 index 000000000000..a52fd04c937a --- /dev/null +++ b/op-e2e/Makefile @@ -0,0 +1,9 @@ +test: + go test -v ./... + +lint: + golangci-lint run -E asciicheck,goimports,misspell ./... + +.PHONY: \ + test \ + lint diff --git a/opnode/test/geth.go b/op-e2e/geth.go similarity index 98% rename from opnode/test/geth.go rename to op-e2e/geth.go index 4281af900cb2..2b1f9ab629a4 100644 --- a/opnode/test/geth.go +++ b/op-e2e/geth.go @@ -1,4 +1,4 @@ -package test +package op_e2e import ( "context" @@ -10,8 +10,9 @@ import ( "strings" "time" - rollupEth "github.com/ethereum-optimism/optimistic-specs/opnode/eth" "github.com/ethereum/go-ethereum" + + rollupEth "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" diff --git a/op-e2e/go.mod b/op-e2e/go.mod new file mode 100644 index 000000000000..daa05021b6b9 --- /dev/null +++ b/op-e2e/go.mod @@ -0,0 +1,168 @@ +module github.com/ethereum-optimism/optimism/op-e2e + +go 1.18 + +require ( + github.com/ethereum-optimism/optimism/op-batcher v0.0.0 + github.com/ethereum-optimism/optimism/op-node v0.0.0 + github.com/ethereum-optimism/optimism/op-proposer v0.0.0 + github.com/ethereum/go-ethereum v1.10.16 + github.com/libp2p/go-libp2p v0.18.1 + github.com/libp2p/go-libp2p-core v0.15.0 + github.com/miguelmota/go-ethereum-hdwallet v0.1.1 + github.com/stretchr/testify v1.7.0 +) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/benbjohnson/clock v1.1.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 // indirect + github.com/coreos/go-systemd/v22 v22.1.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/flynn/noise v1.0.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/godbus/dbus/v5 v5.0.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.3.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/gopacket v1.1.19 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/hashicorp/go-multierror v1.0.0 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/ipfs/go-cid v0.0.7 // indirect + github.com/ipfs/go-datastore v0.5.0 // indirect + github.com/ipfs/go-ds-leveldb v0.5.0 // indirect + github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/ipfs/go-log v1.0.5 // indirect + github.com/ipfs/go-log/v2 v2.5.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/koron/go-ssdp v0.0.2 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/libp2p/go-cidranger v1.1.0 // indirect + github.com/libp2p/go-conn-security-multistream v0.3.0 // indirect + github.com/libp2p/go-eventbus v0.2.1 // indirect + github.com/libp2p/go-flow-metrics v0.0.3 // indirect + github.com/libp2p/go-libp2p-asn-util v0.1.0 // indirect + github.com/libp2p/go-libp2p-blankhost v0.3.0 // indirect + github.com/libp2p/go-libp2p-discovery v0.6.0 // indirect + github.com/libp2p/go-libp2p-mplex v0.6.0 // indirect + github.com/libp2p/go-libp2p-nat v0.1.0 // indirect + github.com/libp2p/go-libp2p-noise v0.3.0 // indirect + github.com/libp2p/go-libp2p-peerstore v0.6.0 // indirect + github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect + github.com/libp2p/go-libp2p-pubsub v0.6.1 // indirect + github.com/libp2p/go-libp2p-swarm v0.10.2 // indirect + github.com/libp2p/go-libp2p-testing v0.9.2 // indirect + github.com/libp2p/go-libp2p-tls v0.3.1 // indirect + github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 // indirect + github.com/libp2p/go-libp2p-yamux v0.9.0 // indirect + github.com/libp2p/go-mplex v0.6.0 // indirect + github.com/libp2p/go-msgio v0.1.0 // indirect + github.com/libp2p/go-nat v0.1.0 // indirect + github.com/libp2p/go-netroute v0.2.0 // indirect + github.com/libp2p/go-openssl v0.0.7 // indirect + github.com/libp2p/go-reuseport v0.1.0 // indirect + github.com/libp2p/go-reuseport-transport v0.1.0 // indirect + github.com/libp2p/go-stream-muxer-multistream v0.4.0 // indirect + github.com/libp2p/go-tcp-transport v0.5.1 // indirect + github.com/libp2p/go-yamux/v3 v3.1.0 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/miekg/dns v1.1.43 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr v0.5.0 // indirect + github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.0.3 // indirect + github.com/multiformats/go-multicodec v0.4.1 // indirect + github.com/multiformats/go-multihash v0.0.15 // indirect + github.com/multiformats/go-multistream v0.2.2 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.11.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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/raulk/clock v1.1.0 // indirect + github.com/raulk/go-watchdog v1.2.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli v1.22.5 // indirect + github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect + github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.19.1 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + google.golang.org/grpc v1.40.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/urfave/cli.v1 v1.20.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) + +replace ( + github.com/ethereum-optimism/optimism/op-batcher v0.0.0 => ../op-batcher + github.com/ethereum-optimism/optimism/op-node v0.0.0 => ../op-node + github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer +) + +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce diff --git a/go.sum b/op-e2e/go.sum similarity index 99% rename from go.sum rename to op-e2e/go.sum index 0d5c50ae89bf..bdb5e1c86239 100644 --- a/go.sum +++ b/op-e2e/go.sum @@ -121,11 +121,14 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -242,11 +245,10 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818 h1:oIqbYtUOntLsTfmbmOxj73nuQLkDHxp2KhNj+AWv32s= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead h1:AiLggtwXHmAGxNusOEH7edb83TtJnavtR2uY1z6YzYc= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -261,7 +263,6 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= @@ -365,7 +366,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -560,7 +560,6 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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 v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 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= @@ -859,7 +858,6 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= 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= @@ -1416,7 +1414,6 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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= @@ -1575,7 +1572,6 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= diff --git a/opnode/test/setup.go b/op-e2e/setup.go similarity index 96% rename from opnode/test/setup.go rename to op-e2e/setup.go index 32a4025597cb..dae022da2f53 100644 --- a/opnode/test/setup.go +++ b/op-e2e/setup.go @@ -1,4 +1,4 @@ -package test +package op_e2e import ( "context" @@ -9,16 +9,16 @@ import ( "strings" "time" - "github.com/ethereum-optimism/optimistic-specs/bss" - "github.com/ethereum-optimism/optimistic-specs/l2os" - "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/withdrawer" - rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" - "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + bss "github.com/ethereum-optimism/optimism/op-batcher" + "github.com/ethereum-optimism/optimism/op-node/contracts/deposit" + "github.com/ethereum-optimism/optimism/op-node/contracts/l1block" + "github.com/ethereum-optimism/optimism/op-node/contracts/withdrawer" + rollupNode "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/predeploy" + "github.com/ethereum-optimism/optimism/op-node/rollup" + l2os "github.com/ethereum-optimism/optimism/op-proposer" + "github.com/ethereum-optimism/optimism/op-proposer/bindings/l2oo" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" diff --git a/opnode/test/system_test.go b/op-e2e/system_test.go similarity index 97% rename from opnode/test/system_test.go rename to op-e2e/system_test.go index 84ad9c5d1efb..3c4c54b7d947 100644 --- a/opnode/test/system_test.go +++ b/op-e2e/system_test.go @@ -1,4 +1,4 @@ -package test +package op_e2e import ( "context" @@ -8,19 +8,19 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" - "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/withdrawer" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" - rollupNode "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" - "github.com/ethereum-optimism/optimistic-specs/opnode/withdrawals" + "github.com/ethereum-optimism/optimism/op-node/contracts/deposit" + "github.com/ethereum-optimism/optimism/op-node/contracts/l1block" + "github.com/ethereum-optimism/optimism/op-node/contracts/withdrawer" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/node" + rollupNode "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/predeploy" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/testlog" + "github.com/ethereum-optimism/optimism/op-node/withdrawals" + "github.com/ethereum-optimism/optimism/op-proposer/bindings/l2oo" + "github.com/ethereum-optimism/optimism/op-proposer/rollupclient" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" diff --git a/opnode/test/tracer.go b/op-e2e/tracer.go similarity index 81% rename from opnode/test/tracer.go rename to op-e2e/tracer.go index e1a81a1154c8..045e558486e7 100644 --- a/opnode/test/tracer.go +++ b/op-e2e/tracer.go @@ -1,11 +1,11 @@ -package test +package op_e2e import ( "context" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/node" "github.com/libp2p/go-libp2p-core/peer" ) diff --git a/opnode/.gitignore b/op-node/.gitignore similarity index 100% rename from opnode/.gitignore rename to op-node/.gitignore diff --git a/opnode/LICENSE b/op-node/LICENSE similarity index 100% rename from opnode/LICENSE rename to op-node/LICENSE diff --git a/opnode/Makefile b/op-node/Makefile similarity index 73% rename from opnode/Makefile rename to op-node/Makefile index 996dbf6821ab..c64b73d14160 100644 --- a/opnode/Makefile +++ b/op-node/Makefile @@ -4,15 +4,15 @@ VERSION := v0.0.0 LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) -LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimistic-specs/opnode/version.Version=$(VERSION) -LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimistic-specs/opnode/version.Meta=$(VERSION_META) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-node/version.Version=$(VERSION) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-node/version.Meta=$(VERSION_META) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" -opnode: - env GO111MODULE=on go build -v $(LDFLAGS) -o ./bin/opnode ./cmd/main.go +op-node: + env GO111MODULE=on go build -v $(LDFLAGS) -o ./bin/op-node ./cmd/main.go clean: - rm bin/opnode + rm bin/op-node test: go test -v ./... @@ -29,7 +29,7 @@ fuzz: .PHONY: \ - bss \ + op-node \ clean \ test \ lint \ diff --git a/opnode/README.md b/op-node/README.md similarity index 95% rename from opnode/README.md rename to op-node/README.md index c3a98f4420c5..0e1fccd452f8 100644 --- a/opnode/README.md +++ b/op-node/README.md @@ -7,8 +7,8 @@ This is the reference implementation of the [rollup-node spec](../specs/rollup-n From the repository root: ```shell -go build -o op ./opnode/cmd -go test ./opnode/... +go build -o op ./op-node/cmd +go test ./op-node/... ``` ## Running diff --git a/opnode/backoff/operation.go b/op-node/backoff/operation.go similarity index 100% rename from opnode/backoff/operation.go rename to op-node/backoff/operation.go diff --git a/opnode/backoff/operation_test.go b/op-node/backoff/operation_test.go similarity index 100% rename from opnode/backoff/operation_test.go rename to op-node/backoff/operation_test.go diff --git a/opnode/backoff/strategies.go b/op-node/backoff/strategies.go similarity index 100% rename from opnode/backoff/strategies.go rename to op-node/backoff/strategies.go diff --git a/opnode/backoff/strategies_test.go b/op-node/backoff/strategies_test.go similarity index 100% rename from opnode/backoff/strategies_test.go rename to op-node/backoff/strategies_test.go diff --git a/opnode/cmd/main.go b/op-node/cmd/main.go similarity index 90% rename from opnode/cmd/main.go rename to op-node/cmd/main.go index f0e32c0d1e14..d2f6cc733e4e 100644 --- a/opnode/cmd/main.go +++ b/op-node/cmd/main.go @@ -6,12 +6,13 @@ import ( "os/signal" "syscall" - "github.com/ethereum-optimism/optimistic-specs/opnode/version" + opnode "github.com/ethereum-optimism/optimism/op-node" - "github.com/ethereum-optimism/optimistic-specs/opnode" - "github.com/ethereum-optimism/optimistic-specs/opnode/flags" + "github.com/ethereum-optimism/optimism/op-node/version" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimism/op-node/flags" + + "github.com/ethereum-optimism/optimism/op-node/node" "github.com/ethereum/go-ethereum/log" "github.com/urfave/cli" ) diff --git a/opnode/cmd/stateviz/assets/index.html b/op-node/cmd/stateviz/assets/index.html similarity index 100% rename from opnode/cmd/stateviz/assets/index.html rename to op-node/cmd/stateviz/assets/index.html diff --git a/opnode/cmd/stateviz/assets/main.js b/op-node/cmd/stateviz/assets/main.js similarity index 100% rename from opnode/cmd/stateviz/assets/main.js rename to op-node/cmd/stateviz/assets/main.js diff --git a/opnode/cmd/stateviz/main.go b/op-node/cmd/stateviz/main.go similarity index 98% rename from opnode/cmd/stateviz/main.go rename to op-node/cmd/stateviz/main.go index edc7b2dba6b0..dd670be9de20 100644 --- a/opnode/cmd/stateviz/main.go +++ b/op-node/cmd/stateviz/main.go @@ -18,7 +18,7 @@ import ( "sync" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/log" ) diff --git a/opnode/contracts/Makefile b/op-node/contracts/Makefile similarity index 100% rename from opnode/contracts/Makefile rename to op-node/contracts/Makefile diff --git a/opnode/contracts/deposit/deposit_feed_raw.go b/op-node/contracts/deposit/deposit_feed_raw.go similarity index 100% rename from opnode/contracts/deposit/deposit_feed_raw.go rename to op-node/contracts/deposit/deposit_feed_raw.go diff --git a/opnode/contracts/deposit/optimism_portal_deployed.go b/op-node/contracts/deposit/optimism_portal_deployed.go similarity index 100% rename from opnode/contracts/deposit/optimism_portal_deployed.go rename to op-node/contracts/deposit/optimism_portal_deployed.go diff --git a/opnode/contracts/doc.go b/op-node/contracts/doc.go similarity index 100% rename from opnode/contracts/doc.go rename to op-node/contracts/doc.go diff --git a/opnode/contracts/l1block/l1_block_info_deployed.go b/op-node/contracts/l1block/l1_block_info_deployed.go similarity index 100% rename from opnode/contracts/l1block/l1_block_info_deployed.go rename to op-node/contracts/l1block/l1_block_info_deployed.go diff --git a/opnode/contracts/l1block/l1_block_info_raw.go b/op-node/contracts/l1block/l1_block_info_raw.go similarity index 100% rename from opnode/contracts/l1block/l1_block_info_raw.go rename to op-node/contracts/l1block/l1_block_info_raw.go diff --git a/opnode/contracts/withdrawer/withdrawer_deployed.go b/op-node/contracts/withdrawer/withdrawer_deployed.go similarity index 100% rename from opnode/contracts/withdrawer/withdrawer_deployed.go rename to op-node/contracts/withdrawer/withdrawer_deployed.go diff --git a/opnode/contracts/withdrawer/withdrawer_raw.go b/op-node/contracts/withdrawer/withdrawer_raw.go similarity index 100% rename from opnode/contracts/withdrawer/withdrawer_raw.go rename to op-node/contracts/withdrawer/withdrawer_raw.go diff --git a/opnode/eth/heads.go b/op-node/eth/heads.go similarity index 100% rename from opnode/eth/heads.go rename to op-node/eth/heads.go diff --git a/opnode/eth/id.go b/op-node/eth/id.go similarity index 100% rename from opnode/eth/id.go rename to op-node/eth/id.go diff --git a/opnode/flags/flags.go b/op-node/flags/flags.go similarity index 100% rename from opnode/flags/flags.go rename to op-node/flags/flags.go diff --git a/opnode/flags/flags_test.go b/op-node/flags/flags_test.go similarity index 100% rename from opnode/flags/flags_test.go rename to op-node/flags/flags_test.go diff --git a/opnode/flags/p2p_flags.go b/op-node/flags/p2p_flags.go similarity index 100% rename from opnode/flags/p2p_flags.go rename to op-node/flags/p2p_flags.go diff --git a/go.mod b/op-node/go.mod similarity index 96% rename from go.mod rename to op-node/go.mod index adaf52484915..76cff91645be 100644 --- a/go.mod +++ b/op-node/go.mod @@ -1,4 +1,4 @@ -module github.com/ethereum-optimism/optimistic-specs +module github.com/ethereum-optimism/optimism/op-node go 1.18 @@ -18,10 +18,10 @@ require ( github.com/libp2p/go-libp2p-peerstore v0.6.0 github.com/libp2p/go-libp2p-pubsub v0.6.1 github.com/libp2p/go-libp2p-swarm v0.10.2 + github.com/libp2p/go-libp2p-testing v0.9.2 github.com/libp2p/go-libp2p-tls v0.3.1 github.com/libp2p/go-libp2p-yamux v0.9.0 github.com/libp2p/go-tcp-transport v0.5.1 - github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/multiformats/go-multiaddr v0.5.0 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/stretchr/testify v1.7.0 @@ -31,11 +31,11 @@ require ( require ( github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/allegro/bigcache v1.2.1 // indirect github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/btcsuite/btcd v0.22.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect - github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cheekybits/genny v1.0.0 // indirect github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 // indirect @@ -88,7 +88,6 @@ require ( github.com/libp2p/go-libp2p-nat v0.1.0 // indirect github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect github.com/libp2p/go-libp2p-quic-transport v0.16.1 // indirect - github.com/libp2p/go-libp2p-testing v0.9.2 // indirect github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 // indirect github.com/libp2p/go-mplex v0.6.0 // indirect github.com/libp2p/go-msgio v0.1.0 // indirect @@ -161,7 +160,6 @@ require ( golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect - golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect golang.org/x/tools v0.1.5 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect diff --git a/op-node/go.sum b/op-node/go.sum new file mode 100644 index 000000000000..0a61b387c037 --- /dev/null +++ b/op-node/go.sum @@ -0,0 +1,1587 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.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.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +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/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +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/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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +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/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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +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/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +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/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +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/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +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/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +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/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 h1:7grrpcfCtbZLsjtB0DgMuzs1umsJmpzaHMZ6cO6iAWw= +github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= +github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +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/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= +github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= +github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +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-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +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/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818 h1:oIqbYtUOntLsTfmbmOxj73nuQLkDHxp2KhNj+AWv32s= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= +github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/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/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +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-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +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.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +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 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +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/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +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= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +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.2/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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/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/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +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.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/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/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +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/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= +github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-datastore v0.5.0 h1:rQicVCEacWyk4JZ6G5bD9TKR7lZEG1MWcG7UdWYrFAU= +github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= +github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= +github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= +github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= +github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= +github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= +github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= +github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= +github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= +github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +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/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= +github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= +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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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 v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +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/libp2p/go-addr-util v0.1.0/go.mod h1:6I3ZYuFr2O/9D+SoyM0zEw0EF3YkldtTX406BpdQMqw= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= +github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= +github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= +github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= +github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-libp2p v0.18.1 h1:IK9EOGNO2ZghU4F+dx9c4xfhMNZr45x06CijJaZE/ms= +github.com/libp2p/go-libp2p v0.18.1/go.mod h1:ll44MqmrIFKpL3BwCexxzm+7RZ8exEtN96V1rRdMG7Y= +github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= +github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= +github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= +github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= +github.com/libp2p/go-libp2p-circuit v0.6.0 h1:rw/HlhmUB3OktS/Ygz6+2XABOmHKzZpPUuMNUMosj8w= +github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= +github.com/libp2p/go-libp2p-connmgr v0.2.4 h1:TMS0vc0TCBomtQJyWr7fYxcVYYhx+q/2gF++G5Jkl/w= +github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJfdCGv51mTmdpmM= +github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.11.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= +github.com/libp2p/go-libp2p-core v0.15.0 h1:hKpgy/bRVwO7Ah5x9u92Vo+gogAaOolafZF5kW0rVm0= +github.com/libp2p/go-libp2p-core v0.15.0/go.mod h1:agSaboYM4hzB1cWekgVReqV5M4g5M+2eNNejV+1EEhs= +github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= +github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= +github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= +github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= +github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= +github.com/libp2p/go-libp2p-nat v0.1.0 h1:vigUi2MEN+fwghe5ijpScxtbbDz+L/6y8XwlzYOJgSY= +github.com/libp2p/go-libp2p-nat v0.1.0/go.mod h1:DQzAG+QbDYjN1/C3B6vXucLtz3u9rEonLVPtZVzQqks= +github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= +github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= +github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= +github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnHd/VBjL4mY5A= +github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= +github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= +github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= +github.com/libp2p/go-libp2p-pubsub v0.6.1 h1:wycbV+f4rreCoVY61Do6g/BUk0RIrbNRcYVbn+QkjGk= +github.com/libp2p/go-libp2p-pubsub v0.6.1/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= +github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= +github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-quic-transport v0.16.1 h1:N/XqYXHurphPLDfXYhll8NyqzdZYQqAF4GIr7+SmLV8= +github.com/libp2p/go-libp2p-quic-transport v0.16.1/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-resource-manager v0.2.0 h1:Ul/k5d5StIpAtq7IapAEGh/2+0rwsJGXYJ6Kbzeedtc= +github.com/libp2p/go-libp2p-resource-manager v0.2.0/go.mod h1:K+eCkiapf+ey/LADO4TaMpMTP9/Qde/uLlrnRqV4PLQ= +github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= +github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= +github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= +github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= +github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= +github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= +github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= +github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= +github.com/libp2p/go-libp2p-testing v0.9.2 h1:dCpODRtRaDZKF8HXT9qqqgON+OMEB423Knrgeod8j84= +github.com/libp2p/go-libp2p-testing v0.9.2/go.mod h1:Td7kbdkWqYTJYQGTwzlgXwaqldraIanyjuRiAbK/XQU= +github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= +github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 h1:MSMe+tUfxpC9GArTz7a4G5zQKQgGh00Vio87d3j3xIg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= +github.com/libp2p/go-libp2p-yamux v0.8.1/go.mod h1:rUozF8Jah2dL9LLGyBaBeTQeARdwhefMCTQVQt6QobE= +github.com/libp2p/go-libp2p-yamux v0.9.0 h1:j+gnKykADCI/3cZlacOYBjQXDsncxgcwzJ1zw6Z6pts= +github.com/libp2p/go-libp2p-yamux v0.9.0/go.mod h1:tpJKkRH9LlHj0VQh9Y9RP1pmF7yCS9ixxY/oSv+hhhQ= +github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= +github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= +github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= +github.com/libp2p/go-msgio v0.1.0 h1:8Q7g/528ivAlfXTFWvWhVjTE8XG8sDTkRUKPYh9+5Q8= +github.com/libp2p/go-msgio v0.1.0/go.mod h1:eNlv2vy9V2X/kNldcZ+SShFE++o2Yjxwx6RAYsmgJnE= +github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= +github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= +github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= +github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= +github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-reuseport v0.1.0 h1:0ooKOx2iwyIkf339WCZ2HN3ujTDbkK0PjC7JVoP1AiM= +github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= +github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7CyD1zuN7xQT8gc= +github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= +github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= +github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= +github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= +github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-tcp-transport v0.5.1 h1:edOOs688VLZAozWC7Kj5/6HHXKNwi9M6wgRmmLa8M6Q= +github.com/libp2p/go-tcp-transport v0.5.1/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-ws-transport v0.6.0 h1:326XBL6Q+5CQ2KtjXz32+eGu02W/Kz2+Fm4SpXdr0q4= +github.com/libp2p/go-ws-transport v0.6.0/go.mod h1:dXqtI9e2JV9FtF1NOtWVZSKXh5zXvnuwPXfj8GPBbYU= +github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.1.0 h1:2johPiST4xsXsqQ/38C2MAERw0hJ+t8oehHWA8F2R3Q= +github.com/libp2p/go-yamux/v3 v3.1.0/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4= +github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= +github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= +github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +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/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= +github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= +github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= +github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= +github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= +github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= +github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= +github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= +github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= +github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= +github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= +github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= +github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= +github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= +github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +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/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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +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.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +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/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/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-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/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-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +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-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/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/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= +github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= +github.com/raulk/go-watchdog v1.2.0 h1:konN75pw2BMmZ+AfuAm5rtFsWcJpKF3m02rKituuXNo= +github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +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/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sirupsen/logrus v1.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/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/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +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/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +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/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= +github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +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= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-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/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +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= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20200904194848-62affa334b73/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +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.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190219092855-153ac476189d/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-20190228124157-a34e9553db1e/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-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/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-20200124204421-9fbb57f87de9/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-20200602225109-6fdc65e7d980/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-20201214210602-f9fddec55a1e/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-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/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-20181130052023-1c3d964395ce/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= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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-20200103221440-774c71fcf114/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= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +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.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +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= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +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/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-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +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= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +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-20200513103714-09dca8ec2884/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.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/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.28.1/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/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +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= +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= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +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 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +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= +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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/opnode/l1/batching.go b/op-node/l1/batching.go similarity index 100% rename from opnode/l1/batching.go rename to op-node/l1/batching.go diff --git a/opnode/l1/batching_test.go b/op-node/l1/batching_test.go similarity index 98% rename from opnode/l1/batching_test.go rename to op-node/l1/batching_test.go index c625eb2a21b8..8af1de2da70d 100644 --- a/opnode/l1/batching_test.go +++ b/op-node/l1/batching_test.go @@ -6,7 +6,8 @@ import ( "fmt" "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" + "github.com/ethereum-optimism/optimism/op-node/testlog" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/assert" diff --git a/opnode/l1/receipts.go b/op-node/l1/receipts.go similarity index 98% rename from opnode/l1/receipts.go rename to op-node/l1/receipts.go index b808f9443aac..c304d80d05d6 100644 --- a/opnode/l1/receipts.go +++ b/op-node/l1/receipts.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" diff --git a/opnode/l1/request_sema.go b/op-node/l1/request_sema.go similarity index 100% rename from opnode/l1/request_sema.go rename to op-node/l1/request_sema.go diff --git a/opnode/l1/source.go b/op-node/l1/source.go similarity index 98% rename from opnode/l1/source.go rename to op-node/l1/source.go index 3b7d7db177cf..9cff4d7ebaf2 100644 --- a/opnode/l1/source.go +++ b/op-node/l1/source.go @@ -5,11 +5,12 @@ import ( "errors" "fmt" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" "github.com/ethereum/go-ethereum" + + "github.com/ethereum-optimism/optimism/op-node/rollup" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" diff --git a/opnode/l1/source_test.go b/op-node/l1/source_test.go similarity index 96% rename from opnode/l1/source_test.go rename to op-node/l1/source_test.go index 499d8a6aa934..b249492ba768 100644 --- a/opnode/l1/source_test.go +++ b/op-node/l1/source_test.go @@ -6,9 +6,10 @@ import ( "math/rand" "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/testlog" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" diff --git a/opnode/l1/types.go b/op-node/l1/types.go similarity index 96% rename from opnode/l1/types.go rename to op-node/l1/types.go index 0cce7ba1a4e5..79f1a66ddc1d 100644 --- a/opnode/l1/types.go +++ b/op-node/l1/types.go @@ -5,8 +5,8 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/trie" diff --git a/opnode/l2/api.go b/op-node/l2/api.go similarity index 99% rename from opnode/l2/api.go rename to op-node/l2/api.go index d2fb9c389e21..3f0911b0bdae 100644 --- a/opnode/l2/api.go +++ b/op-node/l2/api.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/opnode/l2/source.go b/op-node/l2/source.go similarity index 98% rename from opnode/l2/source.go rename to op-node/l2/source.go index 76eb3e9e5dbc..0eecf256ace9 100644 --- a/opnode/l2/source.go +++ b/op-node/l2/source.go @@ -8,9 +8,9 @@ import ( "github.com/ethereum/go-ethereum" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" diff --git a/opnode/l2/ssz.go b/op-node/l2/ssz.go similarity index 100% rename from opnode/l2/ssz.go rename to op-node/l2/ssz.go diff --git a/opnode/l2/ssz_test.go b/op-node/l2/ssz_test.go similarity index 100% rename from opnode/l2/ssz_test.go rename to op-node/l2/ssz_test.go diff --git a/opnode/l2/util.go b/op-node/l2/util.go similarity index 96% rename from opnode/l2/util.go rename to op-node/l2/util.go index 3d7531bb9414..c00a377ca5c1 100644 --- a/opnode/l2/util.go +++ b/op-node/l2/util.go @@ -6,8 +6,8 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb/memorydb" diff --git a/opnode/node/api.go b/op-node/node/api.go similarity index 96% rename from opnode/node/api.go rename to op-node/node/api.go index 1c7fcbd76237..f9aea2e9574e 100644 --- a/opnode/node/api.go +++ b/op-node/node/api.go @@ -7,13 +7,13 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/version" + "github.com/ethereum-optimism/optimism/op-node/version" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/predeploy" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "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/common/hexutil" diff --git a/opnode/node/bundle_builder.go b/op-node/node/bundle_builder.go similarity index 95% rename from opnode/node/bundle_builder.go rename to op-node/node/bundle_builder.go index 07e69567f765..01b7f3c32a85 100644 --- a/opnode/node/bundle_builder.go +++ b/op-node/node/bundle_builder.go @@ -1,8 +1,8 @@ package node import ( - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common/hexutil" ) diff --git a/opnode/node/bundle_builder_test.go b/op-node/node/bundle_builder_test.go similarity index 96% rename from opnode/node/bundle_builder_test.go rename to op-node/node/bundle_builder_test.go index 484aa0acbb63..a8c610a9f605 100644 --- a/opnode/node/bundle_builder_test.go +++ b/op-node/node/bundle_builder_test.go @@ -3,9 +3,9 @@ package node_test import ( "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/require" diff --git a/opnode/node/comms.go b/op-node/node/comms.go similarity index 85% rename from opnode/node/comms.go rename to op-node/node/comms.go index dbd9995500d6..fa2045aa024f 100644 --- a/opnode/node/comms.go +++ b/op-node/node/comms.go @@ -3,8 +3,8 @@ package node import ( "context" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l2" "github.com/libp2p/go-libp2p-core/peer" ) diff --git a/opnode/node/config.go b/op-node/node/config.go similarity index 91% rename from opnode/node/config.go rename to op-node/node/config.go index f541284d1d98..fcd9693eb5a7 100644 --- a/opnode/node/config.go +++ b/op-node/node/config.go @@ -3,9 +3,9 @@ package node import ( "fmt" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + "github.com/ethereum-optimism/optimism/op-node/p2p" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup" ) type Config struct { diff --git a/opnode/node/log.go b/op-node/node/log.go similarity index 100% rename from opnode/node/log.go rename to op-node/node/log.go diff --git a/opnode/node/node.go b/op-node/node/node.go similarity index 96% rename from opnode/node/node.go rename to op-node/node/node.go index 3dda11e7b600..021196880d18 100644 --- a/opnode/node/node.go +++ b/op-node/node/node.go @@ -8,16 +8,16 @@ import ( "github.com/libp2p/go-libp2p-core/peer" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + "github.com/ethereum-optimism/optimism/op-node/p2p" multierror "github.com/hashicorp/go-multierror" - "github.com/ethereum-optimism/optimistic-specs/opnode/backoff" + "github.com/ethereum-optimism/optimism/op-node/backoff" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l1" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/driver" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l1" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/event" diff --git a/opnode/node/server.go b/op-node/node/server.go similarity index 93% rename from opnode/node/server.go rename to op-node/node/server.go index 2bf47312cbca..91a29d34f882 100644 --- a/opnode/node/server.go +++ b/op-node/node/server.go @@ -7,10 +7,10 @@ import ( "net" "net/http" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" + "github.com/ethereum-optimism/optimism/op-node/p2p" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" diff --git a/opnode/node/server_test.go b/op-node/node/server_test.go similarity index 96% rename from opnode/node/server_test.go rename to op-node/node/server_test.go index cae68c396f8b..a9685df53f55 100644 --- a/opnode/node/server_test.go +++ b/op-node/node/server_test.go @@ -5,17 +5,18 @@ import ( "encoding/json" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/version" + "github.com/ethereum-optimism/optimism/op-node/version" "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/testlog" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/predeploy" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/stretchr/testify/mock" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimism/op-node/l2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" diff --git a/opnode/p2p/config.go b/op-node/p2p/config.go similarity index 99% rename from opnode/p2p/config.go rename to op-node/p2p/config.go index 502ede54cecf..6ed62612df52 100644 --- a/opnode/p2p/config.go +++ b/op-node/p2p/config.go @@ -18,7 +18,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/discover" "github.com/libp2p/go-libp2p-core/host" - "github.com/ethereum-optimism/optimistic-specs/opnode/flags" + "github.com/ethereum-optimism/optimism/op-node/flags" "github.com/ethereum/go-ethereum/p2p/enode" ds "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/sync" diff --git a/opnode/p2p/discovery.go b/op-node/p2p/discovery.go similarity index 100% rename from opnode/p2p/discovery.go rename to op-node/p2p/discovery.go diff --git a/opnode/p2p/gossip.go b/op-node/p2p/gossip.go similarity index 99% rename from opnode/p2p/gossip.go rename to op-node/p2p/gossip.go index 79eb3e9b363b..1390d0dfcb24 100644 --- a/opnode/p2p/gossip.go +++ b/op-node/p2p/gossip.go @@ -12,8 +12,8 @@ import ( "github.com/ethereum/go-ethereum/common" lru "github.com/hashicorp/golang-lru" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/golang/snappy" diff --git a/opnode/p2p/host.go b/op-node/p2p/host.go similarity index 100% rename from opnode/p2p/host.go rename to op-node/p2p/host.go diff --git a/opnode/p2p/host_test.go b/op-node/p2p/host_test.go similarity index 97% rename from opnode/p2p/host_test.go rename to op-node/p2p/host_test.go index ba5fb71fdf37..e218762686e3 100644 --- a/opnode/p2p/host_test.go +++ b/op-node/p2p/host_test.go @@ -8,9 +8,9 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" ds "github.com/ipfs/go-datastore" diff --git a/opnode/p2p/node.go b/op-node/p2p/node.go similarity index 98% rename from opnode/p2p/node.go rename to op-node/p2p/node.go index a9be4c2b2d39..d98b8919cb6a 100644 --- a/opnode/p2p/node.go +++ b/op-node/p2p/node.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" diff --git a/opnode/p2p/notifications.go b/op-node/p2p/notifications.go similarity index 100% rename from opnode/p2p/notifications.go rename to op-node/p2p/notifications.go diff --git a/opnode/p2p/prepared.go b/op-node/p2p/prepared.go similarity index 100% rename from opnode/p2p/prepared.go rename to op-node/p2p/prepared.go diff --git a/opnode/p2p/rpc_api.go b/op-node/p2p/rpc_api.go similarity index 100% rename from opnode/p2p/rpc_api.go rename to op-node/p2p/rpc_api.go diff --git a/opnode/p2p/rpc_client.go b/op-node/p2p/rpc_client.go similarity index 100% rename from opnode/p2p/rpc_client.go rename to op-node/p2p/rpc_client.go diff --git a/opnode/p2p/rpc_server.go b/op-node/p2p/rpc_server.go similarity index 100% rename from opnode/p2p/rpc_server.go rename to op-node/p2p/rpc_server.go diff --git a/opnode/p2p/signer.go b/op-node/p2p/signer.go similarity index 95% rename from opnode/p2p/signer.go rename to op-node/p2p/signer.go index e2a5cc2b53e3..ec171c0c5c27 100644 --- a/opnode/p2p/signer.go +++ b/op-node/p2p/signer.go @@ -8,8 +8,8 @@ import ( "io" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/flags" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/flags" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/urfave/cli" diff --git a/opnode/predeploy/predeploy.go b/op-node/predeploy/predeploy.go similarity index 100% rename from opnode/predeploy/predeploy.go rename to op-node/predeploy/predeploy.go diff --git a/opnode/rollup/derive/batch.go b/op-node/rollup/derive/batch.go similarity index 98% rename from opnode/rollup/derive/batch.go rename to op-node/rollup/derive/batch.go index 7c37fe73f44e..e43ac35a0e47 100644 --- a/opnode/rollup/derive/batch.go +++ b/op-node/rollup/derive/batch.go @@ -7,7 +7,7 @@ import ( "io" "sync" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rlp" ) diff --git a/opnode/rollup/derive/batch_test.go b/op-node/rollup/derive/batch_test.go similarity index 93% rename from opnode/rollup/derive/batch_test.go rename to op-node/rollup/derive/batch_test.go index 4914222620fc..ec447801ebb3 100644 --- a/opnode/rollup/derive/batch_test.go +++ b/op-node/rollup/derive/batch_test.go @@ -4,7 +4,7 @@ import ( "bytes" "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/assert" diff --git a/opnode/rollup/derive/doc.go b/op-node/rollup/derive/doc.go similarity index 100% rename from opnode/rollup/derive/doc.go rename to op-node/rollup/derive/doc.go diff --git a/opnode/rollup/derive/fuzz_parsers_test.go b/op-node/rollup/derive/fuzz_parsers_test.go similarity index 97% rename from opnode/rollup/derive/fuzz_parsers_test.go rename to op-node/rollup/derive/fuzz_parsers_test.go index 2894548724d9..f58ab89f3875 100644 --- a/opnode/rollup/derive/fuzz_parsers_test.go +++ b/op-node/rollup/derive/fuzz_parsers_test.go @@ -5,8 +5,8 @@ import ( "math/big" "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/l1block" + "github.com/ethereum-optimism/optimism/op-node/contracts/deposit" + "github.com/ethereum-optimism/optimism/op-node/contracts/l1block" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" diff --git a/opnode/rollup/derive/l1_block_info.go b/op-node/rollup/derive/l1_block_info.go similarity index 100% rename from opnode/rollup/derive/l1_block_info.go rename to op-node/rollup/derive/l1_block_info.go diff --git a/opnode/rollup/derive/l1_block_info_test.go b/op-node/rollup/derive/l1_block_info_test.go similarity index 98% rename from opnode/rollup/derive/l1_block_info_test.go rename to op-node/rollup/derive/l1_block_info_test.go index 983ab31402f1..c27935cce555 100644 --- a/opnode/rollup/derive/l1_block_info_test.go +++ b/op-node/rollup/derive/l1_block_info_test.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" diff --git a/opnode/rollup/derive/payload_attributes.go b/op-node/rollup/derive/payload_attributes.go similarity index 98% rename from opnode/rollup/derive/payload_attributes.go rename to op-node/rollup/derive/payload_attributes.go index e590cfab687e..638378d98cf6 100644 --- a/opnode/rollup/derive/payload_attributes.go +++ b/op-node/rollup/derive/payload_attributes.go @@ -6,8 +6,8 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/opnode/rollup/derive/payload_attributes_test.go b/op-node/rollup/derive/payload_attributes_test.go similarity index 99% rename from opnode/rollup/derive/payload_attributes_test.go rename to op-node/rollup/derive/payload_attributes_test.go index 7f975fe79125..8fa52cd4de8f 100644 --- a/opnode/rollup/derive/payload_attributes_test.go +++ b/op-node/rollup/derive/payload_attributes_test.go @@ -7,7 +7,7 @@ import ( "math/rand" "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/assert" diff --git a/opnode/rollup/driver/driver.go b/op-node/rollup/driver/driver.go similarity index 92% rename from opnode/rollup/driver/driver.go rename to op-node/rollup/driver/driver.go index 816caea9a626..faa1a3afff52 100644 --- a/opnode/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -4,11 +4,11 @@ import ( "context" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l1" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l1" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" diff --git a/opnode/rollup/driver/state.go b/op-node/rollup/driver/state.go similarity index 98% rename from opnode/rollup/driver/state.go rename to op-node/rollup/driver/state.go index 28aa6eff1f58..5c05210600b6 100644 --- a/opnode/rollup/driver/state.go +++ b/op-node/rollup/driver/state.go @@ -7,10 +7,10 @@ import ( gosync "sync" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/sync" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum/go-ethereum/log" ) diff --git a/opnode/rollup/driver/state_test.go b/op-node/rollup/driver/state_test.go similarity index 96% rename from opnode/rollup/driver/state_test.go rename to op-node/rollup/driver/state_test.go index edc4c745ccf1..d11ccd983e80 100644 --- a/opnode/rollup/driver/state_test.go +++ b/op-node/rollup/driver/state_test.go @@ -7,11 +7,11 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testutils" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/testlog" + "github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" diff --git a/opnode/rollup/driver/step.go b/op-node/rollup/driver/step.go similarity index 98% rename from opnode/rollup/driver/step.go rename to op-node/rollup/driver/step.go index e5f915cc9f83..c7282e71adec 100644 --- a/opnode/rollup/driver/step.go +++ b/op-node/rollup/driver/step.go @@ -8,10 +8,10 @@ import ( "math/big" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/opnode/rollup/sync/start.go b/op-node/rollup/sync/start.go similarity index 98% rename from opnode/rollup/sync/start.go rename to op-node/rollup/sync/start.go index 636f9326848d..5a21625cf663 100644 --- a/opnode/rollup/sync/start.go +++ b/op-node/rollup/sync/start.go @@ -23,9 +23,9 @@ // should be. We track two L2 head blocks: // // - The *unsafe L2 block*: This is the highest L2 block whose L1 origin is a plausible (1) -// extension of the canonical L1 chain (as known to the opnode). +// extension of the canonical L1 chain (as known to the op-node). // - The *safe L2 block*: This is the highest L2 block whose epoch's sequencing window is -// complete within the canonical L1 chain (as known to the opnode). +// complete within the canonical L1 chain (as known to the op-node). // // (1) Plausible meaning that the blockhash of the L2 block's L1 origin (as reported in the L1 // Attributes deposit within the L2 block) is not canonical at another height in the L1 chain, @@ -42,8 +42,8 @@ import ( "github.com/ethereum/go-ethereum/common" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" ) type L1Chain interface { @@ -81,9 +81,9 @@ func isAheadOrCanonical(ctx context.Context, l1 L1Chain, block eth.BlockID) (ahe // L2 blocks. // // - The *unsafe L2 block*: This is the highest L2 block whose L1 origin is a plausible (1) -// extension of the canonical L1 chain (as known to the opnode). +// extension of the canonical L1 chain (as known to the op-node). // - The *safe L2 block*: This is the highest L2 block whose epoch's sequencing window is -// complete within the canonical L1 chain (as known to the opnode). +// complete within the canonical L1 chain (as known to the op-node). // // (1) Plausible meaning that the blockhash of the L2 block's L1 origin (as reported in the L1 // Attributes deposit within the L2 block) is not canonical at another height in the L1 chain, diff --git a/opnode/rollup/sync/start_test.go b/op-node/rollup/sync/start_test.go similarity index 95% rename from opnode/rollup/sync/start_test.go rename to op-node/rollup/sync/start_test.go index 946aca8467c7..3946ccec2724 100644 --- a/opnode/rollup/sync/start_test.go +++ b/op-node/rollup/sync/start_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testlog" - "github.com/ethereum-optimism/optimistic-specs/opnode/internal/testutils" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/testlog" + "github.com/ethereum-optimism/optimism/op-node/testutils" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" ) diff --git a/opnode/rollup/types.go b/op-node/rollup/types.go similarity index 97% rename from opnode/rollup/types.go rename to op-node/rollup/types.go index 20d97121ad75..20fa741de80e 100644 --- a/opnode/rollup/types.go +++ b/op-node/rollup/types.go @@ -5,7 +5,7 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) diff --git a/opnode/rollup/types_test.go b/op-node/rollup/types_test.go similarity index 94% rename from opnode/rollup/types_test.go rename to op-node/rollup/types_test.go index 23fb24b1c5df..19895522cba4 100644 --- a/opnode/rollup/types_test.go +++ b/op-node/rollup/types_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" ) diff --git a/opnode/service.go b/op-node/service.go similarity index 91% rename from opnode/service.go rename to op-node/service.go index bfe74f27bb7d..41626b887880 100644 --- a/opnode/service.go +++ b/op-node/service.go @@ -7,10 +7,10 @@ import ( "github.com/ethereum/go-ethereum/log" - "github.com/ethereum-optimism/optimistic-specs/opnode/flags" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" - "github.com/ethereum-optimism/optimistic-specs/opnode/p2p" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/flags" + "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/urfave/cli" ) diff --git a/opnode/internal/testlog/LICENSE b/op-node/testlog/LICENSE similarity index 100% rename from opnode/internal/testlog/LICENSE rename to op-node/testlog/LICENSE diff --git a/opnode/internal/testlog/README.md b/op-node/testlog/README.md similarity index 100% rename from opnode/internal/testlog/README.md rename to op-node/testlog/README.md diff --git a/opnode/internal/testlog/testlog.go b/op-node/testlog/testlog.go similarity index 100% rename from opnode/internal/testlog/testlog.go rename to op-node/testlog/testlog.go diff --git a/opnode/internal/testutils/fake_chain.go b/op-node/testutils/fake_chain.go similarity index 97% rename from opnode/internal/testutils/fake_chain.go rename to op-node/testutils/fake_chain.go index abbb17cfd341..ec1c601343fe 100644 --- a/opnode/internal/testutils/fake_chain.go +++ b/op-node/testutils/fake_chain.go @@ -6,12 +6,13 @@ import ( "math/big" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum-optimism/optimistic-specs/opnode/eth" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/rollup" + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/rollup" ) func FakeGenesis(l1 rune, l2 rune, l1GenesisNumber int) rollup.Genesis { diff --git a/opnode/version/version.go b/op-node/version/version.go similarity index 100% rename from opnode/version/version.go rename to op-node/version/version.go diff --git a/opnode/withdrawals/proof.go b/op-node/withdrawals/proof.go similarity index 100% rename from opnode/withdrawals/proof.go rename to op-node/withdrawals/proof.go diff --git a/opnode/withdrawals/utils.go b/op-node/withdrawals/utils.go similarity index 96% rename from opnode/withdrawals/utils.go rename to op-node/withdrawals/utils.go index 9fc475a348cb..a6403e1ffa59 100644 --- a/opnode/withdrawals/utils.go +++ b/op-node/withdrawals/utils.go @@ -7,10 +7,10 @@ import ( "math/big" "time" - "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/deposit" - "github.com/ethereum-optimism/optimistic-specs/opnode/contracts/withdrawer" - "github.com/ethereum-optimism/optimistic-specs/opnode/predeploy" + "github.com/ethereum-optimism/optimism/op-node/contracts/deposit" + "github.com/ethereum-optimism/optimism/op-node/contracts/withdrawer" + "github.com/ethereum-optimism/optimism/op-node/predeploy" + "github.com/ethereum-optimism/optimism/op-proposer/bindings/l2oo" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -121,7 +121,7 @@ type Client struct { } // Ensure that ProofClient and Client interfaces are valid -var _ ProofClient = Client{} +var _ ProofClient = &Client{} // NewClient wraps a RPC client with both ethclient and gethclient methods. // Implements ProofClient diff --git a/l2os/.gitignore b/op-proposer/.gitignore similarity index 100% rename from l2os/.gitignore rename to op-proposer/.gitignore diff --git a/l2os/Makefile b/op-proposer/Makefile similarity index 88% rename from l2os/Makefile rename to op-proposer/Makefile index 3b5d4758204d..1d7e2f5e5d65 100644 --- a/l2os/Makefile +++ b/op-proposer/Makefile @@ -7,11 +7,11 @@ LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) LDFLAGSSTRING +=-X main.Version=$(VERSION) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" -l2os: - env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/l2os +op-proposer: + env GO111MODULE=on go build -v $(LDFLAGS) -o ./bin/op-proposer ./cmd clean: - rm l2os + rm bin/op-proposer test: go test -v ./... @@ -38,6 +38,6 @@ bindings-l2-output-oracle: bindings \ bindings-mock-l2-output-oracle \ clean \ - l2os \ + op-proposer \ test \ lint diff --git a/l2os/bindings/l2oo/l2_output_oracle.go b/op-proposer/bindings/l2oo/l2_output_oracle.go similarity index 100% rename from l2os/bindings/l2oo/l2_output_oracle.go rename to op-proposer/bindings/l2oo/l2_output_oracle.go diff --git a/l2os/cmd/l2os/main.go b/op-proposer/cmd/main.go similarity index 81% rename from l2os/cmd/l2os/main.go rename to op-proposer/cmd/main.go index ee3f3c0a7459..13720714b22d 100644 --- a/l2os/cmd/l2os/main.go +++ b/op-proposer/cmd/main.go @@ -4,11 +4,12 @@ import ( "fmt" "os" + proposer "github.com/ethereum-optimism/optimism/op-proposer" + "github.com/ethereum/go-ethereum/log" "github.com/urfave/cli" - "github.com/ethereum-optimism/optimistic-specs/l2os" - "github.com/ethereum-optimism/optimistic-specs/l2os/flags" + "github.com/ethereum-optimism/optimism/op-proposer/flags" ) var ( @@ -30,12 +31,12 @@ func main() { app := cli.NewApp() app.Flags = flags.Flags app.Version = fmt.Sprintf("%s-%s-%s", Version, GitCommit, GitDate) - app.Name = "l2os" + app.Name = "op-proposer" app.Usage = "L2Output Submitter" app.Description = "Service for generating and submitting L2 Output " + "checkpoints to the L2OutputOracle contract" - app.Action = l2os.Main(Version) + app.Action = proposer.Main(Version) err := app.Run(os.Args) if err != nil { log.Crit("Application failed", "message", err) diff --git a/l2os/config.go b/op-proposer/config.go similarity index 97% rename from l2os/config.go rename to op-proposer/config.go index 3cb21e336d1b..c319550f688d 100644 --- a/l2os/config.go +++ b/op-proposer/config.go @@ -1,11 +1,11 @@ -package l2os +package op_proposer import ( "time" "github.com/urfave/cli" - "github.com/ethereum-optimism/optimistic-specs/l2os/flags" + "github.com/ethereum-optimism/optimism/op-proposer/flags" ) type Config struct { diff --git a/l2os/drivers/interface.go b/op-proposer/drivers/interface.go similarity index 100% rename from l2os/drivers/interface.go rename to op-proposer/drivers/interface.go diff --git a/l2os/drivers/l2output/driver.go b/op-proposer/drivers/l2output/driver.go similarity index 97% rename from l2os/drivers/l2output/driver.go rename to op-proposer/drivers/l2output/driver.go index b38759d23f54..21272f65256f 100644 --- a/l2os/drivers/l2output/driver.go +++ b/op-proposer/drivers/l2output/driver.go @@ -7,9 +7,9 @@ import ( "math/big" "strings" - "github.com/ethereum-optimism/optimistic-specs/l2os/bindings/l2oo" - "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-proposer/bindings/l2oo" + "github.com/ethereum-optimism/optimism/op-proposer/rollupclient" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" diff --git a/l2os/flags/flags.go b/op-proposer/flags/flags.go similarity index 100% rename from l2os/flags/flags.go rename to op-proposer/flags/flags.go diff --git a/l2os/flags/flags_test.go b/op-proposer/flags/flags_test.go similarity index 100% rename from l2os/flags/flags_test.go rename to op-proposer/flags/flags_test.go diff --git a/op-proposer/go.mod b/op-proposer/go.mod new file mode 100644 index 000000000000..f00201fe60d1 --- /dev/null +++ b/op-proposer/go.mod @@ -0,0 +1,157 @@ +module github.com/ethereum-optimism/optimism/op-proposer + +go 1.18 + +require ( + github.com/ethereum-optimism/optimism/op-node v0.0.0 + github.com/ethereum/go-ethereum v1.10.16 + github.com/miguelmota/go-ethereum-hdwallet v0.1.1 + github.com/stretchr/testify v1.7.0 + github.com/urfave/cli v1.22.5 +) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/benbjohnson/clock v1.1.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 // indirect + github.com/coreos/go-systemd/v22 v22.1.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/flynn/noise v1.0.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/godbus/dbus/v5 v5.0.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.3.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/gopacket v1.1.19 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/hashicorp/go-multierror v1.0.0 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/ipfs/go-cid v0.0.7 // indirect + github.com/ipfs/go-datastore v0.5.0 // indirect + github.com/ipfs/go-ds-leveldb v0.5.0 // indirect + github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/ipfs/go-log v1.0.5 // indirect + github.com/ipfs/go-log/v2 v2.5.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/koron/go-ssdp v0.0.2 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/libp2p/go-cidranger v1.1.0 // indirect + github.com/libp2p/go-conn-security-multistream v0.3.0 // indirect + github.com/libp2p/go-eventbus v0.2.1 // indirect + github.com/libp2p/go-flow-metrics v0.0.3 // indirect + github.com/libp2p/go-libp2p v0.18.1 // indirect + github.com/libp2p/go-libp2p-asn-util v0.1.0 // indirect + github.com/libp2p/go-libp2p-blankhost v0.3.0 // indirect + github.com/libp2p/go-libp2p-core v0.15.0 // indirect + github.com/libp2p/go-libp2p-discovery v0.6.0 // indirect + github.com/libp2p/go-libp2p-mplex v0.6.0 // indirect + github.com/libp2p/go-libp2p-nat v0.1.0 // indirect + github.com/libp2p/go-libp2p-noise v0.3.0 // indirect + github.com/libp2p/go-libp2p-peerstore v0.6.0 // indirect + github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect + github.com/libp2p/go-libp2p-pubsub v0.6.1 // indirect + github.com/libp2p/go-libp2p-swarm v0.10.2 // indirect + github.com/libp2p/go-libp2p-testing v0.9.2 // indirect + github.com/libp2p/go-libp2p-tls v0.3.1 // indirect + github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 // indirect + github.com/libp2p/go-libp2p-yamux v0.9.0 // indirect + github.com/libp2p/go-mplex v0.6.0 // indirect + github.com/libp2p/go-msgio v0.1.0 // indirect + github.com/libp2p/go-nat v0.1.0 // indirect + github.com/libp2p/go-netroute v0.2.0 // indirect + github.com/libp2p/go-openssl v0.0.7 // indirect + github.com/libp2p/go-reuseport v0.1.0 // indirect + github.com/libp2p/go-reuseport-transport v0.1.0 // indirect + github.com/libp2p/go-stream-muxer-multistream v0.4.0 // indirect + github.com/libp2p/go-tcp-transport v0.5.1 // indirect + github.com/libp2p/go-yamux/v3 v3.1.0 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/miekg/dns v1.1.43 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr v0.5.0 // indirect + github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.0.3 // indirect + github.com/multiformats/go-multicodec v0.4.1 // indirect + github.com/multiformats/go-multihash v0.0.15 // indirect + github.com/multiformats/go-multistream v0.2.2 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.11.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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/raulk/clock v1.1.0 // indirect + github.com/raulk/go-watchdog v1.2.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect + github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.19.1 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + google.golang.org/grpc v1.40.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/urfave/cli.v1 v1.20.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) + +replace github.com/ethereum-optimism/optimism/op-node v0.0.0 => ../op-node + +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead diff --git a/op-proposer/go.sum b/op-proposer/go.sum new file mode 100644 index 000000000000..b65acda124db --- /dev/null +++ b/op-proposer/go.sum @@ -0,0 +1,1611 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.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.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +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/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +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/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +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/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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +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/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +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/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +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/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +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/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +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/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 h1:7grrpcfCtbZLsjtB0DgMuzs1umsJmpzaHMZ6cO6iAWw= +github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= +github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +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/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= +github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= +github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +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-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +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/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead h1:AiLggtwXHmAGxNusOEH7edb83TtJnavtR2uY1z6YzYc= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= +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/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= +github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +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/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +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/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +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-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +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 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +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/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +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= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +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.2/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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +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.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= +github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/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/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +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/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= +github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-datastore v0.5.0 h1:rQicVCEacWyk4JZ6G5bD9TKR7lZEG1MWcG7UdWYrFAU= +github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= +github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= +github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= +github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= +github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= +github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= +github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= +github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= +github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= +github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +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/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= +github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= +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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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/libp2p/go-addr-util v0.1.0/go.mod h1:6I3ZYuFr2O/9D+SoyM0zEw0EF3YkldtTX406BpdQMqw= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= +github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= +github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= +github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= +github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-libp2p v0.18.1 h1:IK9EOGNO2ZghU4F+dx9c4xfhMNZr45x06CijJaZE/ms= +github.com/libp2p/go-libp2p v0.18.1/go.mod h1:ll44MqmrIFKpL3BwCexxzm+7RZ8exEtN96V1rRdMG7Y= +github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= +github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= +github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= +github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= +github.com/libp2p/go-libp2p-circuit v0.6.0 h1:rw/HlhmUB3OktS/Ygz6+2XABOmHKzZpPUuMNUMosj8w= +github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= +github.com/libp2p/go-libp2p-connmgr v0.2.4 h1:TMS0vc0TCBomtQJyWr7fYxcVYYhx+q/2gF++G5Jkl/w= +github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJfdCGv51mTmdpmM= +github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.11.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= +github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= +github.com/libp2p/go-libp2p-core v0.15.0 h1:hKpgy/bRVwO7Ah5x9u92Vo+gogAaOolafZF5kW0rVm0= +github.com/libp2p/go-libp2p-core v0.15.0/go.mod h1:agSaboYM4hzB1cWekgVReqV5M4g5M+2eNNejV+1EEhs= +github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= +github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= +github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= +github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= +github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= +github.com/libp2p/go-libp2p-nat v0.1.0 h1:vigUi2MEN+fwghe5ijpScxtbbDz+L/6y8XwlzYOJgSY= +github.com/libp2p/go-libp2p-nat v0.1.0/go.mod h1:DQzAG+QbDYjN1/C3B6vXucLtz3u9rEonLVPtZVzQqks= +github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= +github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= +github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= +github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnHd/VBjL4mY5A= +github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= +github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= +github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= +github.com/libp2p/go-libp2p-pubsub v0.6.1 h1:wycbV+f4rreCoVY61Do6g/BUk0RIrbNRcYVbn+QkjGk= +github.com/libp2p/go-libp2p-pubsub v0.6.1/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= +github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= +github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-quic-transport v0.16.1 h1:N/XqYXHurphPLDfXYhll8NyqzdZYQqAF4GIr7+SmLV8= +github.com/libp2p/go-libp2p-quic-transport v0.16.1/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-resource-manager v0.2.0 h1:Ul/k5d5StIpAtq7IapAEGh/2+0rwsJGXYJ6Kbzeedtc= +github.com/libp2p/go-libp2p-resource-manager v0.2.0/go.mod h1:K+eCkiapf+ey/LADO4TaMpMTP9/Qde/uLlrnRqV4PLQ= +github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= +github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= +github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= +github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= +github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= +github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= +github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= +github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= +github.com/libp2p/go-libp2p-testing v0.9.2 h1:dCpODRtRaDZKF8HXT9qqqgON+OMEB423Knrgeod8j84= +github.com/libp2p/go-libp2p-testing v0.9.2/go.mod h1:Td7kbdkWqYTJYQGTwzlgXwaqldraIanyjuRiAbK/XQU= +github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= +github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= +github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 h1:MSMe+tUfxpC9GArTz7a4G5zQKQgGh00Vio87d3j3xIg= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.1/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= +github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= +github.com/libp2p/go-libp2p-yamux v0.8.1/go.mod h1:rUozF8Jah2dL9LLGyBaBeTQeARdwhefMCTQVQt6QobE= +github.com/libp2p/go-libp2p-yamux v0.9.0 h1:j+gnKykADCI/3cZlacOYBjQXDsncxgcwzJ1zw6Z6pts= +github.com/libp2p/go-libp2p-yamux v0.9.0/go.mod h1:tpJKkRH9LlHj0VQh9Y9RP1pmF7yCS9ixxY/oSv+hhhQ= +github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= +github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= +github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= +github.com/libp2p/go-msgio v0.1.0 h1:8Q7g/528ivAlfXTFWvWhVjTE8XG8sDTkRUKPYh9+5Q8= +github.com/libp2p/go-msgio v0.1.0/go.mod h1:eNlv2vy9V2X/kNldcZ+SShFE++o2Yjxwx6RAYsmgJnE= +github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= +github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= +github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= +github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= +github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-reuseport v0.1.0 h1:0ooKOx2iwyIkf339WCZ2HN3ujTDbkK0PjC7JVoP1AiM= +github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= +github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7CyD1zuN7xQT8gc= +github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= +github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= +github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= +github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= +github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-tcp-transport v0.5.1 h1:edOOs688VLZAozWC7Kj5/6HHXKNwi9M6wgRmmLa8M6Q= +github.com/libp2p/go-tcp-transport v0.5.1/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-ws-transport v0.6.0 h1:326XBL6Q+5CQ2KtjXz32+eGu02W/Kz2+Fm4SpXdr0q4= +github.com/libp2p/go-ws-transport v0.6.0/go.mod h1:dXqtI9e2JV9FtF1NOtWVZSKXh5zXvnuwPXfj8GPBbYU= +github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.1.0 h1:2johPiST4xsXsqQ/38C2MAERw0hJ+t8oehHWA8F2R3Q= +github.com/libp2p/go-yamux/v3 v3.1.0/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4= +github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= +github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= +github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +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/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= +github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= +github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= +github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= +github.com/miguelmota/go-ethereum-hdwallet v0.1.1/go.mod h1:f9m9uXokAHA6WNoYOPjj4AqjJS5pquQRiYYj/XSyPYc= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= +github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= +github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= +github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= +github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= +github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= +github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= +github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= +github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= +github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= +github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= +github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +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/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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +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.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +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/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/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-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/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-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +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-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/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/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= +github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= +github.com/raulk/go-watchdog v1.2.0 h1:konN75pw2BMmZ+AfuAm5rtFsWcJpKF3m02rKituuXNo= +github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +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/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sirupsen/logrus v1.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/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/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +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/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +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/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= +github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +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= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-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/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +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= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20200904194848-62affa334b73/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +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.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190219092855-153ac476189d/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-20190228124157-a34e9553db1e/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-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/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-20200124204421-9fbb57f87de9/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-20200602225109-6fdc65e7d980/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-20201214210602-f9fddec55a1e/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-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/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-20181130052023-1c3d964395ce/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= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-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-20200103221440-774c71fcf114/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= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +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.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +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= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +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/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-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +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= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +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-20200513103714-09dca8ec2884/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.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/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.28.1/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/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +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= +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= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +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= +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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/l2os/l2_output_submitter.go b/op-proposer/l2_output_submitter.go similarity index 96% rename from l2os/l2_output_submitter.go rename to op-proposer/l2_output_submitter.go index 202d9618f618..111b046c90d1 100644 --- a/l2os/l2_output_submitter.go +++ b/op-proposer/l2_output_submitter.go @@ -1,4 +1,4 @@ -package l2os +package op_proposer import ( "context" @@ -8,9 +8,9 @@ import ( "syscall" "time" - "github.com/ethereum-optimism/optimistic-specs/l2os/drivers/l2output" - "github.com/ethereum-optimism/optimistic-specs/l2os/rollupclient" - "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum-optimism/optimism/op-proposer/drivers/l2output" + "github.com/ethereum-optimism/optimism/op-proposer/rollupclient" + "github.com/ethereum-optimism/optimism/op-proposer/txmgr" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" diff --git a/l2os/mock/l1client.go b/op-proposer/mock/l1client.go similarity index 100% rename from l2os/mock/l1client.go rename to op-proposer/mock/l1client.go diff --git a/l2os/rollupclient/rollupclient.go b/op-proposer/rollupclient/rollupclient.go similarity index 87% rename from l2os/rollupclient/rollupclient.go rename to op-proposer/rollupclient/rollupclient.go index 7b6033bc1ea7..3607bf66e181 100644 --- a/l2os/rollupclient/rollupclient.go +++ b/op-proposer/rollupclient/rollupclient.go @@ -4,8 +4,8 @@ import ( "context" "math/big" - "github.com/ethereum-optimism/optimistic-specs/opnode/l2" - "github.com/ethereum-optimism/optimistic-specs/opnode/node" + "github.com/ethereum-optimism/optimism/op-node/l2" + "github.com/ethereum-optimism/optimism/op-node/node" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" ) diff --git a/l2os/service.go b/op-proposer/service.go similarity index 98% rename from l2os/service.go rename to op-proposer/service.go index aa88e758ce67..530d30e69dfb 100644 --- a/l2os/service.go +++ b/op-proposer/service.go @@ -1,4 +1,4 @@ -package l2os +package op_proposer import ( "context" @@ -6,7 +6,7 @@ import ( "sync" "time" - "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum-optimism/optimism/op-proposer/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" diff --git a/l2os/txmgr/send_state.go b/op-proposer/txmgr/send_state.go similarity index 100% rename from l2os/txmgr/send_state.go rename to op-proposer/txmgr/send_state.go diff --git a/l2os/txmgr/send_state_test.go b/op-proposer/txmgr/send_state_test.go similarity index 98% rename from l2os/txmgr/send_state_test.go rename to op-proposer/txmgr/send_state_test.go index 42d16342c5cd..d0c5a1c960cf 100644 --- a/l2os/txmgr/send_state_test.go +++ b/op-proposer/txmgr/send_state_test.go @@ -4,7 +4,7 @@ import ( "errors" "testing" - "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum-optimism/optimism/op-proposer/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/stretchr/testify/require" diff --git a/l2os/txmgr/txmgr.go b/op-proposer/txmgr/txmgr.go similarity index 100% rename from l2os/txmgr/txmgr.go rename to op-proposer/txmgr/txmgr.go diff --git a/l2os/txmgr/txmgr_test.go b/op-proposer/txmgr/txmgr_test.go similarity index 99% rename from l2os/txmgr/txmgr_test.go rename to op-proposer/txmgr/txmgr_test.go index 8c99c3012b9e..ad47beaa9fb8 100644 --- a/l2os/txmgr/txmgr_test.go +++ b/op-proposer/txmgr/txmgr_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimistic-specs/l2os/txmgr" + "github.com/ethereum-optimism/optimism/op-proposer/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" diff --git a/ops-bedrock/Dockerfile.batcher b/ops-bedrock/Dockerfile.batcher new file mode 100644 index 000000000000..86ecf67e585d --- /dev/null +++ b/ops-bedrock/Dockerfile.batcher @@ -0,0 +1,17 @@ +FROM golang:1.18.0-alpine3.15 as builder + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +COPY ./op-node /app/op-node +COPY ./op-proposer /app/op-proposer +COPY ./op-batcher /app/op-batcher + +WORKDIR /app/op-batcher + +RUN make op-batcher + +FROM alpine:3.15 + +COPY --from=builder /app/op-batcher/bin/op-batcher /usr/local/bin + +ENTRYPOINT ["op-batcher"] diff --git a/ops/Dockerfile.l1 b/ops-bedrock/Dockerfile.l1 similarity index 100% rename from ops/Dockerfile.l1 rename to ops-bedrock/Dockerfile.l1 diff --git a/ops/Dockerfile.l2 b/ops-bedrock/Dockerfile.l2 similarity index 100% rename from ops/Dockerfile.l2 rename to ops-bedrock/Dockerfile.l2 diff --git a/ops-bedrock/Dockerfile.node b/ops-bedrock/Dockerfile.node new file mode 100644 index 000000000000..da5bb2283cf0 --- /dev/null +++ b/ops-bedrock/Dockerfile.node @@ -0,0 +1,19 @@ +FROM golang:1.18.0-alpine3.15 as builder + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +COPY ./op-node/go.mod /app/op-node/go.mod +COPY ./op-node/go.sum /app/op-node/go.sum + +WORKDIR /app/op-node +RUN go mod download -x + +COPY ./op-node /app/op-node + +RUN make op-node + +FROM alpine:3.15 + +COPY --from=builder /app/op-node/bin/op-node /usr/local/bin + +CMD ["op-node"] diff --git a/ops-bedrock/Dockerfile.proposer b/ops-bedrock/Dockerfile.proposer new file mode 100644 index 000000000000..bbd37b613ae5 --- /dev/null +++ b/ops-bedrock/Dockerfile.proposer @@ -0,0 +1,16 @@ +FROM golang:1.18.0-alpine3.15 as builder + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +COPY ./op-node /app/op-node +COPY ./op-proposer /app/op-proposer + +WORKDIR /app/op-proposer + +RUN make op-proposer + +FROM alpine:3.15 + +COPY --from=builder /app/op-proposer/bin/op-proposer /usr/local/bin + +CMD ["op-proposer"] diff --git a/ops/Dockerfile.stateviz b/ops-bedrock/Dockerfile.stateviz similarity index 64% rename from ops/Dockerfile.stateviz rename to ops-bedrock/Dockerfile.stateviz index 009a25b2bc20..937c3edb6e85 100644 --- a/ops/Dockerfile.stateviz +++ b/ops-bedrock/Dockerfile.stateviz @@ -2,15 +2,15 @@ FROM golang:1.18.0-alpine3.15 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 +COPY ./op-node/go.mod /app/go.mod +COPY ./op-node/go.sum /app/go.sum WORKDIR /app RUN go mod download -x -COPY ./opnode /app/opnode +COPY ./op-node /app -RUN go build -o ./bin/stateviz ./opnode/cmd/stateviz +RUN go build -o ./bin/stateviz ./cmd/stateviz FROM alpine:3.15 diff --git a/ops/devnet-up.sh b/ops-bedrock/devnet-up.sh similarity index 94% rename from ops/devnet-up.sh rename to ops-bedrock/devnet-up.sh index 9b3886443bf9..a51915caf2f0 100755 --- a/ops/devnet-up.sh +++ b/ops-bedrock/devnet-up.sh @@ -58,13 +58,13 @@ if [ ! -f ./.devnet/genesis-l1.json ]; then echo "Regenerating L1 genesis." mkdir -p ./.devnet GENESIS_TIMESTAMP=$(date +%s | xargs printf "0x%x") - jq ". | .timestamp = \"$GENESIS_TIMESTAMP\" " < ./ops/genesis-l1.json > ./.devnet/genesis-l1.json + jq ". | .timestamp = \"$GENESIS_TIMESTAMP\" " < ./ops-bedrock/genesis-l1.json > ./.devnet/genesis-l1.json else GENESIS_TIMESTAMP=$(jq -r '.timestamp' < ./.devnet/genesis-l1.json) fi # Bring up L1. -cd ops +cd ops-bedrock echo "Bringing up L1..." DOCKER_BUILDKIT=1 docker-compose build docker-compose up -d l1 @@ -97,7 +97,7 @@ L2OO_ADDRESS=$(jq -r .address < ./packages/contracts/deployments/devnetL1/L2Outp # Replace values in the L2 genesis file. It doesn't matter if this gets run every time, # since the replaced values will be the same. -jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$L1_BLOCK_INFO_BYTECODE\"" < ./ops/genesis-l2.json | \ +jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$L1_BLOCK_INFO_BYTECODE\"" < ./ops-bedrock/genesis-l2.json | \ jq ". | .alloc.\"4200000000000000000000000000000000000015\".balance = \"0x0\"" | \ jq ". | .alloc.\"4200000000000000000000000000000000000000\".code = \"$L2_TO_L1_MESSAGE_PASSER_BYTECODE\"" | \ jq ". | .alloc.\"4200000000000000000000000000000000000000\".balance = \"0x0\"" | \ @@ -110,7 +110,7 @@ jq ". | .alloc.\"4200000000000000000000000000000000000015\".code = \"$L1_BLOCK_I jq ". | .timestamp = \"$GENESIS_TIMESTAMP\" " > ./.devnet/genesis-l2.json # Bring up L2. -cd ops +cd ops-bedrock echo "Bringing up L2..." docker-compose up -d l2 wait_up $L2_URL @@ -144,22 +144,22 @@ L2_GENESIS=$(curl \ $L2_URL) # Generate the rollup config. -jq ". | .genesis.l1.hash = \"$(echo $L1_GENESIS | jq -r '.result.hash')\"" < ./ops/rollup.json | \ +jq ". | .genesis.l1.hash = \"$(echo $L1_GENESIS | jq -r '.result.hash')\"" < ./ops-bedrock/rollup.json | \ jq ". | .genesis.l2.hash = \"$(echo $L2_GENESIS | jq -r '.result.hash')\"" | \ jq ". | .genesis.l2_time = $(echo $L2_GENESIS | jq -r '.result.timestamp' | xargs printf "%d")" | \ jq ". | .deposit_contract_address = \"$DEPOSIT_CONTRACT_ADDRESS\"" > ./.devnet/rollup.json SEQUENCER_GENESIS_HASH="$(echo $L2_GENESIS | jq -r '.result.hash')" -SEQUENCER_BATCH_INBOX_ADDRESS="$(cat ./ops/rollup.json | jq -r '.batch_inbox_address')" +SEQUENCER_BATCH_INBOX_ADDRESS="$(cat ./ops-bedrock/rollup.json | jq -r '.batch_inbox_address')" # Bring up everything else. -cd ops +cd ops-bedrock echo "Bringing up devnet..." L2OO_ADDRESS="$L2OO_ADDRESS" \ SEQUENCER_GENESIS_HASH="$SEQUENCER_GENESIS_HASH" \ SEQUENCER_BATCH_INBOX_ADDRESS="$SEQUENCER_BATCH_INBOX_ADDRESS" \ - docker-compose up -d l2os bss + docker-compose up -d op-proposer op-batcher echo "Bringin up stateviz webserver..." docker-compose up -d stateviz diff --git a/ops/docker-compose.yml b/ops-bedrock/docker-compose.yml similarity index 89% rename from ops/docker-compose.yml rename to ops-bedrock/docker-compose.yml index dee41081873b..c8901556cd81 100644 --- a/ops/docker-compose.yml +++ b/ops-bedrock/docker-compose.yml @@ -31,15 +31,15 @@ services: - "l2_data:/db" - ${PWD}/../.devnet/genesis-l2.json:/genesis.json - opnode: + op-node: depends_on: - l1 - l2 build: context: ../ - dockerfile: ./ops/Dockerfile.opnode + dockerfile: ./ops-bedrock/Dockerfile.node command: > - op + op-node --l1=ws://l1:8546 --l2=ws://l2:8546 --sequencing.enabled @@ -62,18 +62,18 @@ services: - ${PWD}/../.devnet/rollup.json:/rollup.json - op_log:/op_log - l2os: + op-proposer: depends_on: - l1 - l2 - - opnode + - op-node build: context: ../ - dockerfile: ./ops/Dockerfile.l2os + dockerfile: ./ops-bedrock/Dockerfile.proposer environment: L1_ETH_RPC: http://l1:8545 L2_ETH_RPC: http://l2:8545 - ROLLUP_RPC: http://opnode:8545 + ROLLUP_RPC: http://op-node:8545 OUTPUT_SUBMITTER_POLL_INTERVAL: 10s OUTPUT_SUBMITTER_NUM_CONFIRMATIONS: 1 OUTPUT_SUBMITTER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 @@ -83,18 +83,18 @@ services: OUTPUT_SUBMITTER_LOG_TERMINAL: "true" L2OO_ADDRESS: "${L2OO_ADDRESS}" - bss: + op-batcher: depends_on: - l1 - l2 - - opnode + - op-node build: context: ../ - dockerfile: ./ops/Dockerfile.bss + dockerfile: ./ops-bedrock/Dockerfile.batcher environment: L1_ETH_RPC: http://l1:8545 L2_ETH_RPC: http://l2:8545 - ROLLUP_RPC: http://opnode:8545 + ROLLUP_RPC: http://op-node:8545 BATCH_SUBMITTER_MIN_L1_TX_SIZE_BYTES: 1 BATCH_SUBMITTER_MAX_L1_TX_SIZE_BYTES: 120000 BATCH_SUBMITTER_POLL_INTERVAL: 1s @@ -111,7 +111,7 @@ services: stateviz: build: context: ../ - dockerfile: ./ops/Dockerfile.stateviz + dockerfile: ./ops-bedrock/Dockerfile.stateviz command: - stateviz - -addr=0.0.0.0:8080 diff --git a/ops/entrypoint.sh b/ops-bedrock/entrypoint.sh similarity index 100% rename from ops/entrypoint.sh rename to ops-bedrock/entrypoint.sh diff --git a/ops/genesis-l1.json b/ops-bedrock/genesis-l1.json similarity index 100% rename from ops/genesis-l1.json rename to ops-bedrock/genesis-l1.json diff --git a/ops/genesis-l2.json b/ops-bedrock/genesis-l2.json similarity index 100% rename from ops/genesis-l2.json rename to ops-bedrock/genesis-l2.json diff --git a/ops/bss-entrypoint.sh b/ops-bedrock/op-batcher-entrypoint.sh similarity index 94% rename from ops/bss-entrypoint.sh rename to ops-bedrock/op-batcher-entrypoint.sh index 1a66f6c071df..01e31d570aa6 100644 --- a/ops/bss-entrypoint.sh +++ b/ops-bedrock/op-batcher-entrypoint.sh @@ -11,4 +11,4 @@ curl \ --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ http://l1:8545 -exec bss +exec op-batcher diff --git a/ops-bedrock/op-batcher-key.txt b/ops-bedrock/op-batcher-key.txt new file mode 100644 index 000000000000..0994f47ba01e --- /dev/null +++ b/ops-bedrock/op-batcher-key.txt @@ -0,0 +1 @@ +bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 \ No newline at end of file diff --git a/ops/p2p-node-key.txt b/ops-bedrock/p2p-node-key.txt similarity index 100% rename from ops/p2p-node-key.txt rename to ops-bedrock/p2p-node-key.txt diff --git a/ops/p2p-sequencer-key.txt b/ops-bedrock/p2p-sequencer-key.txt similarity index 100% rename from ops/p2p-sequencer-key.txt rename to ops-bedrock/p2p-sequencer-key.txt diff --git a/ops/rollup.json b/ops-bedrock/rollup.json similarity index 100% rename from ops/rollup.json rename to ops-bedrock/rollup.json diff --git a/ops/test-integration.sh b/ops-bedrock/test-integration.sh similarity index 100% rename from ops/test-integration.sh rename to ops-bedrock/test-integration.sh diff --git a/ops/Dockerfile.bss b/ops/Dockerfile.bss deleted file mode 100644 index 4913db53dee6..000000000000 --- a/ops/Dockerfile.bss +++ /dev/null @@ -1,22 +0,0 @@ -FROM golang:1.18.0-alpine3.15 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 -x - -COPY Makefile /app/Makefile -COPY ./opnode /app/opnode -COPY ./l2os /app/l2os -COPY ./bss /app/bss - -RUN make bss - -FROM alpine:3.15 - -COPY --from=builder /app/bin/bss /usr/local/bin - -ENTRYPOINT ["bss"] diff --git a/ops/Dockerfile.l2os b/ops/Dockerfile.l2os deleted file mode 100644 index 4141a870b3da..000000000000 --- a/ops/Dockerfile.l2os +++ /dev/null @@ -1,21 +0,0 @@ -FROM golang:1.18.0-alpine3.15 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 -x - -COPY Makefile /app/Makefile -COPY ./opnode /app/opnode -COPY ./l2os /app/l2os - -RUN make l2os - -FROM alpine:3.15 - -COPY --from=builder /app/bin/l2os /usr/local/bin - -CMD ["l2os"] diff --git a/ops/Dockerfile.opnode b/ops/Dockerfile.opnode deleted file mode 100644 index 1b712e2c7134..000000000000 --- a/ops/Dockerfile.opnode +++ /dev/null @@ -1,20 +0,0 @@ -FROM golang:1.18.0-alpine3.15 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 -x - -COPY Makefile /app/Makefile -COPY ./opnode /app/opnode - -RUN make opnode - -FROM alpine:3.15 - -COPY --from=builder /app/bin/op /usr/local/bin - -CMD ["op"] diff --git a/package.json b/package.json index 3ba44a57c61f..cf99457d8d76 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "scripts": { "setup": "yarn install && cargo install lychee", "lint": "yarn lint:fix && yarn lint:check", - "lint:fix": "markdownlint-cli2-fix \"./opnode/README.md\" \"./specs/**/*.md\" \"#**/node_modules\"", - "lint:check": "markdownlint-cli2 \"./opnode/README.md\" \"./specs/**/*.md\" \"#**/node_modules\"", - "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \"./opnode/README.md\" \"./specs/**/*.md\" \"./meta/**/*.md\" \"./opnode/**/*.md\"", + "lint:fix": "markdownlint-cli2-fix \\\"op-node/README.md\\\" \\\"./specs/**/*.md\\\" \\\"#**/node_modules\\\"", + "lint:check": "markdownlint-cli2 \\\"op-node/README.md\\\" \\\"./specs/**/*.md\\\" \\\"#**/node_modules\\\"", + "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \\\"op-node/README.md\\\" \\\"./specs/**/*.md\\\" \\\"./meta/**/*.md\\\" \\\"./op-node/**/*.md\\\"", "lint:toc": "doctoc --title=\"**Table of Contents**\" ./specs ./meta" }, "dependencies": { diff --git a/specs/proposals.md b/specs/proposals.md index 511dd3009838..2e4bbf624493 100644 --- a/specs/proposals.md +++ b/specs/proposals.md @@ -34,8 +34,8 @@ are part of later specification milestones. ## Proposing L2 Output Commitments The proposer's role is to construct and submit output roots, which are commitments made on a configurable interval, -to the `L2OutputOracle` contract running on L2. It does this by running the [L2 output submitter](../l2os/), a service -which periodically queries the rollup node's +to the `L2OutputOracle` contract running on L2. It does this by running the [L2 output proposer](../op-proposer/), +a service which periodically queries the rollup node's [`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is described [below](#l2-output-commitment-construction). From 1188334c6781d72519d1cce403bcf0e3e453fca1 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Sat, 14 May 2022 18:07:30 -0600 Subject: [PATCH 578/585] remove git submodules --- .gitmodules | 9 --------- packages/contracts/lib/ds-test | 1 - packages/contracts/lib/forge-std | 1 - packages/contracts/lib/solmate | 1 - 4 files changed, 12 deletions(-) delete mode 100644 .gitmodules delete mode 160000 packages/contracts/lib/ds-test delete mode 160000 packages/contracts/lib/forge-std delete mode 160000 packages/contracts/lib/solmate diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index cd75690a4831..000000000000 --- a/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "packages/contracts/lib/forge-std"] - path = packages/contracts/lib/forge-std - url = https://github.com/foundry-rs/forge-std -[submodule "packages/contracts/lib/solmate"] - path = packages/contracts/lib/solmate - url = https://github.com/rari-capital/solmate -[submodule "packages/contracts/lib/ds-test"] - path = packages/contracts/lib/ds-test - url = https://github.com/dapphub/ds-test diff --git a/packages/contracts/lib/ds-test b/packages/contracts/lib/ds-test deleted file mode 160000 index 2c7dbcc8586b..000000000000 --- a/packages/contracts/lib/ds-test +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2c7dbcc8586b33f358e3307a443e524490c17666 diff --git a/packages/contracts/lib/forge-std b/packages/contracts/lib/forge-std deleted file mode 160000 index 409465b69928..000000000000 --- a/packages/contracts/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 409465b6992822a91318142dd269660aad9e30ee diff --git a/packages/contracts/lib/solmate b/packages/contracts/lib/solmate deleted file mode 160000 index 290c4eb22b3d..000000000000 --- a/packages/contracts/lib/solmate +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 290c4eb22b3d578d6acdc33a95bf65c297ac7216 From b0119b2cf36f4f961bad8260a6ae292110917fe0 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Sat, 14 May 2022 18:07:30 -0600 Subject: [PATCH 579/585] optimistic-specs: monorepo merge, mv into protocol dir --- packages/contracts/LICENSE | 21 - .editorconfig => protocol/.editorconfig | 0 .../.github}/workflows/devnet-ci.yml | 0 .../.github}/workflows/go-ci.yml | 0 .../.github}/workflows/markdown-ci.yml | 0 .../.github}/workflows/solidity-ci.yml | 0 .gitignore => protocol/.gitignore | 0 .../.markdownlint.json | 0 Makefile => protocol/Makefile | 0 README.md => protocol/README.md | 0 {.circleci => protocol}/config.yml | 0 go.work => protocol/go.work | 0 go.work.sum => protocol/go.work.sum | 0 package.json => protocol/package.json | 0 .../packages}/contracts/.eslintignore | 0 .../packages}/contracts/.eslintrc.js | 0 .../packages}/contracts/.gas-snapshot | 0 .../packages}/contracts/.gitignore | 0 .../packages}/contracts/.npmignore | 0 .../packages}/contracts/.prettierignore | 0 .../packages}/contracts/.prettierrc.js | 0 .../packages}/contracts/.solhint.json | 0 .../packages}/contracts/.solhintignore | 0 .../packages/contracts/LICENSE | 0 .../packages}/contracts/README.md | 0 .../contracts/L1/L1CrossDomainMessenger.sol | 0 .../contracts/L1/L1StandardBridge.sol | 0 .../contracts/contracts/L1/L2OutputOracle.sol | 0 .../contracts/contracts/L1/OptimismPortal.sol | 0 .../contracts/contracts/L2/Burner.sol | 0 .../contracts/contracts/L2/L1Block.sol | 0 .../contracts/contracts/L2/L1BlockNumber.sol | 0 .../contracts/L2/L2CrossDomainMessenger.sol | 0 .../contracts/L2/L2StandardBridge.sol | 0 .../contracts/L2/L2ToL1MessagePasser.sol | 0 .../libraries/ExcessivelySafeCall.sol | 0 .../Lib_BedrockPredeployAddresses.sol | 0 .../libraries/Lib_CrossDomainHashing.sol | 0 .../libraries/Lib_WithdrawalVerifier.sol | 0 .../contracts/contracts/test/CommonTest.t.sol | 0 .../contracts/test/CrossDomainHashing.t.sol | 0 .../contracts/contracts/test/L1Block.t.sol | 0 .../contracts/test/L1BlockNumber.t.sol | 0 .../test/L1CrossDomainMessenger.t.sol | 0 .../contracts/test/L1StandardBridge.t.sol | 0 .../test/L2CrossDomainMessenger.t.sol | 0 .../contracts/test/L2OutputOracle.t.sol | 0 .../contracts/test/L2StandardBridge.t.sol | 0 .../contracts/test/L2ToL1MessagePasser.t.sol | 0 .../contracts/contracts/test/Lib_RLP.t.sol | 0 .../test/OptimismMintableERC20.t.sol | 0 .../test/OptimismMintableTokenFactory.t.sol | 0 .../contracts/test/OptimismPortal.t.sol | 0 .../universal/CrossDomainMessenger.sol | 0 .../universal/OptimismMintableERC20.sol | 0 .../OptimismMintableTokenFactory.sol | 0 .../contracts/universal/StandardBridge.sol | 0 .../deploy/000-L2OutputOracle.deploy.ts | 0 .../deploy/001-OptimismPortal.deploy.ts | 0 .../deploy/002-L1CrossDomainMessenger.ts | 0 .../contracts/deploy/003-L1StandardBridge.ts | 0 .../004-OptimismMintableTokenFactory.ts | 0 .../packages}/contracts/foundry.toml | 0 .../packages}/contracts/hardhat.config.ts | 0 .../packages}/contracts/helpers/constants.ts | 0 .../contracts/helpers/generateProofs.ts | 0 .../packages}/contracts/helpers/index.ts | 0 .../contracts/helpers/trie-test-generator.ts | 0 .../packages}/contracts/helpers/utils.ts | 0 .../packages}/contracts/package.json | 0 .../contracts/scripts/ffiMakeProof.ts | 0 .../packages}/contracts/scripts/makeProof.ts | 0 .../packages}/contracts/slither.config.json | 0 .../packages}/contracts/slither.db.json | 0 .../packages}/contracts/tasks/deposits.ts | 0 .../packages}/contracts/test/helpers.spec.ts | 0 .../packages}/contracts/tsconfig.json | 0 .../packages}/contracts/yarn.lock | 0 .../packages}/integration-tests/.gitignore | 0 .../integration-tests/contracts/Counter.sol | 0 .../integration-tests/contracts/ERC20.sol | 0 .../contracts/MultiDepositor.sol | 0 .../integration-tests/contracts/Reverter.sol | 0 .../packages}/integration-tests/package.json | 0 .../test/000_withdrawals.spec.ts | 0 .../integration-tests/test/deposit.spec.ts | 0 .../integration-tests/test/rpc.spec.ts | 0 .../integration-tests/test/shared/env.ts | 0 .../integration-tests/test/shared/setup.ts | 0 .../integration-tests/test/shared/utils.ts | 0 .../packages}/integration-tests/tsconfig.json | 0 .../packages}/integration-tests/yarn.lock | 0 tsconfig.json | 23 - yarn.lock | 1725 ----------------- 94 files changed, 1769 deletions(-) delete mode 100644 packages/contracts/LICENSE rename .editorconfig => protocol/.editorconfig (100%) rename {.github => protocol/.github}/workflows/devnet-ci.yml (100%) rename {.github => protocol/.github}/workflows/go-ci.yml (100%) rename {.github => protocol/.github}/workflows/markdown-ci.yml (100%) rename {.github => protocol/.github}/workflows/solidity-ci.yml (100%) rename .gitignore => protocol/.gitignore (100%) rename .markdownlint.json => protocol/.markdownlint.json (100%) rename Makefile => protocol/Makefile (100%) rename README.md => protocol/README.md (100%) rename {.circleci => protocol}/config.yml (100%) rename go.work => protocol/go.work (100%) rename go.work.sum => protocol/go.work.sum (100%) rename package.json => protocol/package.json (100%) rename {packages => protocol/packages}/contracts/.eslintignore (100%) rename {packages => protocol/packages}/contracts/.eslintrc.js (100%) rename {packages => protocol/packages}/contracts/.gas-snapshot (100%) rename {packages => protocol/packages}/contracts/.gitignore (100%) rename {packages => protocol/packages}/contracts/.npmignore (100%) rename {packages => protocol/packages}/contracts/.prettierignore (100%) rename {packages => protocol/packages}/contracts/.prettierrc.js (100%) rename {packages => protocol/packages}/contracts/.solhint.json (100%) rename {packages => protocol/packages}/contracts/.solhintignore (100%) rename LICENSE => protocol/packages/contracts/LICENSE (100%) rename {packages => protocol/packages}/contracts/README.md (100%) rename {packages => protocol/packages}/contracts/contracts/L1/L1CrossDomainMessenger.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L1/L1StandardBridge.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L1/L2OutputOracle.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L1/OptimismPortal.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L2/Burner.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L2/L1Block.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L2/L1BlockNumber.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L2/L2CrossDomainMessenger.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L2/L2StandardBridge.sol (100%) rename {packages => protocol/packages}/contracts/contracts/L2/L2ToL1MessagePasser.sol (100%) rename {packages => protocol/packages}/contracts/contracts/libraries/ExcessivelySafeCall.sol (100%) rename {packages => protocol/packages}/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol (100%) rename {packages => protocol/packages}/contracts/contracts/libraries/Lib_CrossDomainHashing.sol (100%) rename {packages => protocol/packages}/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/CommonTest.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/CrossDomainHashing.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L1Block.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L1BlockNumber.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L1CrossDomainMessenger.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L1StandardBridge.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L2CrossDomainMessenger.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L2OutputOracle.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L2StandardBridge.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/L2ToL1MessagePasser.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/Lib_RLP.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/OptimismMintableERC20.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/OptimismMintableTokenFactory.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/test/OptimismPortal.t.sol (100%) rename {packages => protocol/packages}/contracts/contracts/universal/CrossDomainMessenger.sol (100%) rename {packages => protocol/packages}/contracts/contracts/universal/OptimismMintableERC20.sol (100%) rename {packages => protocol/packages}/contracts/contracts/universal/OptimismMintableTokenFactory.sol (100%) rename {packages => protocol/packages}/contracts/contracts/universal/StandardBridge.sol (100%) rename {packages => protocol/packages}/contracts/deploy/000-L2OutputOracle.deploy.ts (100%) rename {packages => protocol/packages}/contracts/deploy/001-OptimismPortal.deploy.ts (100%) rename {packages => protocol/packages}/contracts/deploy/002-L1CrossDomainMessenger.ts (100%) rename {packages => protocol/packages}/contracts/deploy/003-L1StandardBridge.ts (100%) rename {packages => protocol/packages}/contracts/deploy/004-OptimismMintableTokenFactory.ts (100%) rename {packages => protocol/packages}/contracts/foundry.toml (100%) rename {packages => protocol/packages}/contracts/hardhat.config.ts (100%) rename {packages => protocol/packages}/contracts/helpers/constants.ts (100%) rename {packages => protocol/packages}/contracts/helpers/generateProofs.ts (100%) rename {packages => protocol/packages}/contracts/helpers/index.ts (100%) rename {packages => protocol/packages}/contracts/helpers/trie-test-generator.ts (100%) rename {packages => protocol/packages}/contracts/helpers/utils.ts (100%) rename {packages => protocol/packages}/contracts/package.json (100%) rename {packages => protocol/packages}/contracts/scripts/ffiMakeProof.ts (100%) rename {packages => protocol/packages}/contracts/scripts/makeProof.ts (100%) rename {packages => protocol/packages}/contracts/slither.config.json (100%) rename {packages => protocol/packages}/contracts/slither.db.json (100%) rename {packages => protocol/packages}/contracts/tasks/deposits.ts (100%) rename {packages => protocol/packages}/contracts/test/helpers.spec.ts (100%) rename {packages => protocol/packages}/contracts/tsconfig.json (100%) rename {packages => protocol/packages}/contracts/yarn.lock (100%) rename {packages => protocol/packages}/integration-tests/.gitignore (100%) rename {packages => protocol/packages}/integration-tests/contracts/Counter.sol (100%) rename {packages => protocol/packages}/integration-tests/contracts/ERC20.sol (100%) rename {packages => protocol/packages}/integration-tests/contracts/MultiDepositor.sol (100%) rename {packages => protocol/packages}/integration-tests/contracts/Reverter.sol (100%) rename {packages => protocol/packages}/integration-tests/package.json (100%) rename {packages => protocol/packages}/integration-tests/test/000_withdrawals.spec.ts (100%) rename {packages => protocol/packages}/integration-tests/test/deposit.spec.ts (100%) rename {packages => protocol/packages}/integration-tests/test/rpc.spec.ts (100%) rename {packages => protocol/packages}/integration-tests/test/shared/env.ts (100%) rename {packages => protocol/packages}/integration-tests/test/shared/setup.ts (100%) rename {packages => protocol/packages}/integration-tests/test/shared/utils.ts (100%) rename {packages => protocol/packages}/integration-tests/tsconfig.json (100%) rename {packages => protocol/packages}/integration-tests/yarn.lock (100%) delete mode 100644 tsconfig.json delete mode 100644 yarn.lock diff --git a/packages/contracts/LICENSE b/packages/contracts/LICENSE deleted file mode 100644 index 86541fdc788e..000000000000 --- a/packages/contracts/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Optimism - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/.editorconfig b/protocol/.editorconfig similarity index 100% rename from .editorconfig rename to protocol/.editorconfig diff --git a/.github/workflows/devnet-ci.yml b/protocol/.github/workflows/devnet-ci.yml similarity index 100% rename from .github/workflows/devnet-ci.yml rename to protocol/.github/workflows/devnet-ci.yml diff --git a/.github/workflows/go-ci.yml b/protocol/.github/workflows/go-ci.yml similarity index 100% rename from .github/workflows/go-ci.yml rename to protocol/.github/workflows/go-ci.yml diff --git a/.github/workflows/markdown-ci.yml b/protocol/.github/workflows/markdown-ci.yml similarity index 100% rename from .github/workflows/markdown-ci.yml rename to protocol/.github/workflows/markdown-ci.yml diff --git a/.github/workflows/solidity-ci.yml b/protocol/.github/workflows/solidity-ci.yml similarity index 100% rename from .github/workflows/solidity-ci.yml rename to protocol/.github/workflows/solidity-ci.yml diff --git a/.gitignore b/protocol/.gitignore similarity index 100% rename from .gitignore rename to protocol/.gitignore diff --git a/.markdownlint.json b/protocol/.markdownlint.json similarity index 100% rename from .markdownlint.json rename to protocol/.markdownlint.json diff --git a/Makefile b/protocol/Makefile similarity index 100% rename from Makefile rename to protocol/Makefile diff --git a/README.md b/protocol/README.md similarity index 100% rename from README.md rename to protocol/README.md diff --git a/.circleci/config.yml b/protocol/config.yml similarity index 100% rename from .circleci/config.yml rename to protocol/config.yml diff --git a/go.work b/protocol/go.work similarity index 100% rename from go.work rename to protocol/go.work diff --git a/go.work.sum b/protocol/go.work.sum similarity index 100% rename from go.work.sum rename to protocol/go.work.sum diff --git a/package.json b/protocol/package.json similarity index 100% rename from package.json rename to protocol/package.json diff --git a/packages/contracts/.eslintignore b/protocol/packages/contracts/.eslintignore similarity index 100% rename from packages/contracts/.eslintignore rename to protocol/packages/contracts/.eslintignore diff --git a/packages/contracts/.eslintrc.js b/protocol/packages/contracts/.eslintrc.js similarity index 100% rename from packages/contracts/.eslintrc.js rename to protocol/packages/contracts/.eslintrc.js diff --git a/packages/contracts/.gas-snapshot b/protocol/packages/contracts/.gas-snapshot similarity index 100% rename from packages/contracts/.gas-snapshot rename to protocol/packages/contracts/.gas-snapshot diff --git a/packages/contracts/.gitignore b/protocol/packages/contracts/.gitignore similarity index 100% rename from packages/contracts/.gitignore rename to protocol/packages/contracts/.gitignore diff --git a/packages/contracts/.npmignore b/protocol/packages/contracts/.npmignore similarity index 100% rename from packages/contracts/.npmignore rename to protocol/packages/contracts/.npmignore diff --git a/packages/contracts/.prettierignore b/protocol/packages/contracts/.prettierignore similarity index 100% rename from packages/contracts/.prettierignore rename to protocol/packages/contracts/.prettierignore diff --git a/packages/contracts/.prettierrc.js b/protocol/packages/contracts/.prettierrc.js similarity index 100% rename from packages/contracts/.prettierrc.js rename to protocol/packages/contracts/.prettierrc.js diff --git a/packages/contracts/.solhint.json b/protocol/packages/contracts/.solhint.json similarity index 100% rename from packages/contracts/.solhint.json rename to protocol/packages/contracts/.solhint.json diff --git a/packages/contracts/.solhintignore b/protocol/packages/contracts/.solhintignore similarity index 100% rename from packages/contracts/.solhintignore rename to protocol/packages/contracts/.solhintignore diff --git a/LICENSE b/protocol/packages/contracts/LICENSE similarity index 100% rename from LICENSE rename to protocol/packages/contracts/LICENSE diff --git a/packages/contracts/README.md b/protocol/packages/contracts/README.md similarity index 100% rename from packages/contracts/README.md rename to protocol/packages/contracts/README.md diff --git a/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol b/protocol/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol similarity index 100% rename from packages/contracts/contracts/L1/L1CrossDomainMessenger.sol rename to protocol/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol diff --git a/packages/contracts/contracts/L1/L1StandardBridge.sol b/protocol/packages/contracts/contracts/L1/L1StandardBridge.sol similarity index 100% rename from packages/contracts/contracts/L1/L1StandardBridge.sol rename to protocol/packages/contracts/contracts/L1/L1StandardBridge.sol diff --git a/packages/contracts/contracts/L1/L2OutputOracle.sol b/protocol/packages/contracts/contracts/L1/L2OutputOracle.sol similarity index 100% rename from packages/contracts/contracts/L1/L2OutputOracle.sol rename to protocol/packages/contracts/contracts/L1/L2OutputOracle.sol diff --git a/packages/contracts/contracts/L1/OptimismPortal.sol b/protocol/packages/contracts/contracts/L1/OptimismPortal.sol similarity index 100% rename from packages/contracts/contracts/L1/OptimismPortal.sol rename to protocol/packages/contracts/contracts/L1/OptimismPortal.sol diff --git a/packages/contracts/contracts/L2/Burner.sol b/protocol/packages/contracts/contracts/L2/Burner.sol similarity index 100% rename from packages/contracts/contracts/L2/Burner.sol rename to protocol/packages/contracts/contracts/L2/Burner.sol diff --git a/packages/contracts/contracts/L2/L1Block.sol b/protocol/packages/contracts/contracts/L2/L1Block.sol similarity index 100% rename from packages/contracts/contracts/L2/L1Block.sol rename to protocol/packages/contracts/contracts/L2/L1Block.sol diff --git a/packages/contracts/contracts/L2/L1BlockNumber.sol b/protocol/packages/contracts/contracts/L2/L1BlockNumber.sol similarity index 100% rename from packages/contracts/contracts/L2/L1BlockNumber.sol rename to protocol/packages/contracts/contracts/L2/L1BlockNumber.sol diff --git a/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol b/protocol/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol similarity index 100% rename from packages/contracts/contracts/L2/L2CrossDomainMessenger.sol rename to protocol/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol diff --git a/packages/contracts/contracts/L2/L2StandardBridge.sol b/protocol/packages/contracts/contracts/L2/L2StandardBridge.sol similarity index 100% rename from packages/contracts/contracts/L2/L2StandardBridge.sol rename to protocol/packages/contracts/contracts/L2/L2StandardBridge.sol diff --git a/packages/contracts/contracts/L2/L2ToL1MessagePasser.sol b/protocol/packages/contracts/contracts/L2/L2ToL1MessagePasser.sol similarity index 100% rename from packages/contracts/contracts/L2/L2ToL1MessagePasser.sol rename to protocol/packages/contracts/contracts/L2/L2ToL1MessagePasser.sol diff --git a/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol b/protocol/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol similarity index 100% rename from packages/contracts/contracts/libraries/ExcessivelySafeCall.sol rename to protocol/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol diff --git a/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol b/protocol/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol similarity index 100% rename from packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol rename to protocol/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol diff --git a/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol b/protocol/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol similarity index 100% rename from packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol rename to protocol/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol diff --git a/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol b/protocol/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol similarity index 100% rename from packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol rename to protocol/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol diff --git a/packages/contracts/contracts/test/CommonTest.t.sol b/protocol/packages/contracts/contracts/test/CommonTest.t.sol similarity index 100% rename from packages/contracts/contracts/test/CommonTest.t.sol rename to protocol/packages/contracts/contracts/test/CommonTest.t.sol diff --git a/packages/contracts/contracts/test/CrossDomainHashing.t.sol b/protocol/packages/contracts/contracts/test/CrossDomainHashing.t.sol similarity index 100% rename from packages/contracts/contracts/test/CrossDomainHashing.t.sol rename to protocol/packages/contracts/contracts/test/CrossDomainHashing.t.sol diff --git a/packages/contracts/contracts/test/L1Block.t.sol b/protocol/packages/contracts/contracts/test/L1Block.t.sol similarity index 100% rename from packages/contracts/contracts/test/L1Block.t.sol rename to protocol/packages/contracts/contracts/test/L1Block.t.sol diff --git a/packages/contracts/contracts/test/L1BlockNumber.t.sol b/protocol/packages/contracts/contracts/test/L1BlockNumber.t.sol similarity index 100% rename from packages/contracts/contracts/test/L1BlockNumber.t.sol rename to protocol/packages/contracts/contracts/test/L1BlockNumber.t.sol diff --git a/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol b/protocol/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol similarity index 100% rename from packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol rename to protocol/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol diff --git a/packages/contracts/contracts/test/L1StandardBridge.t.sol b/protocol/packages/contracts/contracts/test/L1StandardBridge.t.sol similarity index 100% rename from packages/contracts/contracts/test/L1StandardBridge.t.sol rename to protocol/packages/contracts/contracts/test/L1StandardBridge.t.sol diff --git a/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol b/protocol/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol similarity index 100% rename from packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol rename to protocol/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/protocol/packages/contracts/contracts/test/L2OutputOracle.t.sol similarity index 100% rename from packages/contracts/contracts/test/L2OutputOracle.t.sol rename to protocol/packages/contracts/contracts/test/L2OutputOracle.t.sol diff --git a/packages/contracts/contracts/test/L2StandardBridge.t.sol b/protocol/packages/contracts/contracts/test/L2StandardBridge.t.sol similarity index 100% rename from packages/contracts/contracts/test/L2StandardBridge.t.sol rename to protocol/packages/contracts/contracts/test/L2StandardBridge.t.sol diff --git a/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol b/protocol/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol similarity index 100% rename from packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol rename to protocol/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol diff --git a/packages/contracts/contracts/test/Lib_RLP.t.sol b/protocol/packages/contracts/contracts/test/Lib_RLP.t.sol similarity index 100% rename from packages/contracts/contracts/test/Lib_RLP.t.sol rename to protocol/packages/contracts/contracts/test/Lib_RLP.t.sol diff --git a/packages/contracts/contracts/test/OptimismMintableERC20.t.sol b/protocol/packages/contracts/contracts/test/OptimismMintableERC20.t.sol similarity index 100% rename from packages/contracts/contracts/test/OptimismMintableERC20.t.sol rename to protocol/packages/contracts/contracts/test/OptimismMintableERC20.t.sol diff --git a/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol b/protocol/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol similarity index 100% rename from packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol rename to protocol/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol diff --git a/packages/contracts/contracts/test/OptimismPortal.t.sol b/protocol/packages/contracts/contracts/test/OptimismPortal.t.sol similarity index 100% rename from packages/contracts/contracts/test/OptimismPortal.t.sol rename to protocol/packages/contracts/contracts/test/OptimismPortal.t.sol diff --git a/packages/contracts/contracts/universal/CrossDomainMessenger.sol b/protocol/packages/contracts/contracts/universal/CrossDomainMessenger.sol similarity index 100% rename from packages/contracts/contracts/universal/CrossDomainMessenger.sol rename to protocol/packages/contracts/contracts/universal/CrossDomainMessenger.sol diff --git a/packages/contracts/contracts/universal/OptimismMintableERC20.sol b/protocol/packages/contracts/contracts/universal/OptimismMintableERC20.sol similarity index 100% rename from packages/contracts/contracts/universal/OptimismMintableERC20.sol rename to protocol/packages/contracts/contracts/universal/OptimismMintableERC20.sol diff --git a/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol b/protocol/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol similarity index 100% rename from packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol rename to protocol/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol diff --git a/packages/contracts/contracts/universal/StandardBridge.sol b/protocol/packages/contracts/contracts/universal/StandardBridge.sol similarity index 100% rename from packages/contracts/contracts/universal/StandardBridge.sol rename to protocol/packages/contracts/contracts/universal/StandardBridge.sol diff --git a/packages/contracts/deploy/000-L2OutputOracle.deploy.ts b/protocol/packages/contracts/deploy/000-L2OutputOracle.deploy.ts similarity index 100% rename from packages/contracts/deploy/000-L2OutputOracle.deploy.ts rename to protocol/packages/contracts/deploy/000-L2OutputOracle.deploy.ts diff --git a/packages/contracts/deploy/001-OptimismPortal.deploy.ts b/protocol/packages/contracts/deploy/001-OptimismPortal.deploy.ts similarity index 100% rename from packages/contracts/deploy/001-OptimismPortal.deploy.ts rename to protocol/packages/contracts/deploy/001-OptimismPortal.deploy.ts diff --git a/packages/contracts/deploy/002-L1CrossDomainMessenger.ts b/protocol/packages/contracts/deploy/002-L1CrossDomainMessenger.ts similarity index 100% rename from packages/contracts/deploy/002-L1CrossDomainMessenger.ts rename to protocol/packages/contracts/deploy/002-L1CrossDomainMessenger.ts diff --git a/packages/contracts/deploy/003-L1StandardBridge.ts b/protocol/packages/contracts/deploy/003-L1StandardBridge.ts similarity index 100% rename from packages/contracts/deploy/003-L1StandardBridge.ts rename to protocol/packages/contracts/deploy/003-L1StandardBridge.ts diff --git a/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts b/protocol/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts similarity index 100% rename from packages/contracts/deploy/004-OptimismMintableTokenFactory.ts rename to protocol/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts diff --git a/packages/contracts/foundry.toml b/protocol/packages/contracts/foundry.toml similarity index 100% rename from packages/contracts/foundry.toml rename to protocol/packages/contracts/foundry.toml diff --git a/packages/contracts/hardhat.config.ts b/protocol/packages/contracts/hardhat.config.ts similarity index 100% rename from packages/contracts/hardhat.config.ts rename to protocol/packages/contracts/hardhat.config.ts diff --git a/packages/contracts/helpers/constants.ts b/protocol/packages/contracts/helpers/constants.ts similarity index 100% rename from packages/contracts/helpers/constants.ts rename to protocol/packages/contracts/helpers/constants.ts diff --git a/packages/contracts/helpers/generateProofs.ts b/protocol/packages/contracts/helpers/generateProofs.ts similarity index 100% rename from packages/contracts/helpers/generateProofs.ts rename to protocol/packages/contracts/helpers/generateProofs.ts diff --git a/packages/contracts/helpers/index.ts b/protocol/packages/contracts/helpers/index.ts similarity index 100% rename from packages/contracts/helpers/index.ts rename to protocol/packages/contracts/helpers/index.ts diff --git a/packages/contracts/helpers/trie-test-generator.ts b/protocol/packages/contracts/helpers/trie-test-generator.ts similarity index 100% rename from packages/contracts/helpers/trie-test-generator.ts rename to protocol/packages/contracts/helpers/trie-test-generator.ts diff --git a/packages/contracts/helpers/utils.ts b/protocol/packages/contracts/helpers/utils.ts similarity index 100% rename from packages/contracts/helpers/utils.ts rename to protocol/packages/contracts/helpers/utils.ts diff --git a/packages/contracts/package.json b/protocol/packages/contracts/package.json similarity index 100% rename from packages/contracts/package.json rename to protocol/packages/contracts/package.json diff --git a/packages/contracts/scripts/ffiMakeProof.ts b/protocol/packages/contracts/scripts/ffiMakeProof.ts similarity index 100% rename from packages/contracts/scripts/ffiMakeProof.ts rename to protocol/packages/contracts/scripts/ffiMakeProof.ts diff --git a/packages/contracts/scripts/makeProof.ts b/protocol/packages/contracts/scripts/makeProof.ts similarity index 100% rename from packages/contracts/scripts/makeProof.ts rename to protocol/packages/contracts/scripts/makeProof.ts diff --git a/packages/contracts/slither.config.json b/protocol/packages/contracts/slither.config.json similarity index 100% rename from packages/contracts/slither.config.json rename to protocol/packages/contracts/slither.config.json diff --git a/packages/contracts/slither.db.json b/protocol/packages/contracts/slither.db.json similarity index 100% rename from packages/contracts/slither.db.json rename to protocol/packages/contracts/slither.db.json diff --git a/packages/contracts/tasks/deposits.ts b/protocol/packages/contracts/tasks/deposits.ts similarity index 100% rename from packages/contracts/tasks/deposits.ts rename to protocol/packages/contracts/tasks/deposits.ts diff --git a/packages/contracts/test/helpers.spec.ts b/protocol/packages/contracts/test/helpers.spec.ts similarity index 100% rename from packages/contracts/test/helpers.spec.ts rename to protocol/packages/contracts/test/helpers.spec.ts diff --git a/packages/contracts/tsconfig.json b/protocol/packages/contracts/tsconfig.json similarity index 100% rename from packages/contracts/tsconfig.json rename to protocol/packages/contracts/tsconfig.json diff --git a/packages/contracts/yarn.lock b/protocol/packages/contracts/yarn.lock similarity index 100% rename from packages/contracts/yarn.lock rename to protocol/packages/contracts/yarn.lock diff --git a/packages/integration-tests/.gitignore b/protocol/packages/integration-tests/.gitignore similarity index 100% rename from packages/integration-tests/.gitignore rename to protocol/packages/integration-tests/.gitignore diff --git a/packages/integration-tests/contracts/Counter.sol b/protocol/packages/integration-tests/contracts/Counter.sol similarity index 100% rename from packages/integration-tests/contracts/Counter.sol rename to protocol/packages/integration-tests/contracts/Counter.sol diff --git a/packages/integration-tests/contracts/ERC20.sol b/protocol/packages/integration-tests/contracts/ERC20.sol similarity index 100% rename from packages/integration-tests/contracts/ERC20.sol rename to protocol/packages/integration-tests/contracts/ERC20.sol diff --git a/packages/integration-tests/contracts/MultiDepositor.sol b/protocol/packages/integration-tests/contracts/MultiDepositor.sol similarity index 100% rename from packages/integration-tests/contracts/MultiDepositor.sol rename to protocol/packages/integration-tests/contracts/MultiDepositor.sol diff --git a/packages/integration-tests/contracts/Reverter.sol b/protocol/packages/integration-tests/contracts/Reverter.sol similarity index 100% rename from packages/integration-tests/contracts/Reverter.sol rename to protocol/packages/integration-tests/contracts/Reverter.sol diff --git a/packages/integration-tests/package.json b/protocol/packages/integration-tests/package.json similarity index 100% rename from packages/integration-tests/package.json rename to protocol/packages/integration-tests/package.json diff --git a/packages/integration-tests/test/000_withdrawals.spec.ts b/protocol/packages/integration-tests/test/000_withdrawals.spec.ts similarity index 100% rename from packages/integration-tests/test/000_withdrawals.spec.ts rename to protocol/packages/integration-tests/test/000_withdrawals.spec.ts diff --git a/packages/integration-tests/test/deposit.spec.ts b/protocol/packages/integration-tests/test/deposit.spec.ts similarity index 100% rename from packages/integration-tests/test/deposit.spec.ts rename to protocol/packages/integration-tests/test/deposit.spec.ts diff --git a/packages/integration-tests/test/rpc.spec.ts b/protocol/packages/integration-tests/test/rpc.spec.ts similarity index 100% rename from packages/integration-tests/test/rpc.spec.ts rename to protocol/packages/integration-tests/test/rpc.spec.ts diff --git a/packages/integration-tests/test/shared/env.ts b/protocol/packages/integration-tests/test/shared/env.ts similarity index 100% rename from packages/integration-tests/test/shared/env.ts rename to protocol/packages/integration-tests/test/shared/env.ts diff --git a/packages/integration-tests/test/shared/setup.ts b/protocol/packages/integration-tests/test/shared/setup.ts similarity index 100% rename from packages/integration-tests/test/shared/setup.ts rename to protocol/packages/integration-tests/test/shared/setup.ts diff --git a/packages/integration-tests/test/shared/utils.ts b/protocol/packages/integration-tests/test/shared/utils.ts similarity index 100% rename from packages/integration-tests/test/shared/utils.ts rename to protocol/packages/integration-tests/test/shared/utils.ts diff --git a/packages/integration-tests/tsconfig.json b/protocol/packages/integration-tests/tsconfig.json similarity index 100% rename from packages/integration-tests/tsconfig.json rename to protocol/packages/integration-tests/tsconfig.json diff --git a/packages/integration-tests/yarn.lock b/protocol/packages/integration-tests/yarn.lock similarity index 100% rename from packages/integration-tests/yarn.lock rename to protocol/packages/integration-tests/yarn.lock diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index f389a4990f71..000000000000 --- a/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es2017", - "sourceMap": true, - "esModuleInterop": true, - "composite": true, - "resolveJsonModule": true, - "declaration": true, - "noImplicitAny": false, - "removeComments": true, - "noLib": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "typeRoots": [ - "node_modules/@types" - ] - }, - "exclude": [ - "node_modules", - "dist" - ] -} diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index f008300e70b7..000000000000 --- a/yarn.lock +++ /dev/null @@ -1,1725 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== - dependencies: - "@babel/highlight" "^7.16.0" - -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== - dependencies: - "@babel/helper-validator-identifier" "^7.15.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@eth-optimism/core-utils@^0.8.1": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.8.1.tgz#ee7d8815f9ddb67ca3e2f3ec1d8515a46af5caf6" - integrity sha512-GJJvw9cBekvR1xH/f2jpgp6MnbWlMBaVm1h3BA0sEzmlaFufTG4ybGrHkL3nQT0Vqtjs3LYjaExkVmsUzpb7xg== - dependencies: - "@ethersproject/abstract-provider" "^5.5.1" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/providers" "^5.5.3" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/web" "^5.5.1" - bufio "^1.0.7" - chai "^4.3.4" - ethers "^5.5.4" - -"@ethersproject/abi@5.6.0", "@ethersproject/abi@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.0.tgz#ea07cbc1eec2374d32485679c12408005895e9f3" - integrity sha512-AhVByTwdXCc2YQ20v300w6KVHle9g2OFc28ZAFCPnJyEpkv1xKXjZcSTgWOlv1i+0dqlgF8RCF2Rn2KC1t+1Vg== - dependencies: - "@ethersproject/address" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/constants" "^5.6.0" - "@ethersproject/hash" "^5.6.0" - "@ethersproject/keccak256" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - -"@ethersproject/abstract-provider@5.6.0", "@ethersproject/abstract-provider@^5.5.1", "@ethersproject/abstract-provider@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz#0c4ac7054650dbd9c476cf5907f588bbb6ef3061" - integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== - dependencies: - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/networks" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/transactions" "^5.6.0" - "@ethersproject/web" "^5.6.0" - -"@ethersproject/abstract-signer@5.6.0", "@ethersproject/abstract-signer@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz#9cd7ae9211c2b123a3b29bf47aab17d4d016e3e7" - integrity sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ== - dependencies: - "@ethersproject/abstract-provider" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - -"@ethersproject/address@5.6.0", "@ethersproject/address@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" - integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== - dependencies: - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/keccak256" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/rlp" "^5.6.0" - -"@ethersproject/base64@5.6.0", "@ethersproject/base64@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.0.tgz#a12c4da2a6fb86d88563216b0282308fc15907c9" - integrity sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw== - dependencies: - "@ethersproject/bytes" "^5.6.0" - -"@ethersproject/basex@5.6.0", "@ethersproject/basex@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.0.tgz#9ea7209bf0a1c3ddc2a90f180c3a7f0d7d2e8a69" - integrity sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - -"@ethersproject/bignumber@5.6.0", "@ethersproject/bignumber@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.0.tgz#116c81b075c57fa765a8f3822648cf718a8a0e26" - integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - bn.js "^4.11.9" - -"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@^5.6.0": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" - integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/constants@5.6.0", "@ethersproject/constants@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.0.tgz#55e3eb0918584d3acc0688e9958b0cedef297088" - integrity sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA== - dependencies: - "@ethersproject/bignumber" "^5.6.0" - -"@ethersproject/contracts@5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.0.tgz#60f2cfc7addd99a865c6c8cfbbcec76297386067" - integrity sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw== - dependencies: - "@ethersproject/abi" "^5.6.0" - "@ethersproject/abstract-provider" "^5.6.0" - "@ethersproject/abstract-signer" "^5.6.0" - "@ethersproject/address" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/constants" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/transactions" "^5.6.0" - -"@ethersproject/hash@5.6.0", "@ethersproject/hash@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.0.tgz#d24446a5263e02492f9808baa99b6e2b4c3429a2" - integrity sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA== - dependencies: - "@ethersproject/abstract-signer" "^5.6.0" - "@ethersproject/address" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/keccak256" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - -"@ethersproject/hdnode@5.6.0", "@ethersproject/hdnode@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.0.tgz#9dcbe8d629bbbcf144f2cae476337fe92d320998" - integrity sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw== - dependencies: - "@ethersproject/abstract-signer" "^5.6.0" - "@ethersproject/basex" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/pbkdf2" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/sha2" "^5.6.0" - "@ethersproject/signing-key" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - "@ethersproject/transactions" "^5.6.0" - "@ethersproject/wordlists" "^5.6.0" - -"@ethersproject/json-wallets@5.6.0", "@ethersproject/json-wallets@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz#4c2fc27f17e36c583e7a252fb938bc46f98891e5" - integrity sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ== - dependencies: - "@ethersproject/abstract-signer" "^5.6.0" - "@ethersproject/address" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/hdnode" "^5.6.0" - "@ethersproject/keccak256" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/pbkdf2" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - "@ethersproject/transactions" "^5.6.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.6.0", "@ethersproject/keccak256@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.0.tgz#fea4bb47dbf8f131c2e1774a1cecbfeb9d606459" - integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== - dependencies: - "@ethersproject/bytes" "^5.6.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@5.6.0", "@ethersproject/logger@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" - integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== - -"@ethersproject/networks@5.6.1", "@ethersproject/networks@^5.6.0": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.1.tgz#7a21ed1f83e86121737b16841961ec99ccf5c9c7" - integrity sha512-b2rrupf3kCTcc3jr9xOWBuHylSFtbpJf79Ga7QR98ienU2UqGimPGEsYMgbI29KHJfA5Us89XwGVmxrlxmSrMg== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/pbkdf2@5.6.0", "@ethersproject/pbkdf2@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz#04fcc2d7c6bff88393f5b4237d906a192426685a" - integrity sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/sha2" "^5.6.0" - -"@ethersproject/properties@5.6.0", "@ethersproject/properties@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" - integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/providers@5.6.2", "@ethersproject/providers@^5.5.3": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.2.tgz#b9807b1c8c6f59fa2ee4b3cf6519724d07a9f422" - integrity sha512-6/EaFW/hNWz+224FXwl8+HdMRzVHt8DpPmu5MZaIQqx/K/ELnC9eY236SMV7mleCM3NnEArFwcAAxH5kUUgaRg== - dependencies: - "@ethersproject/abstract-provider" "^5.6.0" - "@ethersproject/abstract-signer" "^5.6.0" - "@ethersproject/address" "^5.6.0" - "@ethersproject/basex" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/constants" "^5.6.0" - "@ethersproject/hash" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/networks" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.0" - "@ethersproject/rlp" "^5.6.0" - "@ethersproject/sha2" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - "@ethersproject/transactions" "^5.6.0" - "@ethersproject/web" "^5.6.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.6.0", "@ethersproject/random@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.0.tgz#1505d1ab6a250e0ee92f436850fa3314b2cb5ae6" - integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/rlp@5.6.0", "@ethersproject/rlp@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.0.tgz#55a7be01c6f5e64d6e6e7edb6061aa120962a717" - integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/sha2@5.6.0", "@ethersproject/sha2@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.0.tgz#364c4c11cc753bda36f31f001628706ebadb64d9" - integrity sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.6.0", "@ethersproject/signing-key@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.0.tgz#4f02e3fb09e22b71e2e1d6dc4bcb5dafa69ce042" - integrity sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - bn.js "^4.11.9" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.0.tgz#64657362a596bf7f5630bdc921c07dd78df06dc3" - integrity sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww== - dependencies: - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/keccak256" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/sha2" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - -"@ethersproject/strings@5.6.0", "@ethersproject/strings@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.0.tgz#9891b26709153d996bf1303d39a7f4bc047878fd" - integrity sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/constants" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/transactions@5.6.0", "@ethersproject/transactions@^5.5.0", "@ethersproject/transactions@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.0.tgz#4b594d73a868ef6e1529a2f8f94a785e6791ae4e" - integrity sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg== - dependencies: - "@ethersproject/address" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/constants" "^5.6.0" - "@ethersproject/keccak256" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/rlp" "^5.6.0" - "@ethersproject/signing-key" "^5.6.0" - -"@ethersproject/units@5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.0.tgz#e5cbb1906988f5740254a21b9ded6bd51e826d9c" - integrity sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw== - dependencies: - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/constants" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/wallet@5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.0.tgz#33d11a806d783864208f348709a5a3badac8e22a" - integrity sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg== - dependencies: - "@ethersproject/abstract-provider" "^5.6.0" - "@ethersproject/abstract-signer" "^5.6.0" - "@ethersproject/address" "^5.6.0" - "@ethersproject/bignumber" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/hash" "^5.6.0" - "@ethersproject/hdnode" "^5.6.0" - "@ethersproject/json-wallets" "^5.6.0" - "@ethersproject/keccak256" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.0" - "@ethersproject/signing-key" "^5.6.0" - "@ethersproject/transactions" "^5.6.0" - "@ethersproject/wordlists" "^5.6.0" - -"@ethersproject/web@5.6.0", "@ethersproject/web@^5.5.1", "@ethersproject/web@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.0.tgz#4bf8b3cbc17055027e1a5dd3c357e37474eaaeb8" - integrity sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg== - dependencies: - "@ethersproject/base64" "^5.6.0" - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - -"@ethersproject/wordlists@5.6.0", "@ethersproject/wordlists@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.0.tgz#79e62c5276e091d8575f6930ba01a29218ded032" - integrity sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/hash" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.0" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@textlint/ast-node-types@^4.2.5": - version "4.4.3" - resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-4.4.3.tgz#fdba16e8126cddc50f45433ce7f6c55e7829566c" - integrity sha512-qi2jjgO6Tn3KNPGnm6B7p6QTEPvY95NFsIAaJuwbulur8iJUEenp1OnoUfiDaC/g2WPPEFkcfXpmnu8XEMFo2A== - -"@textlint/markdown-to-ast@~6.1.7": - version "6.1.7" - resolved "https://registry.yarnpkg.com/@textlint/markdown-to-ast/-/markdown-to-ast-6.1.7.tgz#7ed9561b577bcd5307c8ef82660bc568ce31647e" - integrity sha512-B0QtokeQR4a9+4q0NQr8T9l7A1fFihTN5Ze57tVgqW+3ymzXEouh8DvPHeNQ4T6jEkAThvdjk95mxAMpGRJ79w== - dependencies: - "@textlint/ast-node-types" "^4.2.5" - debug "^4.1.1" - remark-frontmatter "^1.2.0" - remark-parse "^5.0.0" - structured-source "^3.0.2" - traverse "^0.6.6" - unified "^6.1.6" - -"@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -anchor-markdown-header@~0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz#045063d76e6a1f9cd327a57a0126aa0fdec371a7" - integrity sha1-BFBj125qH5zTJ6V6ASaqD97Dcac= - dependencies: - emoji-regex "~6.1.0" - -ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-escapes@^4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -bail@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" - integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== - -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - -bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -boundary@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/boundary/-/boundary-1.0.1.tgz#4d67dc2602c0cc16dd9bce7ebf87e948290f5812" - integrity sha1-TWfcJgLAzBbdm85+v4fpSCkPWBI= - -braces@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -bufio@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.0.7.tgz#b7f63a1369a0829ed64cc14edf0573b3e382a33e" - integrity sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A== - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -chai@^4.3.4: - version "4.3.6" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" - integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.1.0, chalk@^4.1.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -character-entities-legacy@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" - integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== - -character-entities@^1.0.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" - integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== - -character-reference-invalid@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" - integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - -clone@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - -collapse-white-space@^1.0.2: - version "1.0.6" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" - integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@^2.0.16: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -cosmiconfig@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@^4.1.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@^4.3.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== - dependencies: - type-detect "^4.0.0" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctoc@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctoc/-/doctoc-2.1.0.tgz#e7cbcd1f9e65519c295461423b2e7195d9e0d7ab" - integrity sha512-0darEVEuWKLyIlpGOzE5cILf/pgUu25qUs6YwCqLqfxb8+3b9Cl4iakA8vwYrBQOkJ5SwpHKEPVMu2KOMrTA7A== - dependencies: - "@textlint/markdown-to-ast" "~6.1.7" - anchor-markdown-header "~0.5.7" - htmlparser2 "~4.1.0" - minimist "~1.2.5" - underscore "~1.12.1" - update-section "~0.3.3" - -dom-serializer@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" - integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== - dependencies: - domelementtype "^2.0.1" - -domhandler@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" - integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== - dependencies: - domelementtype "^2.2.0" - -domutils@^2.0.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@~6.1.0: - version "6.1.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.3.tgz#ec79a3969b02d2ecf2b72254279bf99bc7a83932" - integrity sha1-7HmjlpsC0uzytyJUJ5v5m8eoOTI= - -enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -entities@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" - integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -ethers@^5.5.4: - version "5.6.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.2.tgz#e75bac7f038c5e0fdde667dba62fc223924143a2" - integrity sha512-EzGCbns24/Yluu7+ToWnMca3SXJ1Jk1BvWB7CCmVNxyOeM4LLvw2OLuIHhlkhQk1dtOcj9UMsdkxUh8RiG1dxQ== - dependencies: - "@ethersproject/abi" "5.6.0" - "@ethersproject/abstract-provider" "5.6.0" - "@ethersproject/abstract-signer" "5.6.0" - "@ethersproject/address" "5.6.0" - "@ethersproject/base64" "5.6.0" - "@ethersproject/basex" "5.6.0" - "@ethersproject/bignumber" "5.6.0" - "@ethersproject/bytes" "5.6.1" - "@ethersproject/constants" "5.6.0" - "@ethersproject/contracts" "5.6.0" - "@ethersproject/hash" "5.6.0" - "@ethersproject/hdnode" "5.6.0" - "@ethersproject/json-wallets" "5.6.0" - "@ethersproject/keccak256" "5.6.0" - "@ethersproject/logger" "5.6.0" - "@ethersproject/networks" "5.6.1" - "@ethersproject/pbkdf2" "5.6.0" - "@ethersproject/properties" "5.6.0" - "@ethersproject/providers" "5.6.2" - "@ethersproject/random" "5.6.0" - "@ethersproject/rlp" "5.6.0" - "@ethersproject/sha2" "5.6.0" - "@ethersproject/signing-key" "5.6.0" - "@ethersproject/solidity" "5.6.0" - "@ethersproject/strings" "5.6.0" - "@ethersproject/transactions" "5.6.0" - "@ethersproject/units" "5.6.0" - "@ethersproject/wallet" "5.6.0" - "@ethersproject/web" "5.6.0" - "@ethersproject/wordlists" "5.6.0" - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -fast-glob@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -fault@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" - integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== - dependencies: - format "^0.2.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -format@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" - integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" - integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -globby@~11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" - slash "^3.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -htmlparser2@~4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" - integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== - dependencies: - domelementtype "^2.0.1" - domhandler "^3.0.0" - domutils "^2.0.0" - entities "^2.0.0" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ignore@^5.1.4: - version "5.1.9" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" - integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inherits@^2.0.0, inherits@^2.0.3, inherits@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-alphabetical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" - integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== - -is-alphanumerical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" - integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-buffer@^1.1.4: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-decimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" - integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" - integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-whitespace-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" - integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== - -is-word-character@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" - integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= - -linkify-it@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" - integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== - dependencies: - uc.micro "^1.0.1" - -lint-staged@11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-11.0.0.tgz#24d0a95aa316ba28e257f5c4613369a75a10c712" - integrity sha512-3rsRIoyaE8IphSUtO1RVTFl1e0SLBtxxUOPBtHxQgBHS5/i6nqvjcUfNioMa4BU9yGnPzbO+xkfLtXtxBpCzjw== - dependencies: - chalk "^4.1.1" - cli-truncate "^2.1.0" - commander "^7.2.0" - cosmiconfig "^7.0.0" - debug "^4.3.1" - dedent "^0.7.0" - enquirer "^2.3.6" - execa "^5.0.0" - listr2 "^3.8.2" - log-symbols "^4.1.0" - micromatch "^4.0.4" - normalize-path "^3.0.0" - please-upgrade-node "^3.2.0" - string-argv "0.3.1" - stringify-object "^3.3.0" - -listr2@^3.8.2: - version "3.13.4" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.13.4.tgz#34101fc0184545597e00d1e7915ccfbfb17332e6" - integrity sha512-lZ1Rut1DSIRwbxQbI8qaUBfOWJ1jEYRgltIM97j6kKOCI2pHVWMyxZvkU/JKmRBWcIYgDS2PK+yDgVqm7u3crw== - dependencies: - cli-truncate "^2.1.0" - clone "^2.1.2" - colorette "^2.0.16" - log-update "^4.0.0" - p-map "^4.0.0" - rxjs "^7.4.0" - through "^2.3.8" - wrap-ansi "^7.0.0" - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== - dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" - -loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== - dependencies: - get-func-name "^2.0.0" - -markdown-escapes@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" - integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== - -markdown-it@12.2.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.2.0.tgz#091f720fd5db206f80de7a8d1f1a7035fd0d38db" - integrity sha512-Wjws+uCrVQRqOoJvze4HCqkKl1AsSh95iFAeQDwnyfxM09divCBSXlDR1uTvyUP3Grzpn4Ru8GeCxYPM8vkCQg== - dependencies: - argparse "^2.0.1" - entities "~2.1.0" - linkify-it "^3.0.1" - mdurl "^1.0.1" - uc.micro "^1.0.5" - -markdownlint-cli2-formatter-default@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.2.tgz#76f1a064d70966178dfe3bb489af9423d830ca79" - integrity sha512-jIz1X3SIC8sX4NDFqQFUXL+JEtfnDoN4i+xocEu+etcxGX455pHb6sx86f/yVk4mKJ2o7aNe2ydSx9an22BfBg== - -markdownlint-cli2@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/markdownlint-cli2/-/markdownlint-cli2-0.3.2.tgz#328774b5ab981997fdd6fa8f72ea7feaed84722b" - integrity sha512-Wj4iQy2J49m9CVkWkLTdFxMTPDqD3AyL3NbLQgz/nUnTu8LnDguFCbQtFhdzQPvncHVjrKT2vYqg7DifzVP4tA== - dependencies: - globby "~11.0.4" - markdownlint "~0.24.0" - markdownlint-cli2-formatter-default "^0.0.2" - markdownlint-rule-helpers "~0.15.0" - micromatch "~4.0.4" - strip-json-comments "~3.1.1" - yaml "~1.10.2" - -markdownlint-rule-helpers@~0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.15.0.tgz#11434c573649b9235ae70b967314f5711f7d8fa8" - integrity sha512-A+9mswc3m/kkqpJCqntmte/1VKhDJ+tjZsERLz5L4h/Qr7ht2/BkGkgY5E7/wsxIhcpl+ctIfz+oS3PQrMOB2w== - -markdownlint@^0.24.0, markdownlint@~0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.24.0.tgz#224b53f671367a237d40c8be1745c7be9a322671" - integrity sha512-OJIGsGFV/rC9irI5E1FMy6v9hdACSwaa+EN3224Y5KG8zj2EYzdHOw0pOJovIYmjNfEZ9BtxUY4P7uYHTSNnbQ== - dependencies: - markdown-it "12.2.0" - -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4, micromatch@~4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimist@~1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -onetime@^5.1.0, onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-entities@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" - integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -please-upgrade-node@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" - integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== - dependencies: - semver-compare "^1.0.0" - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -remark-frontmatter@^1.2.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-1.3.3.tgz#67ec63c89da5a84bb793ecec166e11b4eb47af10" - integrity sha512-fM5eZPBvu2pVNoq3ZPW22q+5Ativ1oLozq2qYt9I2oNyxiUd/tDl0iLLntEVAegpZIslPWg1brhcP1VsaSVUag== - dependencies: - fault "^1.0.1" - xtend "^4.0.1" - -remark-parse@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" - integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA== - dependencies: - collapse-white-space "^1.0.2" - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - is-word-character "^1.0.0" - markdown-escapes "^1.0.0" - parse-entities "^1.1.0" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - trim "0.0.1" - trim-trailing-lines "^1.0.0" - unherit "^1.0.4" - unist-util-remove-position "^1.0.0" - vfile-location "^2.0.0" - xtend "^4.0.1" - -repeat-string@^1.5.4: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -replace-ext@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rxjs@^7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" - integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== - dependencies: - tslib "~2.1.0" - -scrypt-js@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -semver-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" - integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" - integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -state-toggle@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" - integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== - -string-argv@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" - integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -structured-source@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/structured-source/-/structured-source-3.0.2.tgz#dd802425e0f53dc4a6e7aca3752901a1ccda7af5" - integrity sha1-3YAkJeD1PcSm56yjdSkBoczaevU= - dependencies: - boundary "^1.0.1" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -through@^2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -traverse@^0.6.6: - version "0.6.6" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" - integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= - -trim-trailing-lines@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" - integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== - -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - -trough@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" - integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== - -tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== - -underscore@~1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" - integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== - -unherit@^1.0.4: - version "1.1.3" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" - integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== - dependencies: - inherits "^2.0.0" - xtend "^4.0.0" - -unified@^6.1.6: - version "6.2.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" - integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^1.1.0" - trough "^1.0.0" - vfile "^2.0.0" - x-is-string "^0.1.0" - -unist-util-is@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" - integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== - -unist-util-remove-position@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz#ec037348b6102c897703eee6d0294ca4755a2020" - integrity sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A== - dependencies: - unist-util-visit "^1.1.0" - -unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" - integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== - -unist-util-visit-parents@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" - integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== - dependencies: - unist-util-is "^3.0.0" - -unist-util-visit@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" - integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== - dependencies: - unist-util-visit-parents "^2.0.0" - -update-section@~0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/update-section/-/update-section-0.3.3.tgz#458f17820d37820dc60e20b86d94391b00123158" - integrity sha1-RY8Xgg03gg3GDiC4bZQ5GwASMVg= - -vfile-location@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" - integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== - -vfile-message@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1" - integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA== - dependencies: - unist-util-stringify-position "^1.1.1" - -vfile@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" - integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== - dependencies: - is-buffer "^1.1.4" - replace-ext "1.0.0" - unist-util-stringify-position "^1.0.0" - vfile-message "^1.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - -x-is-string@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" - integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yaml@^1.10.0, yaml@~1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== From 0e3f8fc1020fe5fe7910d6f4e96e29815fc3494e Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Sat, 14 May 2022 18:07:33 -0600 Subject: [PATCH 580/585] bedrock contracts dependencies --- .gitmodules | 9 +++++++++ protocol/.markdownlint.json => .markdownlint.json | 0 .../contracts-bedrock}/.eslintignore | 0 .../contracts-bedrock}/.eslintrc.js | 0 .../contracts-bedrock}/.gas-snapshot | 0 .../contracts => packages/contracts-bedrock}/.gitignore | 0 .../contracts => packages/contracts-bedrock}/.npmignore | 0 .../contracts-bedrock}/.prettierignore | 0 .../contracts-bedrock}/.prettierrc.js | 0 .../contracts-bedrock}/.solhint.json | 0 .../contracts-bedrock}/.solhintignore | 0 .../contracts => packages/contracts-bedrock}/LICENSE | 0 .../contracts => packages/contracts-bedrock}/README.md | 0 .../contracts/L1/L1CrossDomainMessenger.sol | 0 .../contracts-bedrock}/contracts/L1/L1StandardBridge.sol | 0 .../contracts-bedrock}/contracts/L1/L2OutputOracle.sol | 0 .../contracts-bedrock}/contracts/L1/OptimismPortal.sol | 0 .../contracts-bedrock}/contracts/L2/Burner.sol | 0 .../contracts-bedrock}/contracts/L2/L1Block.sol | 0 .../contracts-bedrock}/contracts/L2/L1BlockNumber.sol | 0 .../contracts/L2/L2CrossDomainMessenger.sol | 0 .../contracts-bedrock}/contracts/L2/L2StandardBridge.sol | 0 .../contracts/L2/L2ToL1MessagePasser.sol | 0 .../contracts/libraries/ExcessivelySafeCall.sol | 0 .../libraries/Lib_BedrockPredeployAddresses.sol | 0 .../contracts/libraries/Lib_CrossDomainHashing.sol | 0 .../contracts/libraries/Lib_WithdrawalVerifier.sol | 0 .../contracts-bedrock}/contracts/test/CommonTest.t.sol | 0 .../contracts/test/CrossDomainHashing.t.sol | 0 .../contracts-bedrock}/contracts/test/L1Block.t.sol | 0 .../contracts/test/L1BlockNumber.t.sol | 0 .../contracts/test/L1CrossDomainMessenger.t.sol | 0 .../contracts/test/L1StandardBridge.t.sol | 0 .../contracts/test/L2CrossDomainMessenger.t.sol | 0 .../contracts/test/L2OutputOracle.t.sol | 0 .../contracts/test/L2StandardBridge.t.sol | 0 .../contracts/test/L2ToL1MessagePasser.t.sol | 0 .../contracts-bedrock}/contracts/test/Lib_RLP.t.sol | 0 .../contracts/test/OptimismMintableERC20.t.sol | 0 .../contracts/test/OptimismMintableTokenFactory.t.sol | 0 .../contracts/test/OptimismPortal.t.sol | 0 .../contracts/universal/CrossDomainMessenger.sol | 0 .../contracts/universal/OptimismMintableERC20.sol | 0 .../contracts/universal/OptimismMintableTokenFactory.sol | 0 .../contracts/universal/StandardBridge.sol | 0 .../deploy/000-L2OutputOracle.deploy.ts | 0 .../deploy/001-OptimismPortal.deploy.ts | 0 .../deploy/002-L1CrossDomainMessenger.ts | 0 .../contracts-bedrock}/deploy/003-L1StandardBridge.ts | 0 .../deploy/004-OptimismMintableTokenFactory.ts | 0 .../contracts-bedrock}/foundry.toml | 0 .../contracts-bedrock}/hardhat.config.ts | 0 .../contracts-bedrock}/helpers/constants.ts | 0 .../contracts-bedrock}/helpers/generateProofs.ts | 0 .../contracts-bedrock}/helpers/index.ts | 0 .../contracts-bedrock}/helpers/trie-test-generator.ts | 0 .../contracts-bedrock}/helpers/utils.ts | 0 packages/contracts-bedrock/lib/ds-test | 1 + packages/contracts-bedrock/lib/forge-std | 1 + packages/contracts-bedrock/lib/solmate | 1 + .../contracts-bedrock}/package.json | 0 .../contracts-bedrock}/scripts/ffiMakeProof.ts | 0 .../contracts-bedrock}/scripts/makeProof.ts | 0 .../contracts-bedrock}/slither.config.json | 0 .../contracts-bedrock}/slither.db.json | 0 .../contracts-bedrock}/tasks/deposits.ts | 0 .../contracts-bedrock}/test/helpers.spec.ts | 0 .../contracts-bedrock}/tsconfig.json | 0 .../contracts => packages/contracts-bedrock}/yarn.lock | 0 .../integration-tests-bedrock}/.gitignore | 0 .../integration-tests-bedrock}/contracts/Counter.sol | 0 .../integration-tests-bedrock}/contracts/ERC20.sol | 0 .../contracts/MultiDepositor.sol | 0 .../integration-tests-bedrock}/contracts/Reverter.sol | 0 .../integration-tests-bedrock}/package.json | 0 .../test/000_withdrawals.spec.ts | 0 .../integration-tests-bedrock}/test/deposit.spec.ts | 0 .../integration-tests-bedrock}/test/rpc.spec.ts | 0 .../integration-tests-bedrock}/test/shared/env.ts | 0 .../integration-tests-bedrock}/test/shared/setup.ts | 0 .../integration-tests-bedrock}/test/shared/utils.ts | 0 .../integration-tests-bedrock}/tsconfig.json | 0 .../integration-tests-bedrock}/yarn.lock | 0 specs/README.md | 2 +- 84 files changed, 13 insertions(+), 1 deletion(-) rename protocol/.markdownlint.json => .markdownlint.json (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.eslintignore (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.eslintrc.js (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.gas-snapshot (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.gitignore (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.npmignore (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.prettierignore (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.prettierrc.js (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.solhint.json (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/.solhintignore (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/LICENSE (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/README.md (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L1/L1CrossDomainMessenger.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L1/L1StandardBridge.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L1/L2OutputOracle.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L1/OptimismPortal.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L2/Burner.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L2/L1Block.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L2/L1BlockNumber.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L2/L2CrossDomainMessenger.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L2/L2StandardBridge.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/L2/L2ToL1MessagePasser.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/libraries/ExcessivelySafeCall.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/libraries/Lib_BedrockPredeployAddresses.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/libraries/Lib_CrossDomainHashing.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/libraries/Lib_WithdrawalVerifier.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/CommonTest.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/CrossDomainHashing.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L1Block.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L1BlockNumber.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L1CrossDomainMessenger.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L1StandardBridge.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L2CrossDomainMessenger.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L2OutputOracle.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L2StandardBridge.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/L2ToL1MessagePasser.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/Lib_RLP.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/OptimismMintableERC20.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/OptimismMintableTokenFactory.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/test/OptimismPortal.t.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/universal/CrossDomainMessenger.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/universal/OptimismMintableERC20.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/universal/OptimismMintableTokenFactory.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/contracts/universal/StandardBridge.sol (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/deploy/000-L2OutputOracle.deploy.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/deploy/001-OptimismPortal.deploy.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/deploy/002-L1CrossDomainMessenger.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/deploy/003-L1StandardBridge.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/deploy/004-OptimismMintableTokenFactory.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/foundry.toml (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/hardhat.config.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/helpers/constants.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/helpers/generateProofs.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/helpers/index.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/helpers/trie-test-generator.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/helpers/utils.ts (100%) create mode 160000 packages/contracts-bedrock/lib/ds-test create mode 160000 packages/contracts-bedrock/lib/forge-std create mode 160000 packages/contracts-bedrock/lib/solmate rename {protocol/packages/contracts => packages/contracts-bedrock}/package.json (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/scripts/ffiMakeProof.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/scripts/makeProof.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/slither.config.json (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/slither.db.json (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/tasks/deposits.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/test/helpers.spec.ts (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/tsconfig.json (100%) rename {protocol/packages/contracts => packages/contracts-bedrock}/yarn.lock (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/.gitignore (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/contracts/Counter.sol (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/contracts/ERC20.sol (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/contracts/MultiDepositor.sol (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/contracts/Reverter.sol (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/package.json (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/test/000_withdrawals.spec.ts (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/test/deposit.spec.ts (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/test/rpc.spec.ts (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/test/shared/env.ts (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/test/shared/setup.ts (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/test/shared/utils.ts (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/tsconfig.json (100%) rename {protocol/packages/integration-tests => packages/integration-tests-bedrock}/yarn.lock (100%) diff --git a/.gitmodules b/.gitmodules index 8802b2259132..da4de9866f39 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,12 @@ [submodule "tests"] path = l2geth/tests/testdata url = https://github.com/ethereum/tests +[submodule "packages/contracts-bedrock/lib/forge-std"] + path = packages/contracts-bedrock/lib/forge-std + url = https://github.com/foundry-rs/forge-std.git +[submodule "packages/contracts-bedrock/lib/solmate"] + path = packages/contracts-bedrock/lib/solmate + url = https://github.com/rari-capital/solmate.git +[submodule "packages/contracts-bedrock/lib/ds-test"] + path = packages/contracts-bedrock/lib/ds-test + url = https://github.com/dapphub/ds-test.git diff --git a/protocol/.markdownlint.json b/.markdownlint.json similarity index 100% rename from protocol/.markdownlint.json rename to .markdownlint.json diff --git a/protocol/packages/contracts/.eslintignore b/packages/contracts-bedrock/.eslintignore similarity index 100% rename from protocol/packages/contracts/.eslintignore rename to packages/contracts-bedrock/.eslintignore diff --git a/protocol/packages/contracts/.eslintrc.js b/packages/contracts-bedrock/.eslintrc.js similarity index 100% rename from protocol/packages/contracts/.eslintrc.js rename to packages/contracts-bedrock/.eslintrc.js diff --git a/protocol/packages/contracts/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot similarity index 100% rename from protocol/packages/contracts/.gas-snapshot rename to packages/contracts-bedrock/.gas-snapshot diff --git a/protocol/packages/contracts/.gitignore b/packages/contracts-bedrock/.gitignore similarity index 100% rename from protocol/packages/contracts/.gitignore rename to packages/contracts-bedrock/.gitignore diff --git a/protocol/packages/contracts/.npmignore b/packages/contracts-bedrock/.npmignore similarity index 100% rename from protocol/packages/contracts/.npmignore rename to packages/contracts-bedrock/.npmignore diff --git a/protocol/packages/contracts/.prettierignore b/packages/contracts-bedrock/.prettierignore similarity index 100% rename from protocol/packages/contracts/.prettierignore rename to packages/contracts-bedrock/.prettierignore diff --git a/protocol/packages/contracts/.prettierrc.js b/packages/contracts-bedrock/.prettierrc.js similarity index 100% rename from protocol/packages/contracts/.prettierrc.js rename to packages/contracts-bedrock/.prettierrc.js diff --git a/protocol/packages/contracts/.solhint.json b/packages/contracts-bedrock/.solhint.json similarity index 100% rename from protocol/packages/contracts/.solhint.json rename to packages/contracts-bedrock/.solhint.json diff --git a/protocol/packages/contracts/.solhintignore b/packages/contracts-bedrock/.solhintignore similarity index 100% rename from protocol/packages/contracts/.solhintignore rename to packages/contracts-bedrock/.solhintignore diff --git a/protocol/packages/contracts/LICENSE b/packages/contracts-bedrock/LICENSE similarity index 100% rename from protocol/packages/contracts/LICENSE rename to packages/contracts-bedrock/LICENSE diff --git a/protocol/packages/contracts/README.md b/packages/contracts-bedrock/README.md similarity index 100% rename from protocol/packages/contracts/README.md rename to packages/contracts-bedrock/README.md diff --git a/protocol/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol b/packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol similarity index 100% rename from protocol/packages/contracts/contracts/L1/L1CrossDomainMessenger.sol rename to packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol diff --git a/protocol/packages/contracts/contracts/L1/L1StandardBridge.sol b/packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol similarity index 100% rename from protocol/packages/contracts/contracts/L1/L1StandardBridge.sol rename to packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol diff --git a/protocol/packages/contracts/contracts/L1/L2OutputOracle.sol b/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol similarity index 100% rename from protocol/packages/contracts/contracts/L1/L2OutputOracle.sol rename to packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol diff --git a/protocol/packages/contracts/contracts/L1/OptimismPortal.sol b/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol similarity index 100% rename from protocol/packages/contracts/contracts/L1/OptimismPortal.sol rename to packages/contracts-bedrock/contracts/L1/OptimismPortal.sol diff --git a/protocol/packages/contracts/contracts/L2/Burner.sol b/packages/contracts-bedrock/contracts/L2/Burner.sol similarity index 100% rename from protocol/packages/contracts/contracts/L2/Burner.sol rename to packages/contracts-bedrock/contracts/L2/Burner.sol diff --git a/protocol/packages/contracts/contracts/L2/L1Block.sol b/packages/contracts-bedrock/contracts/L2/L1Block.sol similarity index 100% rename from protocol/packages/contracts/contracts/L2/L1Block.sol rename to packages/contracts-bedrock/contracts/L2/L1Block.sol diff --git a/protocol/packages/contracts/contracts/L2/L1BlockNumber.sol b/packages/contracts-bedrock/contracts/L2/L1BlockNumber.sol similarity index 100% rename from protocol/packages/contracts/contracts/L2/L1BlockNumber.sol rename to packages/contracts-bedrock/contracts/L2/L1BlockNumber.sol diff --git a/protocol/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol b/packages/contracts-bedrock/contracts/L2/L2CrossDomainMessenger.sol similarity index 100% rename from protocol/packages/contracts/contracts/L2/L2CrossDomainMessenger.sol rename to packages/contracts-bedrock/contracts/L2/L2CrossDomainMessenger.sol diff --git a/protocol/packages/contracts/contracts/L2/L2StandardBridge.sol b/packages/contracts-bedrock/contracts/L2/L2StandardBridge.sol similarity index 100% rename from protocol/packages/contracts/contracts/L2/L2StandardBridge.sol rename to packages/contracts-bedrock/contracts/L2/L2StandardBridge.sol diff --git a/protocol/packages/contracts/contracts/L2/L2ToL1MessagePasser.sol b/packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol similarity index 100% rename from protocol/packages/contracts/contracts/L2/L2ToL1MessagePasser.sol rename to packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol diff --git a/protocol/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol b/packages/contracts-bedrock/contracts/libraries/ExcessivelySafeCall.sol similarity index 100% rename from protocol/packages/contracts/contracts/libraries/ExcessivelySafeCall.sol rename to packages/contracts-bedrock/contracts/libraries/ExcessivelySafeCall.sol diff --git a/protocol/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol b/packages/contracts-bedrock/contracts/libraries/Lib_BedrockPredeployAddresses.sol similarity index 100% rename from protocol/packages/contracts/contracts/libraries/Lib_BedrockPredeployAddresses.sol rename to packages/contracts-bedrock/contracts/libraries/Lib_BedrockPredeployAddresses.sol diff --git a/protocol/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol b/packages/contracts-bedrock/contracts/libraries/Lib_CrossDomainHashing.sol similarity index 100% rename from protocol/packages/contracts/contracts/libraries/Lib_CrossDomainHashing.sol rename to packages/contracts-bedrock/contracts/libraries/Lib_CrossDomainHashing.sol diff --git a/protocol/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol b/packages/contracts-bedrock/contracts/libraries/Lib_WithdrawalVerifier.sol similarity index 100% rename from protocol/packages/contracts/contracts/libraries/Lib_WithdrawalVerifier.sol rename to packages/contracts-bedrock/contracts/libraries/Lib_WithdrawalVerifier.sol diff --git a/protocol/packages/contracts/contracts/test/CommonTest.t.sol b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/CommonTest.t.sol rename to packages/contracts-bedrock/contracts/test/CommonTest.t.sol diff --git a/protocol/packages/contracts/contracts/test/CrossDomainHashing.t.sol b/packages/contracts-bedrock/contracts/test/CrossDomainHashing.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/CrossDomainHashing.t.sol rename to packages/contracts-bedrock/contracts/test/CrossDomainHashing.t.sol diff --git a/protocol/packages/contracts/contracts/test/L1Block.t.sol b/packages/contracts-bedrock/contracts/test/L1Block.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L1Block.t.sol rename to packages/contracts-bedrock/contracts/test/L1Block.t.sol diff --git a/protocol/packages/contracts/contracts/test/L1BlockNumber.t.sol b/packages/contracts-bedrock/contracts/test/L1BlockNumber.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L1BlockNumber.t.sol rename to packages/contracts-bedrock/contracts/test/L1BlockNumber.t.sol diff --git a/protocol/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L1CrossDomainMessenger.t.sol rename to packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol diff --git a/protocol/packages/contracts/contracts/test/L1StandardBridge.t.sol b/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L1StandardBridge.t.sol rename to packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol diff --git a/protocol/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L2CrossDomainMessenger.t.sol rename to packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol diff --git a/protocol/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L2OutputOracle.t.sol rename to packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol diff --git a/protocol/packages/contracts/contracts/test/L2StandardBridge.t.sol b/packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L2StandardBridge.t.sol rename to packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol diff --git a/protocol/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol b/packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol rename to packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol diff --git a/protocol/packages/contracts/contracts/test/Lib_RLP.t.sol b/packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/Lib_RLP.t.sol rename to packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol diff --git a/protocol/packages/contracts/contracts/test/OptimismMintableERC20.t.sol b/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/OptimismMintableERC20.t.sol rename to packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol diff --git a/protocol/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol b/packages/contracts-bedrock/contracts/test/OptimismMintableTokenFactory.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/OptimismMintableTokenFactory.t.sol rename to packages/contracts-bedrock/contracts/test/OptimismMintableTokenFactory.t.sol diff --git a/protocol/packages/contracts/contracts/test/OptimismPortal.t.sol b/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol similarity index 100% rename from protocol/packages/contracts/contracts/test/OptimismPortal.t.sol rename to packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol diff --git a/protocol/packages/contracts/contracts/universal/CrossDomainMessenger.sol b/packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol similarity index 100% rename from protocol/packages/contracts/contracts/universal/CrossDomainMessenger.sol rename to packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol diff --git a/protocol/packages/contracts/contracts/universal/OptimismMintableERC20.sol b/packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol similarity index 100% rename from protocol/packages/contracts/contracts/universal/OptimismMintableERC20.sol rename to packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol diff --git a/protocol/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol b/packages/contracts-bedrock/contracts/universal/OptimismMintableTokenFactory.sol similarity index 100% rename from protocol/packages/contracts/contracts/universal/OptimismMintableTokenFactory.sol rename to packages/contracts-bedrock/contracts/universal/OptimismMintableTokenFactory.sol diff --git a/protocol/packages/contracts/contracts/universal/StandardBridge.sol b/packages/contracts-bedrock/contracts/universal/StandardBridge.sol similarity index 100% rename from protocol/packages/contracts/contracts/universal/StandardBridge.sol rename to packages/contracts-bedrock/contracts/universal/StandardBridge.sol diff --git a/protocol/packages/contracts/deploy/000-L2OutputOracle.deploy.ts b/packages/contracts-bedrock/deploy/000-L2OutputOracle.deploy.ts similarity index 100% rename from protocol/packages/contracts/deploy/000-L2OutputOracle.deploy.ts rename to packages/contracts-bedrock/deploy/000-L2OutputOracle.deploy.ts diff --git a/protocol/packages/contracts/deploy/001-OptimismPortal.deploy.ts b/packages/contracts-bedrock/deploy/001-OptimismPortal.deploy.ts similarity index 100% rename from protocol/packages/contracts/deploy/001-OptimismPortal.deploy.ts rename to packages/contracts-bedrock/deploy/001-OptimismPortal.deploy.ts diff --git a/protocol/packages/contracts/deploy/002-L1CrossDomainMessenger.ts b/packages/contracts-bedrock/deploy/002-L1CrossDomainMessenger.ts similarity index 100% rename from protocol/packages/contracts/deploy/002-L1CrossDomainMessenger.ts rename to packages/contracts-bedrock/deploy/002-L1CrossDomainMessenger.ts diff --git a/protocol/packages/contracts/deploy/003-L1StandardBridge.ts b/packages/contracts-bedrock/deploy/003-L1StandardBridge.ts similarity index 100% rename from protocol/packages/contracts/deploy/003-L1StandardBridge.ts rename to packages/contracts-bedrock/deploy/003-L1StandardBridge.ts diff --git a/protocol/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts b/packages/contracts-bedrock/deploy/004-OptimismMintableTokenFactory.ts similarity index 100% rename from protocol/packages/contracts/deploy/004-OptimismMintableTokenFactory.ts rename to packages/contracts-bedrock/deploy/004-OptimismMintableTokenFactory.ts diff --git a/protocol/packages/contracts/foundry.toml b/packages/contracts-bedrock/foundry.toml similarity index 100% rename from protocol/packages/contracts/foundry.toml rename to packages/contracts-bedrock/foundry.toml diff --git a/protocol/packages/contracts/hardhat.config.ts b/packages/contracts-bedrock/hardhat.config.ts similarity index 100% rename from protocol/packages/contracts/hardhat.config.ts rename to packages/contracts-bedrock/hardhat.config.ts diff --git a/protocol/packages/contracts/helpers/constants.ts b/packages/contracts-bedrock/helpers/constants.ts similarity index 100% rename from protocol/packages/contracts/helpers/constants.ts rename to packages/contracts-bedrock/helpers/constants.ts diff --git a/protocol/packages/contracts/helpers/generateProofs.ts b/packages/contracts-bedrock/helpers/generateProofs.ts similarity index 100% rename from protocol/packages/contracts/helpers/generateProofs.ts rename to packages/contracts-bedrock/helpers/generateProofs.ts diff --git a/protocol/packages/contracts/helpers/index.ts b/packages/contracts-bedrock/helpers/index.ts similarity index 100% rename from protocol/packages/contracts/helpers/index.ts rename to packages/contracts-bedrock/helpers/index.ts diff --git a/protocol/packages/contracts/helpers/trie-test-generator.ts b/packages/contracts-bedrock/helpers/trie-test-generator.ts similarity index 100% rename from protocol/packages/contracts/helpers/trie-test-generator.ts rename to packages/contracts-bedrock/helpers/trie-test-generator.ts diff --git a/protocol/packages/contracts/helpers/utils.ts b/packages/contracts-bedrock/helpers/utils.ts similarity index 100% rename from protocol/packages/contracts/helpers/utils.ts rename to packages/contracts-bedrock/helpers/utils.ts diff --git a/packages/contracts-bedrock/lib/ds-test b/packages/contracts-bedrock/lib/ds-test new file mode 160000 index 000000000000..c7a36fb236f2 --- /dev/null +++ b/packages/contracts-bedrock/lib/ds-test @@ -0,0 +1 @@ +Subproject commit c7a36fb236f298e04edf28e2fee385b80f53945f diff --git a/packages/contracts-bedrock/lib/forge-std b/packages/contracts-bedrock/lib/forge-std new file mode 160000 index 000000000000..4d36e3f7e216 --- /dev/null +++ b/packages/contracts-bedrock/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 4d36e3f7e2168c8155c641eb0f80e85cd584bd1c diff --git a/packages/contracts-bedrock/lib/solmate b/packages/contracts-bedrock/lib/solmate new file mode 160000 index 000000000000..851ea3baa432 --- /dev/null +++ b/packages/contracts-bedrock/lib/solmate @@ -0,0 +1 @@ +Subproject commit 851ea3baa4327f453da723df75b1093b58b964dc diff --git a/protocol/packages/contracts/package.json b/packages/contracts-bedrock/package.json similarity index 100% rename from protocol/packages/contracts/package.json rename to packages/contracts-bedrock/package.json diff --git a/protocol/packages/contracts/scripts/ffiMakeProof.ts b/packages/contracts-bedrock/scripts/ffiMakeProof.ts similarity index 100% rename from protocol/packages/contracts/scripts/ffiMakeProof.ts rename to packages/contracts-bedrock/scripts/ffiMakeProof.ts diff --git a/protocol/packages/contracts/scripts/makeProof.ts b/packages/contracts-bedrock/scripts/makeProof.ts similarity index 100% rename from protocol/packages/contracts/scripts/makeProof.ts rename to packages/contracts-bedrock/scripts/makeProof.ts diff --git a/protocol/packages/contracts/slither.config.json b/packages/contracts-bedrock/slither.config.json similarity index 100% rename from protocol/packages/contracts/slither.config.json rename to packages/contracts-bedrock/slither.config.json diff --git a/protocol/packages/contracts/slither.db.json b/packages/contracts-bedrock/slither.db.json similarity index 100% rename from protocol/packages/contracts/slither.db.json rename to packages/contracts-bedrock/slither.db.json diff --git a/protocol/packages/contracts/tasks/deposits.ts b/packages/contracts-bedrock/tasks/deposits.ts similarity index 100% rename from protocol/packages/contracts/tasks/deposits.ts rename to packages/contracts-bedrock/tasks/deposits.ts diff --git a/protocol/packages/contracts/test/helpers.spec.ts b/packages/contracts-bedrock/test/helpers.spec.ts similarity index 100% rename from protocol/packages/contracts/test/helpers.spec.ts rename to packages/contracts-bedrock/test/helpers.spec.ts diff --git a/protocol/packages/contracts/tsconfig.json b/packages/contracts-bedrock/tsconfig.json similarity index 100% rename from protocol/packages/contracts/tsconfig.json rename to packages/contracts-bedrock/tsconfig.json diff --git a/protocol/packages/contracts/yarn.lock b/packages/contracts-bedrock/yarn.lock similarity index 100% rename from protocol/packages/contracts/yarn.lock rename to packages/contracts-bedrock/yarn.lock diff --git a/protocol/packages/integration-tests/.gitignore b/packages/integration-tests-bedrock/.gitignore similarity index 100% rename from protocol/packages/integration-tests/.gitignore rename to packages/integration-tests-bedrock/.gitignore diff --git a/protocol/packages/integration-tests/contracts/Counter.sol b/packages/integration-tests-bedrock/contracts/Counter.sol similarity index 100% rename from protocol/packages/integration-tests/contracts/Counter.sol rename to packages/integration-tests-bedrock/contracts/Counter.sol diff --git a/protocol/packages/integration-tests/contracts/ERC20.sol b/packages/integration-tests-bedrock/contracts/ERC20.sol similarity index 100% rename from protocol/packages/integration-tests/contracts/ERC20.sol rename to packages/integration-tests-bedrock/contracts/ERC20.sol diff --git a/protocol/packages/integration-tests/contracts/MultiDepositor.sol b/packages/integration-tests-bedrock/contracts/MultiDepositor.sol similarity index 100% rename from protocol/packages/integration-tests/contracts/MultiDepositor.sol rename to packages/integration-tests-bedrock/contracts/MultiDepositor.sol diff --git a/protocol/packages/integration-tests/contracts/Reverter.sol b/packages/integration-tests-bedrock/contracts/Reverter.sol similarity index 100% rename from protocol/packages/integration-tests/contracts/Reverter.sol rename to packages/integration-tests-bedrock/contracts/Reverter.sol diff --git a/protocol/packages/integration-tests/package.json b/packages/integration-tests-bedrock/package.json similarity index 100% rename from protocol/packages/integration-tests/package.json rename to packages/integration-tests-bedrock/package.json diff --git a/protocol/packages/integration-tests/test/000_withdrawals.spec.ts b/packages/integration-tests-bedrock/test/000_withdrawals.spec.ts similarity index 100% rename from protocol/packages/integration-tests/test/000_withdrawals.spec.ts rename to packages/integration-tests-bedrock/test/000_withdrawals.spec.ts diff --git a/protocol/packages/integration-tests/test/deposit.spec.ts b/packages/integration-tests-bedrock/test/deposit.spec.ts similarity index 100% rename from protocol/packages/integration-tests/test/deposit.spec.ts rename to packages/integration-tests-bedrock/test/deposit.spec.ts diff --git a/protocol/packages/integration-tests/test/rpc.spec.ts b/packages/integration-tests-bedrock/test/rpc.spec.ts similarity index 100% rename from protocol/packages/integration-tests/test/rpc.spec.ts rename to packages/integration-tests-bedrock/test/rpc.spec.ts diff --git a/protocol/packages/integration-tests/test/shared/env.ts b/packages/integration-tests-bedrock/test/shared/env.ts similarity index 100% rename from protocol/packages/integration-tests/test/shared/env.ts rename to packages/integration-tests-bedrock/test/shared/env.ts diff --git a/protocol/packages/integration-tests/test/shared/setup.ts b/packages/integration-tests-bedrock/test/shared/setup.ts similarity index 100% rename from protocol/packages/integration-tests/test/shared/setup.ts rename to packages/integration-tests-bedrock/test/shared/setup.ts diff --git a/protocol/packages/integration-tests/test/shared/utils.ts b/packages/integration-tests-bedrock/test/shared/utils.ts similarity index 100% rename from protocol/packages/integration-tests/test/shared/utils.ts rename to packages/integration-tests-bedrock/test/shared/utils.ts diff --git a/protocol/packages/integration-tests/tsconfig.json b/packages/integration-tests-bedrock/tsconfig.json similarity index 100% rename from protocol/packages/integration-tests/tsconfig.json rename to packages/integration-tests-bedrock/tsconfig.json diff --git a/protocol/packages/integration-tests/yarn.lock b/packages/integration-tests-bedrock/yarn.lock similarity index 100% rename from protocol/packages/integration-tests/yarn.lock rename to packages/integration-tests-bedrock/yarn.lock diff --git a/specs/README.md b/specs/README.md index cef0578d2c5a..a708eba898f4 100644 --- a/specs/README.md +++ b/specs/README.md @@ -1,5 +1,5 @@ -# Optimism specs +# Optimism Bedrock specs This directory contains the plain english specs for Optimism, an minimal optimistic rollup protocol that maintains 1:1 compatibility with Ethereum. From 4550c3bb8388881fda990dcb92d32e81dac4d3a1 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Sat, 14 May 2022 19:38:29 -0600 Subject: [PATCH 581/585] monorepo merge: fix Go env --- batch-submitter/go.mod | 58 +++++++++++++++++++++- batch-submitter/go.sum | 105 ++++++++++++++++++--------------------- bss-core/go.mod | 66 +++++++++++++++++++++++-- bss-core/go.sum | 90 +++++++++++++++++----------------- gas-oracle/go.mod | 61 ++++++++++++++++++++++- gas-oracle/go.sum | 87 ++++++++++++++++---------------- go.work | 6 +++ go.work.sum | 9 ++++ indexer/go.mod | 74 ++++++++++++++-------------- indexer/go.sum | 109 +++++++++++++++++++---------------------- l2geth-exporter/go.mod | 46 ++++++++++++++++- l2geth-exporter/go.sum | 76 ++++++++++++++-------------- l2geth/go.mod | 67 ++++++++++++++----------- l2geth/go.sum | 107 +++++++++++++++++++--------------------- op-batcher/go.sum | 5 +- op-e2e/go.sum | 14 ++++-- op-exporter/go.mod | 46 +++++++++++++++-- op-exporter/go.sum | 67 +++++++++---------------- op-node/go.mod | 6 ++- op-node/go.sum | 9 ++-- op-proposer/go.mod | 1 + op-proposer/go.sum | 5 +- proxyd/go.mod | 56 ++++++++++++++++++--- proxyd/go.sum | 83 ++++++++++++++----------------- teleportr/go.mod | 53 ++++++++++---------- teleportr/go.sum | 93 +++++++++++++++++------------------ 26 files changed, 837 insertions(+), 562 deletions(-) create mode 100644 go.work.sum diff --git a/batch-submitter/go.mod b/batch-submitter/go.mod index e10870c73b91..e96a0aef0e54 100644 --- a/batch-submitter/go.mod +++ b/batch-submitter/go.mod @@ -1,16 +1,70 @@ module github.com/ethereum-optimism/optimism/batch-submitter -go 1.16 +go 1.18 replace github.com/ethereum-optimism/optimism/bss-core v0.0.0 => ../bss-core + replace github.com/ethereum-optimism/optimism/l2geth v0.0.0 => ../l2geth require ( github.com/ethereum-optimism/optimism/bss-core v0.0.0 github.com/ethereum-optimism/optimism/l2geth v0.0.0 github.com/ethereum/go-ethereum v1.10.16 - github.com/getsentry/sentry-go v0.11.0 + github.com/getsentry/sentry-go v0.12.0 github.com/prometheus/client_golang v1.11.0 github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.5 ) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/base58 v1.0.3 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 // indirect + github.com/decred/dcrd/hdkeychain/v3 v3.0.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect + github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) diff --git a/batch-submitter/go.sum b/batch-submitter/go.sum index be54c5bd5be3..5a718fec1448 100644 --- a/batch-submitter/go.sum +++ b/batch-submitter/go.sum @@ -40,10 +40,9 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= @@ -54,8 +53,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy 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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= 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/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= @@ -79,8 +78,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -95,10 +95,9 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -110,10 +109,9 @@ github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= 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= @@ -161,33 +159,30 @@ github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRP github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa h1:XKAhUk/dtp+CV0VO6mhG2V7jA9vbcGcnYF/Ay9NjZrY= -github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/go-ethereum v1.10.12/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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/getsentry/sentry-go v0.11.0 h1:qro8uttJGvNAMr5CLcFI9CHR0aDzXl0Vs3Pmw/oTPg8= -github.com/getsentry/sentry-go v0.11.0/go.mod h1:KBQIxiZAetw62Cj8Ri964vAEWVdgfaUCn30Q3bCvANo= +github.com/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= @@ -200,23 +195,23 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm 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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= 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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= @@ -240,8 +235,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -257,8 +252,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -267,19 +262,19 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 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/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.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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= @@ -291,8 +286,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -337,7 +332,6 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 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/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= @@ -365,7 +359,6 @@ 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.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= 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= @@ -377,19 +370,19 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -399,10 +392,10 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -417,8 +410,8 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -426,18 +419,17 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/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 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= 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/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/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 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= @@ -466,34 +458,33 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q 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 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= 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/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 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= 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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 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= @@ -508,8 +499,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= @@ -526,12 +517,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -557,6 +548,7 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 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= @@ -578,8 +570,8 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -637,8 +629,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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= @@ -698,8 +690,8 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -708,13 +700,13 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -748,7 +740,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -793,8 +784,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -825,8 +816,8 @@ 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-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/bss-core/go.mod b/bss-core/go.mod index 5596fe64404e..f45a870fc0ee 100644 --- a/bss-core/go.mod +++ b/bss-core/go.mod @@ -1,13 +1,71 @@ module github.com/ethereum-optimism/optimism/bss-core -go 1.16 +go 1.18 require ( - github.com/btcsuite/btcd v0.22.0-beta // indirect github.com/decred/dcrd/hdkeychain/v3 v3.0.0 github.com/ethereum/go-ethereum v1.10.16 - github.com/getsentry/sentry-go v0.11.0 + github.com/getsentry/sentry-go v0.12.0 github.com/prometheus/client_golang v1.11.0 github.com/stretchr/testify v1.7.0 - github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef + github.com/tyler-smith/go-bip39 v1.1.0 +) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/allegro/bigcache v1.2.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/base58 v1.0.3 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/crypto/ripemd160 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-kit/kit v0.10.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-cmp v0.5.8 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect + github.com/onsi/gomega v1.16.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/bss-core/go.sum b/bss-core/go.sum index 78fbd40899f0..a125801f4954 100644 --- a/bss-core/go.sum +++ b/bss-core/go.sum @@ -40,10 +40,9 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= @@ -54,8 +53,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy 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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= 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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -78,6 +77,7 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2 github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -91,10 +91,9 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f 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 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -153,8 +152,8 @@ github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRP github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -164,19 +163,18 @@ github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5w github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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/getsentry/sentry-go v0.11.0 h1:qro8uttJGvNAMr5CLcFI9CHR0aDzXl0Vs3Pmw/oTPg8= -github.com/getsentry/sentry-go v0.11.0/go.mod h1:KBQIxiZAetw62Cj8Ri964vAEWVdgfaUCn30Q3bCvANo= +github.com/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= @@ -189,22 +187,22 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm 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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= 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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= @@ -228,8 +226,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -245,8 +243,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -255,18 +253,18 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 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/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.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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= @@ -278,8 +276,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -349,7 +347,6 @@ 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.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= 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= @@ -361,19 +358,19 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -383,10 +380,10 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -401,8 +398,8 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -410,13 +407,13 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/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 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= 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/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= @@ -449,21 +446,22 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q 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 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= 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/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 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -471,8 +469,8 @@ github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtm 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 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= @@ -487,8 +485,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -501,12 +499,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -529,6 +527,7 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 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= @@ -550,8 +549,8 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -607,8 +606,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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= @@ -668,8 +667,8 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -678,13 +677,13 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -717,7 +716,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -762,8 +760,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -793,8 +791,8 @@ 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-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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= diff --git a/gas-oracle/go.mod b/gas-oracle/go.mod index 91d2428eef4d..370603d96bb5 100644 --- a/gas-oracle/go.mod +++ b/gas-oracle/go.mod @@ -1,8 +1,65 @@ module github.com/ethereum-optimism/optimism/gas-oracle -go 1.16 +go 1.18 require ( github.com/ethereum/go-ethereum v1.10.16 - github.com/urfave/cli v1.20.0 + github.com/urfave/cli v1.22.5 +) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/allegro/bigcache v1.2.1 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/deepmap/oapi-codegen v1.8.2 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-kit/kit v0.10.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-cmp v0.5.8 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/influxdata/influxdb v1.8.3 // indirect + github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect + github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect + github.com/onsi/gomega v1.16.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/gas-oracle/go.sum b/gas-oracle/go.sum index a4e249d41f22..b30506f6e850 100644 --- a/gas-oracle/go.sum +++ b/gas-oracle/go.sum @@ -35,16 +35,15 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= 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/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= @@ -60,8 +59,9 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 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 v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -73,10 +73,9 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -85,6 +84,7 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h 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/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= 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= @@ -105,21 +105,21 @@ github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r 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 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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= @@ -128,19 +128,19 @@ github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1T 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-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/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= @@ -175,25 +175,25 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 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/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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 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/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 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -203,8 +203,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -246,7 +246,6 @@ github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM52 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/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= 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.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -266,45 +265,45 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= 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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 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/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.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 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= 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/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= @@ -330,20 +329,22 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 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/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -352,8 +353,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO 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 v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -366,14 +367,14 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= 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= @@ -381,6 +382,7 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ 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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 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= @@ -397,8 +399,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -449,8 +451,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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= @@ -502,8 +504,8 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -512,13 +514,13 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -549,7 +551,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -616,8 +617,8 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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= diff --git a/go.work b/go.work index b70fbe2b9435..247cab8c6d48 100644 --- a/go.work +++ b/go.work @@ -7,7 +7,11 @@ use ( ./indexer ./l2geth ./l2geth-exporter + ./op-batcher + ./op-e2e ./op-exporter + ./op-node + ./op-proposer ./proxyd ./teleportr ) @@ -15,3 +19,5 @@ use ( replace github.com/ethereum-optimism/optimism/bss-core v0.0.0 => ./bss-core replace github.com/ethereum-optimism/optimism/l2geth v0.0.0 => ./l2geth + +replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 000000000000..339aba62148f --- /dev/null +++ b/go.work.sum @@ -0,0 +1,9 @@ +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce h1:Wa0BVNdeyzIoJkrZtI7o2NEw8F98vVIzkPpiFACbdCA= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= +github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= diff --git a/indexer/go.mod b/indexer/go.mod index d5a779b4eb7c..2892767ba841 100644 --- a/indexer/go.mod +++ b/indexer/go.mod @@ -10,63 +10,65 @@ require ( github.com/getsentry/sentry-go v0.12.0 github.com/google/uuid v1.3.0 github.com/gorilla/mux v1.8.0 - github.com/lib/pq v1.0.0 - github.com/prometheus/client_golang v1.0.0 - github.com/rs/cors v1.7.0 + github.com/lib/pq v1.10.4 + github.com/prometheus/client_golang v1.11.0 + github.com/rs/cors v1.8.2 github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.5 ) require ( - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/VictoriaMetrics/fastcache v1.6.0 // indirect + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect - github.com/beorn7/perks v1.0.0 // indirect - github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect - github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa // indirect - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-stack/stack v1.8.0 // indirect - github.com/golang/protobuf v1.4.3 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect - github.com/huin/goupnp v1.0.2 // indirect + github.com/huin/goupnp v1.0.3 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/karalabe/usb v0.0.2 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 // indirect + github.com/pborman/uuid v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect - github.com/prometheus/common v0.6.0 // indirect - github.com/prometheus/procfs v0.0.2 // indirect - github.com/prometheus/tsdb v0.7.1 // indirect - github.com/rjeczalik/notify v0.9.1 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // 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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect - golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - google.golang.org/protobuf v1.23.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/indexer/go.sum b/indexer/go.sum index d22d037ce942..a7380905026e 100644 --- a/indexer/go.sum +++ b/indexer/go.sum @@ -40,17 +40,16 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= 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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= 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/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= @@ -68,13 +67,14 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxq github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -91,8 +91,8 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -106,8 +106,8 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= 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= @@ -133,31 +133,27 @@ github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRP github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa h1:XKAhUk/dtp+CV0VO6mhG2V7jA9vbcGcnYF/Ay9NjZrY= -github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220104205740-f39387287484 h1:HbNZa+JqIBEWgTmqUY6/iHNNKWVycVFSQ9BJitYIy6U= -github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220104205740-f39387287484/go.mod h1:Tiv7YftnDjuhq2ktkynxSujAASpUxZP+E0RRPjQD3z0= -github.com/ethereum/go-ethereum v1.10.12/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk= @@ -173,21 +169,21 @@ github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 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-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= @@ -212,8 +208,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -229,8 +225,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -248,12 +244,12 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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= @@ -265,8 +261,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -307,7 +303,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V 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/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= @@ -326,7 +321,6 @@ github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo 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/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= 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.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -340,8 +334,8 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= 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 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 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= @@ -350,8 +344,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO 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-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -362,8 +356,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -373,10 +367,10 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -390,8 +384,8 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -399,19 +393,18 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/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 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= 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/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/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= -github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 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= @@ -427,40 +420,40 @@ github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUI 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 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= 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_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= 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/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 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= 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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -473,8 +466,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= @@ -491,12 +484,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -523,6 +516,7 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 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= @@ -545,8 +539,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -605,8 +599,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f h1:1scJEYZBaF48BaG6tYbtxmLcXqwYGSfGcMoStTqkkIw= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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= @@ -666,11 +660,11 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= 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= @@ -683,8 +677,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -718,7 +712,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -762,8 +755,8 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -792,8 +785,8 @@ 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-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/l2geth-exporter/go.mod b/l2geth-exporter/go.mod index 4db6f032ccf7..56e462291e15 100644 --- a/l2geth-exporter/go.mod +++ b/l2geth-exporter/go.mod @@ -1,8 +1,52 @@ module github.com/ethereum-optimism/optimism/l2geth-exporter -go 1.16 +go 1.18 require ( github.com/ethereum/go-ethereum v1.10.16 github.com/prometheus/client_golang v1.11.0 ) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-cmp v0.5.8 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.4.3 // 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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) diff --git a/l2geth-exporter/go.sum b/l2geth-exporter/go.sum index df5e34681f80..4c1e96a81c25 100644 --- a/l2geth-exporter/go.sum +++ b/l2geth-exporter/go.sum @@ -35,10 +35,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 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= @@ -64,8 +63,9 @@ 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 v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -77,10 +77,9 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -108,20 +107,20 @@ github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r 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 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= 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 h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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= @@ -136,14 +135,14 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb 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-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/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= @@ -164,8 +163,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -180,8 +179,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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= @@ -189,17 +188,17 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 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/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 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -209,8 +208,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -271,26 +270,26 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= 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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -340,27 +339,28 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q 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 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= 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/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 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 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= @@ -371,8 +371,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO 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 v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -385,12 +385,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= 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= @@ -398,6 +398,7 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ 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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 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= @@ -414,8 +415,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -525,8 +526,8 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -535,13 +536,13 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -572,7 +573,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -617,8 +617,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -640,8 +640,8 @@ 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/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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= diff --git a/l2geth/go.mod b/l2geth/go.mod index 8b2609e85a32..d8f98f8794dc 100644 --- a/l2geth/go.mod +++ b/l2geth/go.mod @@ -4,59 +4,70 @@ go 1.15 require ( github.com/Azure/azure-storage-blob-go v0.7.0 - github.com/VictoriaMetrics/fastcache v1.6.0 + github.com/Azure/go-autorest/autorest/adal v0.9.5 // indirect + github.com/VictoriaMetrics/fastcache v1.9.0 + github.com/allegro/bigcache v1.2.1 // indirect github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 github.com/aws/aws-sdk-go v1.42.6 - github.com/btcsuite/btcd v0.22.0-beta + github.com/btcsuite/btcd v0.22.1 github.com/cespare/cp v0.1.0 github.com/cloudflare/cloudflare-go v0.14.0 github.com/davecgh/go-spew v1.1.1 - github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea + github.com/deckarep/golang-set v1.8.0 github.com/docker/docker v20.10.10+incompatible - github.com/edsrzf/mmap-go v1.0.0 - github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa - github.com/ethereum/go-ethereum v1.10.12 + github.com/edsrzf/mmap-go v1.1.0 + github.com/elastic/gosigar v0.12.0 + github.com/ethereum/go-ethereum v1.10.16 github.com/fatih/color v1.7.0 - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff + github.com/fjl/memsize v0.0.1 + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 + github.com/go-kit/kit v0.10.0 // indirect github.com/go-resty/resty/v2 v2.4.0 - github.com/go-stack/stack v1.8.0 - github.com/golang/protobuf v1.4.3 + github.com/go-stack/stack v1.8.1 + github.com/golang/protobuf v1.5.2 github.com/golang/snappy v0.0.4 - github.com/gorilla/websocket v1.4.2 - github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 + github.com/google/go-cmp v0.5.8 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 + github.com/graph-gophers/graphql-go v1.3.0 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d - github.com/huin/goupnp v1.0.2 + github.com/huin/goupnp v1.0.3 github.com/influxdata/influxdb v1.8.3 - github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 + github.com/jackpal/go-nat-pmp v1.0.2 github.com/jarcoal/httpmock v1.0.8 - github.com/julienschmidt/httprouter v1.2.0 - github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559 - github.com/mattn/go-colorable v0.1.8 - github.com/mattn/go-isatty v0.0.12 + github.com/julienschmidt/httprouter v1.3.0 + github.com/karalabe/usb v0.0.2 + github.com/mattn/go-colorable v0.1.12 + github.com/mattn/go-isatty v0.0.14 + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 - github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 + github.com/onsi/gomega v1.16.0 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pborman/uuid v1.2.0 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 - github.com/prometheus/tsdb v0.7.1 - github.com/rjeczalik/notify v0.9.1 + github.com/prometheus/tsdb v0.10.0 + github.com/rjeczalik/notify v0.9.2 github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff - github.com/rs/cors v1.7.0 - github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 + github.com/rs/cors v1.8.2 + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef + github.com/tyler-smith/go-bip39 v1.1.0 github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 - golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 - golang.org/x/text v0.3.6 - golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/urfave/cli.v1 v1.20.0 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gotest.tools/v3 v3.0.3 // indirect ) diff --git a/l2geth/go.sum b/l2geth/go.sum index 5c54b8a4040d..2a31ff381532 100644 --- a/l2geth/go.sum +++ b/l2geth/go.sum @@ -23,36 +23,35 @@ github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-storage-blob-go v0.7.0 h1:MuueVOYkufCxJw5YZzF842DY2MBsp+hLuh2apKY0mck= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0 h1:CxTzQrySOxDnKpLjFJeZAS5Qrv/qFPkgLjx5bOAi//I= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= 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/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= @@ -73,8 +72,9 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -91,8 +91,8 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -109,12 +109,11 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 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 v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 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 h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 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= @@ -125,24 +124,23 @@ github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05 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 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa h1:XKAhUk/dtp+CV0VO6mhG2V7jA9vbcGcnYF/Ay9NjZrY= -github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.10.12 h1:el/KddB3gLEsnNgGQ3SQuZuiZjwnFTYHe5TwUet5Om4= -github.com/ethereum/go-ethereum v1.10.12/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= +github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= 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 h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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= @@ -151,12 +149,11 @@ github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1T 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-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= @@ -164,8 +161,8 @@ github.com/go-resty/resty/v2 v2.4.0 h1:s6TItTLejEI+2mn98oijC5w/Rk2YU+OA6x0mnZN6r github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/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= @@ -186,8 +183,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -201,8 +198,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 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/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -210,14 +207,15 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 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/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 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 h1:sezaKhEfPFg8W0Enm61B9Gs911H8iesGY5R8NDPtd1M= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= 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= @@ -226,8 +224,8 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:i 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -243,8 +241,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y 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-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jarcoal/httpmock v1.0.8 h1:8kI16SoO6LQKgPE7PvQuV+YuD/inwHd7fOOe2zMbo4k= github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= @@ -260,12 +258,11 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 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 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= 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.0-20211005121534-4c5740d64559 h1:0VWDXPNE0brOek1Q8bLfzKkvOzwbQE/snjGojlCr8CY= -github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= @@ -274,7 +271,6 @@ github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM52 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/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= 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.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -295,19 +291,19 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= 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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -321,28 +317,27 @@ github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hz 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= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.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 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= 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/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 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= -github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= -github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= @@ -365,16 +360,17 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 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/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff h1:+6NUiITWwE5q1KO6SAfUX918c+Tab0+tGAM/mtdlUyA= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= 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= @@ -388,8 +384,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO 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 v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= @@ -408,8 +404,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45 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 h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= 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= @@ -437,8 +433,8 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -492,8 +488,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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= @@ -545,24 +541,24 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -594,7 +590,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -638,8 +633,8 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -665,8 +660,8 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= diff --git a/op-batcher/go.sum b/op-batcher/go.sum index 532503582af4..6f6a934173d6 100644 --- a/op-batcher/go.sum +++ b/op-batcher/go.sum @@ -126,6 +126,7 @@ github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= @@ -866,8 +867,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1031,8 +1032,8 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= 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= diff --git a/op-e2e/go.sum b/op-e2e/go.sum index bdb5e1c86239..60300e13c4eb 100644 --- a/op-e2e/go.sum +++ b/op-e2e/go.sum @@ -124,7 +124,6 @@ github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MR github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= -github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= @@ -245,10 +244,11 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead h1:AiLggtwXHmAGxNusOEH7edb83TtJnavtR2uY1z6YzYc= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220427171107-d0070e0a6ead/go.mod h1:m2COxrfN3y8Yc0+FBC04+TVGFq9cAgxGO2QsEiiBYJM= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce h1:Wa0BVNdeyzIoJkrZtI7o2NEw8F98vVIzkPpiFACbdCA= +github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -263,6 +263,7 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= @@ -560,6 +561,7 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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 v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 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= @@ -858,6 +860,7 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= 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= @@ -869,8 +872,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1035,8 +1038,8 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= 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= @@ -1414,6 +1417,7 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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= diff --git a/op-exporter/go.mod b/op-exporter/go.mod index 20df8aa9ac31..9cd066a5f0d5 100644 --- a/op-exporter/go.mod +++ b/op-exporter/go.mod @@ -1,13 +1,51 @@ module github.com/ethereum-optimism/optimism/op-exporter -go 1.16 +go 1.18 require ( - github.com/ethereum/go-ethereum v1.10.4 - github.com/prometheus/client_golang v1.4.0 - github.com/sirupsen/logrus v1.4.2 + github.com/ethereum/go-ethereum v1.10.16 + github.com/prometheus/client_golang v1.11.0 + github.com/sirupsen/logrus v1.7.0 github.com/ybbus/jsonrpc v2.1.2+incompatible gopkg.in/alecthomas/kingpin.v2 v2.2.6 k8s.io/apimachinery v0.21.2 k8s.io/client-go v0.21.2 ) + +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/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/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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // 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.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // 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 + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + k8s.io/api v0.21.2 // indirect + k8s.io/klog/v2 v2.8.0 // indirect + k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.0 // indirect + sigs.k8s.io/yaml v1.2.0 // indirect +) diff --git a/op-exporter/go.sum b/op-exporter/go.sum index cc15dc5481e2..58c2898f9916 100644 --- a/op-exporter/go.sum +++ b/op-exporter/go.sum @@ -60,8 +60,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy 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 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= 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/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= @@ -92,10 +92,9 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f 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 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -110,24 +109,18 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 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 v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= 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.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 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-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 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.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/op_exporter v0.0.0-20211207210647-c5a8db939ad4 h1:tTFuDWKAWayPWkqWd8CPwSfDoO4tMVScZgM5nhXs2+c= -github.com/ethereum-optimism/op_exporter v0.0.0-20211207210647-c5a8db939ad4/go.mod h1:w2HqYJpeDcqB6ZpPDsD7NmkvJCDAs23uNW7YHTn4g0M= -github.com/ethereum/go-ethereum v1.10.4 h1:JPZPL2MHbegfFStcaOrrggMVIcf57OQHQ0J3UhjQ+xQ= -github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= +github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= 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= @@ -156,7 +149,6 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9 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.2+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/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -187,10 +179,9 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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= @@ -201,8 +192,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 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= @@ -223,7 +214,6 @@ github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyyc 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/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 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= @@ -231,7 +221,6 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:i 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.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= 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= @@ -244,16 +233,14 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y 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-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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/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.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= 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/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= @@ -261,7 +248,6 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 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.0-20190919080040-51dc0efba356/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= @@ -270,11 +256,11 @@ github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 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 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/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/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= @@ -286,11 +272,9 @@ 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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 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= @@ -311,7 +295,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW 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 h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= 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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -326,8 +309,8 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= 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/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= @@ -345,8 +328,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb 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.4.0 h1:YVIb/fVcOTMSqtqZWSKnHpSLBxu8DKgxq8z6RuBZwqI= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= 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_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -355,12 +337,10 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T 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.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= 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.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= 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= @@ -373,8 +353,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm 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 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= 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= @@ -396,7 +376,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P 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.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= 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= @@ -465,7 +444,6 @@ 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-20181011144130-49bb7cea24b1/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= @@ -490,14 +468,14 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 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 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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 h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 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/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= @@ -545,25 +523,25 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= 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 h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= 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 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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 h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -606,7 +584,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -628,8 +605,8 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl 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 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= 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/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= @@ -666,15 +643,15 @@ 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.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= 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/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= @@ -692,8 +669,8 @@ 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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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= diff --git a/op-node/go.mod b/op-node/go.mod index 76cff91645be..f50edcb93b8e 100644 --- a/op-node/go.mod +++ b/op-node/go.mod @@ -3,6 +3,7 @@ module github.com/ethereum-optimism/optimism/op-node go 1.18 require ( + github.com/ethereum-optimism/optimism/op-proposer v0.0.0 github.com/ethereum/go-ethereum v1.10.16 github.com/golang/snappy v0.0.4 github.com/google/go-cmp v0.5.8 @@ -144,11 +145,10 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect - github.com/stretchr/objx v0.1.1 // indirect + github.com/stretchr/objx v0.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect @@ -173,5 +173,7 @@ require ( replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220428214415-643b449b5818 +replace github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer + // For local debugging: // replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/op-node/go.sum b/op-node/go.sum index 0a61b387c037..dc0363ee5927 100644 --- a/op-node/go.sum +++ b/op-node/go.sum @@ -112,8 +112,10 @@ github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= @@ -346,6 +348,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -840,8 +843,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1006,8 +1009,9 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +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= @@ -1029,7 +1033,6 @@ github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hM github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= diff --git a/op-proposer/go.mod b/op-proposer/go.mod index f00201fe60d1..0166afe8eb7f 100644 --- a/op-proposer/go.mod +++ b/op-proposer/go.mod @@ -113,6 +113,7 @@ require ( github.com/multiformats/go-multistream v0.2.2 // indirect github.com/multiformats/go-varint v0.0.6 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/gomega v1.16.0 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/op-proposer/go.sum b/op-proposer/go.sum index b65acda124db..863b482061ca 100644 --- a/op-proposer/go.sum +++ b/op-proposer/go.sum @@ -867,8 +867,9 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1032,8 +1033,8 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= 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= diff --git a/proxyd/go.mod b/proxyd/go.mod index 9ed597833247..8415a9492e3c 100644 --- a/proxyd/go.mod +++ b/proxyd/go.mod @@ -1,22 +1,66 @@ module github.com/ethereum-optimism/optimism/proxyd -go 1.16 +go 1.18 require ( github.com/BurntSushi/toml v0.4.1 - github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/alicebob/miniredis v2.5.0+incompatible github.com/ethereum/go-ethereum v1.10.16 github.com/go-redis/redis/v8 v8.11.4 github.com/golang/snappy v0.0.4 - github.com/gomodule/redigo v1.8.8 // indirect github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.4.2 + github.com/gorilla/websocket v1.5.0 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/prometheus/client_golang v1.11.0 - github.com/rs/cors v1.8.0 + github.com/rs/cors v1.8.2 github.com/stretchr/testify v1.7.0 - github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c +) + +require ( + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/gomodule/redigo v1.8.8 // indirect + github.com/google/go-cmp v0.5.8 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/pmezard/go-difflib v1.0.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 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/proxyd/go.sum b/proxyd/go.sum index 128f28cdd1b9..88dd55311acd 100644 --- a/proxyd/go.sum +++ b/proxyd/go.sum @@ -37,10 +37,9 @@ github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi 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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 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= @@ -70,8 +69,9 @@ 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 v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -82,7 +82,6 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f 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 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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= @@ -116,26 +115,24 @@ github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r 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 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= 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= @@ -147,18 +144,16 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb 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-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-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= @@ -201,8 +196,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.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.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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= @@ -210,18 +205,18 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -231,8 +226,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -256,7 +251,6 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC 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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -289,7 +283,6 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ 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/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= 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= @@ -297,26 +290,26 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= 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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -372,28 +365,28 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q 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 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= 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/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 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= 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/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so= -github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 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= @@ -404,8 +397,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO 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 v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -418,14 +411,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= 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= @@ -435,6 +426,7 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 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= @@ -451,8 +443,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -505,8 +497,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/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-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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= @@ -566,8 +558,8 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -576,13 +568,13 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -614,7 +606,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -660,8 +651,8 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -670,8 +661,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN 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/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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= diff --git a/teleportr/go.mod b/teleportr/go.mod index fe2807a76b72..6c170ade2c4c 100644 --- a/teleportr/go.mod +++ b/teleportr/go.mod @@ -11,18 +11,17 @@ require ( github.com/gorilla/mux v1.8.0 github.com/lib/pq v1.10.4 github.com/prometheus/client_golang v1.11.0 - github.com/rs/cors v1.7.0 + github.com/rs/cors v1.8.2 github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.5 ) require ( - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/VictoriaMetrics/fastcache v1.6.0 // indirect + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/base58 v1.0.3 // indirect @@ -30,36 +29,38 @@ require ( github.com/decred/dcrd/crypto/ripemd160 v1.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 // indirect github.com/decred/dcrd/hdkeychain/v3 v3.0.0 // indirect - github.com/getsentry/sentry-go v0.11.0 // indirect - github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-stack/stack v1.8.0 // indirect - github.com/golang/protobuf v1.4.3 // indirect + github.com/getsentry/sentry-go v0.12.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.0 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect - github.com/prometheus/tsdb v0.7.1 // indirect - github.com/rjeczalik/notify v0.9.1 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/prometheus/common v0.30.0 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef // indirect - golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect - golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect - google.golang.org/protobuf v1.26.0-rc.1 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) - diff --git a/teleportr/go.sum b/teleportr/go.sum index 157a0e550403..9313ea21276e 100644 --- a/teleportr/go.sum +++ b/teleportr/go.sum @@ -40,10 +40,9 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= @@ -54,8 +53,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy 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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= 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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -94,8 +93,8 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 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/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= @@ -109,8 +108,8 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= 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= @@ -157,31 +156,29 @@ github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRP github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/go-ethereum v1.10.12/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= 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/getsentry/sentry-go v0.11.0 h1:qro8uttJGvNAMr5CLcFI9CHR0aDzXl0Vs3Pmw/oTPg8= -github.com/getsentry/sentry-go v0.11.0/go.mod h1:KBQIxiZAetw62Cj8Ri964vAEWVdgfaUCn30Q3bCvANo= +github.com/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= @@ -194,22 +191,22 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm 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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= 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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 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 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= @@ -233,8 +230,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -250,8 +247,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 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-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -269,12 +266,12 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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= @@ -286,8 +283,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= 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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -331,7 +328,6 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 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/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= @@ -359,7 +355,6 @@ 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.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= 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= @@ -373,19 +368,19 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG 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 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 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/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -395,10 +390,10 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -413,8 +408,8 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -422,13 +417,13 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/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 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= 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/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= @@ -461,33 +456,33 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q 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 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= 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/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 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= 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 h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= 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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 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= @@ -502,8 +497,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -516,12 +511,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -546,6 +541,7 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 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= @@ -567,8 +563,8 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= 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= @@ -624,8 +620,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= 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= @@ -685,8 +681,8 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -695,13 +691,13 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= 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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -734,7 +730,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -779,8 +774,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -810,8 +805,8 @@ 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-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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= From 61c6cda1cee260471479ca9ea7d3c0d1ad4706d5 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Sat, 14 May 2022 21:00:42 -0600 Subject: [PATCH 582/585] monorepo merge: move contracts-bedrock into non-Lerna package --- .gitmodules | 6 +- .../.eslintignore | 0 .../.eslintrc.js | 0 .../.gas-snapshot | 0 .../.gitignore | 0 .../.npmignore | 0 .../.prettierignore | 0 .../.prettierrc.js | 0 .../.solhint.json | 0 .../.solhintignore | 0 .../LICENSE | 0 .../README.md | 0 .../contracts/L1/L1CrossDomainMessenger.sol | 0 .../contracts/L1/L1StandardBridge.sol | 0 .../contracts/L1/L2OutputOracle.sol | 0 .../contracts/L1/OptimismPortal.sol | 0 .../contracts/L2/Burner.sol | 0 .../contracts/L2/L1Block.sol | 0 .../contracts/L2/L1BlockNumber.sol | 0 .../contracts/L2/L2CrossDomainMessenger.sol | 0 .../contracts/L2/L2StandardBridge.sol | 0 .../contracts/L2/L2ToL1MessagePasser.sol | 0 .../libraries/ExcessivelySafeCall.sol | 0 .../Lib_BedrockPredeployAddresses.sol | 0 .../libraries/Lib_CrossDomainHashing.sol | 0 .../libraries/Lib_WithdrawalVerifier.sol | 0 .../contracts/test/CommonTest.t.sol | 0 .../contracts/test/CrossDomainHashing.t.sol | 0 .../contracts/test/L1Block.t.sol | 0 .../contracts/test/L1BlockNumber.t.sol | 0 .../test/L1CrossDomainMessenger.t.sol | 0 .../contracts/test/L1StandardBridge.t.sol | 0 .../test/L2CrossDomainMessenger.t.sol | 0 .../contracts/test/L2OutputOracle.t.sol | 0 .../contracts/test/L2StandardBridge.t.sol | 0 .../contracts/test/L2ToL1MessagePasser.t.sol | 0 .../contracts/test/Lib_RLP.t.sol | 0 .../test/OptimismMintableERC20.t.sol | 0 .../test/OptimismMintableTokenFactory.t.sol | 0 .../contracts/test/OptimismPortal.t.sol | 0 .../universal/CrossDomainMessenger.sol | 0 .../universal/OptimismMintableERC20.sol | 0 .../OptimismMintableTokenFactory.sol | 0 .../contracts/universal/StandardBridge.sol | 0 .../deploy/000-L2OutputOracle.deploy.ts | 0 .../deploy/001-OptimismPortal.deploy.ts | 0 .../deploy/002-L1CrossDomainMessenger.ts | 0 .../deploy/003-L1StandardBridge.ts | 0 .../004-OptimismMintableTokenFactory.ts | 0 .../foundry.toml | 0 .../hardhat.config.ts | 0 .../helpers/constants.ts | 0 .../helpers/generateProofs.ts | 0 .../helpers/index.ts | 0 .../helpers/trie-test-generator.ts | 0 .../helpers/utils.ts | 0 .../lib/ds-test | 0 .../lib/forge-std | 0 .../lib/solmate | 0 .../package.json | 0 .../scripts/ffiMakeProof.ts | 0 .../scripts/makeProof.ts | 0 .../slither.config.json | 0 .../slither.db.json | 0 .../tasks/deposits.ts | 0 .../test/helpers.spec.ts | 0 .../tsconfig.json | 0 .../yarn.lock | 0 package.json | 6 +- .../integration-tests-bedrock/package.json | 5 +- yarn.lock | 1604 ++++++++++++++++- 71 files changed, 1549 insertions(+), 72 deletions(-) rename {packages/contracts-bedrock => contracts-bedrock}/.eslintignore (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.eslintrc.js (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.gas-snapshot (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.gitignore (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.npmignore (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.prettierignore (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.prettierrc.js (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.solhint.json (100%) rename {packages/contracts-bedrock => contracts-bedrock}/.solhintignore (100%) rename {packages/contracts-bedrock => contracts-bedrock}/LICENSE (100%) rename {packages/contracts-bedrock => contracts-bedrock}/README.md (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L1/L1CrossDomainMessenger.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L1/L1StandardBridge.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L1/L2OutputOracle.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L1/OptimismPortal.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L2/Burner.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L2/L1Block.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L2/L1BlockNumber.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L2/L2CrossDomainMessenger.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L2/L2StandardBridge.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/L2/L2ToL1MessagePasser.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/libraries/ExcessivelySafeCall.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/libraries/Lib_BedrockPredeployAddresses.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/libraries/Lib_CrossDomainHashing.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/libraries/Lib_WithdrawalVerifier.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/CommonTest.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/CrossDomainHashing.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L1Block.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L1BlockNumber.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L1CrossDomainMessenger.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L1StandardBridge.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L2CrossDomainMessenger.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L2OutputOracle.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L2StandardBridge.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/L2ToL1MessagePasser.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/Lib_RLP.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/OptimismMintableERC20.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/OptimismMintableTokenFactory.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/test/OptimismPortal.t.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/universal/CrossDomainMessenger.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/universal/OptimismMintableERC20.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/universal/OptimismMintableTokenFactory.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/contracts/universal/StandardBridge.sol (100%) rename {packages/contracts-bedrock => contracts-bedrock}/deploy/000-L2OutputOracle.deploy.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/deploy/001-OptimismPortal.deploy.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/deploy/002-L1CrossDomainMessenger.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/deploy/003-L1StandardBridge.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/deploy/004-OptimismMintableTokenFactory.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/foundry.toml (100%) rename {packages/contracts-bedrock => contracts-bedrock}/hardhat.config.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/helpers/constants.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/helpers/generateProofs.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/helpers/index.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/helpers/trie-test-generator.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/helpers/utils.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/lib/ds-test (100%) rename {packages/contracts-bedrock => contracts-bedrock}/lib/forge-std (100%) rename {packages/contracts-bedrock => contracts-bedrock}/lib/solmate (100%) rename {packages/contracts-bedrock => contracts-bedrock}/package.json (100%) rename {packages/contracts-bedrock => contracts-bedrock}/scripts/ffiMakeProof.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/scripts/makeProof.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/slither.config.json (100%) rename {packages/contracts-bedrock => contracts-bedrock}/slither.db.json (100%) rename {packages/contracts-bedrock => contracts-bedrock}/tasks/deposits.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/test/helpers.spec.ts (100%) rename {packages/contracts-bedrock => contracts-bedrock}/tsconfig.json (100%) rename {packages/contracts-bedrock => contracts-bedrock}/yarn.lock (100%) diff --git a/.gitmodules b/.gitmodules index da4de9866f39..7db875da0070 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,11 +2,11 @@ path = l2geth/tests/testdata url = https://github.com/ethereum/tests [submodule "packages/contracts-bedrock/lib/forge-std"] - path = packages/contracts-bedrock/lib/forge-std + path = contracts-bedrock/lib/forge-std url = https://github.com/foundry-rs/forge-std.git [submodule "packages/contracts-bedrock/lib/solmate"] - path = packages/contracts-bedrock/lib/solmate + path = contracts-bedrock/lib/solmate url = https://github.com/rari-capital/solmate.git [submodule "packages/contracts-bedrock/lib/ds-test"] - path = packages/contracts-bedrock/lib/ds-test + path = contracts-bedrock/lib/ds-test url = https://github.com/dapphub/ds-test.git diff --git a/packages/contracts-bedrock/.eslintignore b/contracts-bedrock/.eslintignore similarity index 100% rename from packages/contracts-bedrock/.eslintignore rename to contracts-bedrock/.eslintignore diff --git a/packages/contracts-bedrock/.eslintrc.js b/contracts-bedrock/.eslintrc.js similarity index 100% rename from packages/contracts-bedrock/.eslintrc.js rename to contracts-bedrock/.eslintrc.js diff --git a/packages/contracts-bedrock/.gas-snapshot b/contracts-bedrock/.gas-snapshot similarity index 100% rename from packages/contracts-bedrock/.gas-snapshot rename to contracts-bedrock/.gas-snapshot diff --git a/packages/contracts-bedrock/.gitignore b/contracts-bedrock/.gitignore similarity index 100% rename from packages/contracts-bedrock/.gitignore rename to contracts-bedrock/.gitignore diff --git a/packages/contracts-bedrock/.npmignore b/contracts-bedrock/.npmignore similarity index 100% rename from packages/contracts-bedrock/.npmignore rename to contracts-bedrock/.npmignore diff --git a/packages/contracts-bedrock/.prettierignore b/contracts-bedrock/.prettierignore similarity index 100% rename from packages/contracts-bedrock/.prettierignore rename to contracts-bedrock/.prettierignore diff --git a/packages/contracts-bedrock/.prettierrc.js b/contracts-bedrock/.prettierrc.js similarity index 100% rename from packages/contracts-bedrock/.prettierrc.js rename to contracts-bedrock/.prettierrc.js diff --git a/packages/contracts-bedrock/.solhint.json b/contracts-bedrock/.solhint.json similarity index 100% rename from packages/contracts-bedrock/.solhint.json rename to contracts-bedrock/.solhint.json diff --git a/packages/contracts-bedrock/.solhintignore b/contracts-bedrock/.solhintignore similarity index 100% rename from packages/contracts-bedrock/.solhintignore rename to contracts-bedrock/.solhintignore diff --git a/packages/contracts-bedrock/LICENSE b/contracts-bedrock/LICENSE similarity index 100% rename from packages/contracts-bedrock/LICENSE rename to contracts-bedrock/LICENSE diff --git a/packages/contracts-bedrock/README.md b/contracts-bedrock/README.md similarity index 100% rename from packages/contracts-bedrock/README.md rename to contracts-bedrock/README.md diff --git a/packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol b/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol rename to contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol diff --git a/packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol b/contracts-bedrock/contracts/L1/L1StandardBridge.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol rename to contracts-bedrock/contracts/L1/L1StandardBridge.sol diff --git a/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol b/contracts-bedrock/contracts/L1/L2OutputOracle.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol rename to contracts-bedrock/contracts/L1/L2OutputOracle.sol diff --git a/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol b/contracts-bedrock/contracts/L1/OptimismPortal.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L1/OptimismPortal.sol rename to contracts-bedrock/contracts/L1/OptimismPortal.sol diff --git a/packages/contracts-bedrock/contracts/L2/Burner.sol b/contracts-bedrock/contracts/L2/Burner.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L2/Burner.sol rename to contracts-bedrock/contracts/L2/Burner.sol diff --git a/packages/contracts-bedrock/contracts/L2/L1Block.sol b/contracts-bedrock/contracts/L2/L1Block.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L2/L1Block.sol rename to contracts-bedrock/contracts/L2/L1Block.sol diff --git a/packages/contracts-bedrock/contracts/L2/L1BlockNumber.sol b/contracts-bedrock/contracts/L2/L1BlockNumber.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L2/L1BlockNumber.sol rename to contracts-bedrock/contracts/L2/L1BlockNumber.sol diff --git a/packages/contracts-bedrock/contracts/L2/L2CrossDomainMessenger.sol b/contracts-bedrock/contracts/L2/L2CrossDomainMessenger.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L2/L2CrossDomainMessenger.sol rename to contracts-bedrock/contracts/L2/L2CrossDomainMessenger.sol diff --git a/packages/contracts-bedrock/contracts/L2/L2StandardBridge.sol b/contracts-bedrock/contracts/L2/L2StandardBridge.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L2/L2StandardBridge.sol rename to contracts-bedrock/contracts/L2/L2StandardBridge.sol diff --git a/packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol b/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol similarity index 100% rename from packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol rename to contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol diff --git a/packages/contracts-bedrock/contracts/libraries/ExcessivelySafeCall.sol b/contracts-bedrock/contracts/libraries/ExcessivelySafeCall.sol similarity index 100% rename from packages/contracts-bedrock/contracts/libraries/ExcessivelySafeCall.sol rename to contracts-bedrock/contracts/libraries/ExcessivelySafeCall.sol diff --git a/packages/contracts-bedrock/contracts/libraries/Lib_BedrockPredeployAddresses.sol b/contracts-bedrock/contracts/libraries/Lib_BedrockPredeployAddresses.sol similarity index 100% rename from packages/contracts-bedrock/contracts/libraries/Lib_BedrockPredeployAddresses.sol rename to contracts-bedrock/contracts/libraries/Lib_BedrockPredeployAddresses.sol diff --git a/packages/contracts-bedrock/contracts/libraries/Lib_CrossDomainHashing.sol b/contracts-bedrock/contracts/libraries/Lib_CrossDomainHashing.sol similarity index 100% rename from packages/contracts-bedrock/contracts/libraries/Lib_CrossDomainHashing.sol rename to contracts-bedrock/contracts/libraries/Lib_CrossDomainHashing.sol diff --git a/packages/contracts-bedrock/contracts/libraries/Lib_WithdrawalVerifier.sol b/contracts-bedrock/contracts/libraries/Lib_WithdrawalVerifier.sol similarity index 100% rename from packages/contracts-bedrock/contracts/libraries/Lib_WithdrawalVerifier.sol rename to contracts-bedrock/contracts/libraries/Lib_WithdrawalVerifier.sol diff --git a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol b/contracts-bedrock/contracts/test/CommonTest.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/CommonTest.t.sol rename to contracts-bedrock/contracts/test/CommonTest.t.sol diff --git a/packages/contracts-bedrock/contracts/test/CrossDomainHashing.t.sol b/contracts-bedrock/contracts/test/CrossDomainHashing.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/CrossDomainHashing.t.sol rename to contracts-bedrock/contracts/test/CrossDomainHashing.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L1Block.t.sol b/contracts-bedrock/contracts/test/L1Block.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L1Block.t.sol rename to contracts-bedrock/contracts/test/L1Block.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L1BlockNumber.t.sol b/contracts-bedrock/contracts/test/L1BlockNumber.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L1BlockNumber.t.sol rename to contracts-bedrock/contracts/test/L1BlockNumber.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol b/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol rename to contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol b/contracts-bedrock/contracts/test/L1StandardBridge.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol rename to contracts-bedrock/contracts/test/L1StandardBridge.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol b/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol rename to contracts-bedrock/contracts/test/L2CrossDomainMessenger.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol b/contracts-bedrock/contracts/test/L2OutputOracle.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol rename to contracts-bedrock/contracts/test/L2OutputOracle.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol b/contracts-bedrock/contracts/test/L2StandardBridge.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L2StandardBridge.t.sol rename to contracts-bedrock/contracts/test/L2StandardBridge.t.sol diff --git a/packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol b/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol rename to contracts-bedrock/contracts/test/L2ToL1MessagePasser.t.sol diff --git a/packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol b/contracts-bedrock/contracts/test/Lib_RLP.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol rename to contracts-bedrock/contracts/test/Lib_RLP.t.sol diff --git a/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol b/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol rename to contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol diff --git a/packages/contracts-bedrock/contracts/test/OptimismMintableTokenFactory.t.sol b/contracts-bedrock/contracts/test/OptimismMintableTokenFactory.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/OptimismMintableTokenFactory.t.sol rename to contracts-bedrock/contracts/test/OptimismMintableTokenFactory.t.sol diff --git a/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol b/contracts-bedrock/contracts/test/OptimismPortal.t.sol similarity index 100% rename from packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol rename to contracts-bedrock/contracts/test/OptimismPortal.t.sol diff --git a/packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol b/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol similarity index 100% rename from packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol rename to contracts-bedrock/contracts/universal/CrossDomainMessenger.sol diff --git a/packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol b/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol similarity index 100% rename from packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol rename to contracts-bedrock/contracts/universal/OptimismMintableERC20.sol diff --git a/packages/contracts-bedrock/contracts/universal/OptimismMintableTokenFactory.sol b/contracts-bedrock/contracts/universal/OptimismMintableTokenFactory.sol similarity index 100% rename from packages/contracts-bedrock/contracts/universal/OptimismMintableTokenFactory.sol rename to contracts-bedrock/contracts/universal/OptimismMintableTokenFactory.sol diff --git a/packages/contracts-bedrock/contracts/universal/StandardBridge.sol b/contracts-bedrock/contracts/universal/StandardBridge.sol similarity index 100% rename from packages/contracts-bedrock/contracts/universal/StandardBridge.sol rename to contracts-bedrock/contracts/universal/StandardBridge.sol diff --git a/packages/contracts-bedrock/deploy/000-L2OutputOracle.deploy.ts b/contracts-bedrock/deploy/000-L2OutputOracle.deploy.ts similarity index 100% rename from packages/contracts-bedrock/deploy/000-L2OutputOracle.deploy.ts rename to contracts-bedrock/deploy/000-L2OutputOracle.deploy.ts diff --git a/packages/contracts-bedrock/deploy/001-OptimismPortal.deploy.ts b/contracts-bedrock/deploy/001-OptimismPortal.deploy.ts similarity index 100% rename from packages/contracts-bedrock/deploy/001-OptimismPortal.deploy.ts rename to contracts-bedrock/deploy/001-OptimismPortal.deploy.ts diff --git a/packages/contracts-bedrock/deploy/002-L1CrossDomainMessenger.ts b/contracts-bedrock/deploy/002-L1CrossDomainMessenger.ts similarity index 100% rename from packages/contracts-bedrock/deploy/002-L1CrossDomainMessenger.ts rename to contracts-bedrock/deploy/002-L1CrossDomainMessenger.ts diff --git a/packages/contracts-bedrock/deploy/003-L1StandardBridge.ts b/contracts-bedrock/deploy/003-L1StandardBridge.ts similarity index 100% rename from packages/contracts-bedrock/deploy/003-L1StandardBridge.ts rename to contracts-bedrock/deploy/003-L1StandardBridge.ts diff --git a/packages/contracts-bedrock/deploy/004-OptimismMintableTokenFactory.ts b/contracts-bedrock/deploy/004-OptimismMintableTokenFactory.ts similarity index 100% rename from packages/contracts-bedrock/deploy/004-OptimismMintableTokenFactory.ts rename to contracts-bedrock/deploy/004-OptimismMintableTokenFactory.ts diff --git a/packages/contracts-bedrock/foundry.toml b/contracts-bedrock/foundry.toml similarity index 100% rename from packages/contracts-bedrock/foundry.toml rename to contracts-bedrock/foundry.toml diff --git a/packages/contracts-bedrock/hardhat.config.ts b/contracts-bedrock/hardhat.config.ts similarity index 100% rename from packages/contracts-bedrock/hardhat.config.ts rename to contracts-bedrock/hardhat.config.ts diff --git a/packages/contracts-bedrock/helpers/constants.ts b/contracts-bedrock/helpers/constants.ts similarity index 100% rename from packages/contracts-bedrock/helpers/constants.ts rename to contracts-bedrock/helpers/constants.ts diff --git a/packages/contracts-bedrock/helpers/generateProofs.ts b/contracts-bedrock/helpers/generateProofs.ts similarity index 100% rename from packages/contracts-bedrock/helpers/generateProofs.ts rename to contracts-bedrock/helpers/generateProofs.ts diff --git a/packages/contracts-bedrock/helpers/index.ts b/contracts-bedrock/helpers/index.ts similarity index 100% rename from packages/contracts-bedrock/helpers/index.ts rename to contracts-bedrock/helpers/index.ts diff --git a/packages/contracts-bedrock/helpers/trie-test-generator.ts b/contracts-bedrock/helpers/trie-test-generator.ts similarity index 100% rename from packages/contracts-bedrock/helpers/trie-test-generator.ts rename to contracts-bedrock/helpers/trie-test-generator.ts diff --git a/packages/contracts-bedrock/helpers/utils.ts b/contracts-bedrock/helpers/utils.ts similarity index 100% rename from packages/contracts-bedrock/helpers/utils.ts rename to contracts-bedrock/helpers/utils.ts diff --git a/packages/contracts-bedrock/lib/ds-test b/contracts-bedrock/lib/ds-test similarity index 100% rename from packages/contracts-bedrock/lib/ds-test rename to contracts-bedrock/lib/ds-test diff --git a/packages/contracts-bedrock/lib/forge-std b/contracts-bedrock/lib/forge-std similarity index 100% rename from packages/contracts-bedrock/lib/forge-std rename to contracts-bedrock/lib/forge-std diff --git a/packages/contracts-bedrock/lib/solmate b/contracts-bedrock/lib/solmate similarity index 100% rename from packages/contracts-bedrock/lib/solmate rename to contracts-bedrock/lib/solmate diff --git a/packages/contracts-bedrock/package.json b/contracts-bedrock/package.json similarity index 100% rename from packages/contracts-bedrock/package.json rename to contracts-bedrock/package.json diff --git a/packages/contracts-bedrock/scripts/ffiMakeProof.ts b/contracts-bedrock/scripts/ffiMakeProof.ts similarity index 100% rename from packages/contracts-bedrock/scripts/ffiMakeProof.ts rename to contracts-bedrock/scripts/ffiMakeProof.ts diff --git a/packages/contracts-bedrock/scripts/makeProof.ts b/contracts-bedrock/scripts/makeProof.ts similarity index 100% rename from packages/contracts-bedrock/scripts/makeProof.ts rename to contracts-bedrock/scripts/makeProof.ts diff --git a/packages/contracts-bedrock/slither.config.json b/contracts-bedrock/slither.config.json similarity index 100% rename from packages/contracts-bedrock/slither.config.json rename to contracts-bedrock/slither.config.json diff --git a/packages/contracts-bedrock/slither.db.json b/contracts-bedrock/slither.db.json similarity index 100% rename from packages/contracts-bedrock/slither.db.json rename to contracts-bedrock/slither.db.json diff --git a/packages/contracts-bedrock/tasks/deposits.ts b/contracts-bedrock/tasks/deposits.ts similarity index 100% rename from packages/contracts-bedrock/tasks/deposits.ts rename to contracts-bedrock/tasks/deposits.ts diff --git a/packages/contracts-bedrock/test/helpers.spec.ts b/contracts-bedrock/test/helpers.spec.ts similarity index 100% rename from packages/contracts-bedrock/test/helpers.spec.ts rename to contracts-bedrock/test/helpers.spec.ts diff --git a/packages/contracts-bedrock/tsconfig.json b/contracts-bedrock/tsconfig.json similarity index 100% rename from packages/contracts-bedrock/tsconfig.json rename to contracts-bedrock/tsconfig.json diff --git a/packages/contracts-bedrock/yarn.lock b/contracts-bedrock/yarn.lock similarity index 100% rename from packages/contracts-bedrock/yarn.lock rename to contracts-bedrock/yarn.lock diff --git a/package.json b/package.json index c75762385ccd..ba90924fadf6 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,11 @@ "lint-staged": "11.0.0", "patch-package": "^6.4.7", "prettier": "^2.3.1", - "typescript": "^4.6.2" + "typescript": "^4.6.2", + "doctoc": "2.1.0", + "lint-staged": "11.0.0", + "markdownlint": "^0.24.0", + "markdownlint-cli2": "^0.3.2" }, "scripts": { "clean": "yarn lerna run clean --parallel", diff --git a/packages/integration-tests-bedrock/package.json b/packages/integration-tests-bedrock/package.json index 14656c6e1dd1..fd8fe93328d8 100644 --- a/packages/integration-tests-bedrock/package.json +++ b/packages/integration-tests-bedrock/package.json @@ -1,6 +1,6 @@ { "private": true, - "name": "@eth-optimism/integration-tests", + "name": "@eth-optimism/integration-tests-bedrock", "version": "0.5.9", "description": "[Optimism] Integration tests", "scripts": { @@ -11,8 +11,7 @@ "test": "ts-mocha --timeout 30000 test/**/*.spec.ts", "test:actor": "IS_LIVE_NETWORK=true ts-node actor-tests/lib/runner.ts", "test:integration:live": "NO_NETWORK=true IS_LIVE_NETWORK=true hardhat --network optimism test", - "clean": "rimraf cache artifacts", - "pre-commit": "lint-staged" + "clean": "rimraf cache artifacts" }, "keywords": [ "optimism", diff --git a/yarn.lock b/yarn.lock index ab007fdf120a..3bf157962aea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -434,6 +434,11 @@ ts-node "^8.0.2" url-join "^4.0.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" @@ -446,6 +451,22 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + +"@dabh/diagnostics@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== + dependencies: + colorspace "1.1.x" + enabled "2.0.x" + kuler "^2.0.0" + "@defi-wonderland/smock@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@defi-wonderland/smock/-/smock-2.0.2.tgz#0be863a61420fb162190c9be8798befada179f30" @@ -497,6 +518,54 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@eth-optimism/contracts@0.5.20": + version "0.5.20" + resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.5.20.tgz#3cc9d97dbc924d629bb4446237b8a54b32676533" + integrity sha512-HliboXKsiCFJdtiOlqJH2ZS+u9lkvXqCufpSnNCOrvxD4J3O8VkGUZib2Zelaz6srIX+23z9zM5JvqLYX/bubA== + dependencies: + "@eth-optimism/core-utils" "0.8.3" + "@ethersproject/abstract-provider" "^5.5.1" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/hardware-wallets" "^5.5.0" + +"@eth-optimism/core-utils@0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.7.3.tgz#67a7ec3cd65a555c6b5ef50d03ea66aa8df9f6c8" + integrity sha512-e531gfcMN6LWvGgJGfB37cU8HNUXfCkT6OO84KT8qKHMT4mOxyUqnApTYOHBxXGetLd3z/n67KwBCkJLZBr9jw== + dependencies: + "@ethersproject/abstract-provider" "^5.4.1" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/providers" "^5.4.5" + "@ethersproject/web" "^5.5.0" + chai "^4.3.4" + ethers "^5.4.5" + lodash "^4.17.21" + +"@eth-optimism/core-utils@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.8.3.tgz#226d6ac4cb80bd165d64f5ffa4f3e0b300568678" + integrity sha512-jM3dPAg9TinskLyH4w9KofEqgLWJsf5VrlC8a2/0zKNlZUJuVzE/ZYfcq243qqlJn1vb4QkBKjYVHKMu1Wjzjg== + dependencies: + "@ethersproject/abstract-provider" "^5.5.1" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/providers" "^5.5.3" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.1" + bufio "^1.0.7" + chai "^4.3.4" + ethers "^5.5.4" + +"@eth-optimism/sdk@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@eth-optimism/sdk/-/sdk-1.0.4.tgz#47b91ae99a5ad28b126dc2b04320fa6cbf796b12" + integrity sha512-bvnn4vHPADiq7I7JjXIGQq/OqTAf3k2u9PCQwc3xYZnfHeklanl/lL62JZtSI55rEugbXX/sRCIAp0TPdFTUTA== + dependencies: + "@eth-optimism/contracts" "0.5.20" + "@eth-optimism/core-utils" "0.8.3" + lodash "^4.17.21" + merkletreejs "^0.2.27" + rlp "^2.2.7" + "@ethereum-waffle/chai@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.0.tgz#2477877410a96bf370edd64df905b04fb9aba9d5" @@ -505,6 +574,14 @@ "@ethereum-waffle/provider" "^3.4.0" ethers "^5.0.0" +"@ethereum-waffle/chai@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" + integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== + dependencies: + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.5.2" + "@ethereum-waffle/compiler@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.0.tgz#68917321212563544913de33e408327745cb1284" @@ -522,6 +599,23 @@ ts-generator "^0.1.1" typechain "^3.0.0" +"@ethereum-waffle/compiler@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" + integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + "@ethereum-waffle/ens@^3.3.0": version "3.3.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.3.0.tgz#d54f4c8e6b7bcafdc13ab294433f45416b2b2791" @@ -531,6 +625,15 @@ "@ensdomains/resolver" "^0.2.4" ethers "^5.0.1" +"@ethereum-waffle/ens@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" + integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + "@ethereum-waffle/mock-contract@^3.3.0": version "3.3.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.3.0.tgz#7b331f1c95c5d46ee9478f7a6be2869f707d307a" @@ -539,6 +642,14 @@ "@ethersproject/abi" "^5.0.1" ethers "^5.0.1" +"@ethereum-waffle/mock-contract@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" + integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + "@ethereum-waffle/provider@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.0.tgz#a36a0890d4fbc230e807870c8d3b683594efef00" @@ -550,6 +661,17 @@ patch-package "^6.2.2" postinstall-postinstall "^2.1.0" +"@ethereum-waffle/provider@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" + integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== + dependencies: + "@ethereum-waffle/ens" "^3.4.4" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + "@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.0", "@ethereumjs/block@^3.6.1": version "3.6.1" resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.1.tgz#50574d3e993ae247dcfe2abbdb91d2a4a22accb9" @@ -560,6 +682,16 @@ ethereumjs-util "^7.1.4" merkle-patricia-tree "^4.2.3" +"@ethereumjs/block@^3.6.2": + version "3.6.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.2.tgz#63d1e26d0b7a7a3684fce920de6ebabec1e5b674" + integrity sha512-mOqYWwMlAZpYUEOEqt7EfMFuVL2eyLqWWIzcf4odn6QgXY8jBI2NhVuJncrMCKeMZrsJAe7/auaRRB6YcdH+Qw== + dependencies: + "@ethereumjs/common" "^2.6.3" + "@ethereumjs/tx" "^3.5.1" + ethereumjs-util "^7.1.4" + merkle-patricia-tree "^4.2.4" + "@ethereumjs/blockchain@^5.5.0", "@ethereumjs/blockchain@^5.5.1": version "5.5.1" resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.1.tgz#60f1f50592c06cc47e1704800b88b7d32f609742" @@ -574,6 +706,20 @@ lru-cache "^5.1.1" semaphore-async-await "^1.5.1" +"@ethereumjs/blockchain@^5.5.2": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.2.tgz#1848abd9dc1ee56acf8cec4c84304d7f4667d027" + integrity sha512-Jz26iJmmsQtngerW6r5BDFaew/f2mObLrRZo3rskLOx1lmtMZ8+TX/vJexmivrnWgmAsTdNWhlKUYY4thPhPig== + dependencies: + "@ethereumjs/block" "^3.6.2" + "@ethereumjs/common" "^2.6.3" + "@ethereumjs/ethash" "^1.1.0" + debug "^4.3.3" + ethereumjs-util "^7.1.4" + level-mem "^5.0.1" + lru-cache "^5.1.1" + semaphore-async-await "^1.5.1" + "@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.4.0.tgz#2d67f6e6ba22246c5c89104e6b9a119fb3039766" @@ -590,6 +736,14 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.4" +"@ethereumjs/common@^2.6.3", "@ethereumjs/common@^2.6.4": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.4.tgz#1b3cdd3aa4ee3b0ca366756fc35e4a03022a01cc" + integrity sha512-RDJh/R/EAr+B7ZRg5LfJ0BIpf/1LydFgYdvZEuTraojCbVypO2sQ+QnpP5u2wJf9DASyooKqu8O4FJEWUV6NXw== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.4" + "@ethereumjs/ethash@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.1.0.tgz#7c5918ffcaa9cb9c1dc7d12f77ef038c11fb83fb" @@ -617,6 +771,14 @@ "@ethereumjs/common" "^2.6.1" ethereumjs-util "^7.1.4" +"@ethereumjs/tx@^3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.1.tgz#8d941b83a602b4a89949c879615f7ea9a90e6671" + integrity sha512-xzDrTiu4sqZXUcaBxJ4n4W5FrppwxLxZB4ZDGVLtxSQR4lVuOnFR6RcUHdg1mpUhAPVrmnzLJpxaeXnPxIyhWA== + dependencies: + "@ethereumjs/common" "^2.6.3" + ethereumjs-util "^7.1.4" + "@ethereumjs/vm@^5.6.0": version "5.7.1" resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.7.1.tgz#3bf757fbad0081838ccb4f22003cd73319ab3616" @@ -635,6 +797,24 @@ merkle-patricia-tree "^4.2.3" rustbn.js "~0.2.0" +"@ethereumjs/vm@^5.9.0": + version "5.9.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.0.tgz#54e485097c6dbb42554d541ef8d84d06b7ddf12f" + integrity sha512-0IRsj4IuF8lFDWVVLc4mFOImaSX8VWF8CGm3mXHG/LLlQ/Tryy/kKXMw/bU9D+Zw03CdteW+wCGqNFS6+mPjpg== + dependencies: + "@ethereumjs/block" "^3.6.2" + "@ethereumjs/blockchain" "^5.5.2" + "@ethereumjs/common" "^2.6.4" + "@ethereumjs/tx" "^3.5.1" + async-eventemitter "^0.2.4" + core-js-pure "^3.0.1" + debug "^4.3.3" + ethereumjs-util "^7.1.4" + functional-red-black-tree "^1.0.1" + mcl-wasm "^0.7.1" + merkle-patricia-tree "^4.2.4" + rustbn.js "~0.2.0" + "@ethersproject/abi@5.0.0-beta.153": version "5.0.0-beta.153" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" @@ -695,6 +875,21 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/abi@5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.2.tgz#f2956f2ac724cd720e581759d9e3840cd9744818" + integrity sha512-40Ixjhy+YzFtnvzIqFU13FW9hd1gMoLa3cJfSDnfnL4o8EnEG1qLiV8sNJo3sHYi9UYMfFeRuZ7kv5+vhzU7gQ== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/abi@^5.0.12": version "5.4.1" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.4.1.tgz#6ac28fafc9ef6f5a7a37e30356a2eb31fa05d39b" @@ -751,7 +946,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/web" "^5.5.0" -"@ethersproject/abstract-provider@^5.6.0": +"@ethersproject/abstract-provider@5.6.0", "@ethersproject/abstract-provider@^5.4.1", "@ethersproject/abstract-provider@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz#0c4ac7054650dbd9c476cf5907f588bbb6ef3061" integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== @@ -786,6 +981,17 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/properties" "^5.5.0" +"@ethersproject/abstract-signer@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.1.tgz#54df786bdf1aabe20d0ed508ec05e0aa2d06674f" + integrity sha512-xhSLo6y0nGJS7NxfvOSzCaWKvWb1TLT7dQ0nnpHZrDnC67xfnWm9NXflTMFPUXXMtjr33CdV0kWDEmnbrQZ74Q== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/abstract-signer@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz#9cd7ae9211c2b123a3b29bf47aab17d4d016e3e7" @@ -819,7 +1025,7 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/rlp" "^5.5.0" -"@ethersproject/address@^5.6.0": +"@ethersproject/address@5.6.0", "@ethersproject/address@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== @@ -844,7 +1050,7 @@ dependencies: "@ethersproject/bytes" "^5.5.0" -"@ethersproject/base64@^5.6.0": +"@ethersproject/base64@5.6.0", "@ethersproject/base64@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.0.tgz#a12c4da2a6fb86d88563216b0282308fc15907c9" integrity sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw== @@ -867,7 +1073,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/properties" "^5.5.0" -"@ethersproject/basex@^5.6.0": +"@ethersproject/basex@5.6.0", "@ethersproject/basex@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.0.tgz#9ea7209bf0a1c3ddc2a90f180c3a7f0d7d2e8a69" integrity sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ== @@ -893,6 +1099,15 @@ "@ethersproject/logger" "^5.5.0" bn.js "^4.11.9" +"@ethersproject/bignumber@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.1.tgz#d5e0da518eb82ab8d08ca9db501888bbf5f0c8fb" + integrity sha512-UtMeZ3GaUuF9sx2u9nPZiPP3ULcAFmXyvynR7oHl/tPrM+vldZh7ocMsoa1PqKYGnQnqUZJoqxZnGN6J0qdipA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + bn.js "^4.11.9" + "@ethersproject/bignumber@^5.4.1": version "5.4.2" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.2.tgz#44232e015ae4ce82ac034de549eb3583c71283d8" @@ -925,6 +1140,13 @@ dependencies: "@ethersproject/logger" "^5.5.0" +"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" + integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/bytes@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.0.tgz#81652f2a0e04533575befadce555213c11d8aa20" @@ -946,7 +1168,7 @@ dependencies: "@ethersproject/bignumber" "^5.5.0" -"@ethersproject/constants@^5.6.0": +"@ethersproject/constants@5.6.0", "@ethersproject/constants@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.0.tgz#55e3eb0918584d3acc0688e9958b0cedef297088" integrity sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA== @@ -985,6 +1207,22 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/transactions" "^5.5.0" +"@ethersproject/contracts@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.1.tgz#c0eba3f8a2226456f92251a547344fd0593281d2" + integrity sha512-0fpBBDoPqJMsutE6sNjg6pvCJaIcl7tliMQTMRcoUWDACfjO68CpKOJBlsEhEhmzdnu/41KbrfAeg+sB3y35MQ== + dependencies: + "@ethersproject/abi" "^5.6.0" + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/hardware-wallets@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/hardware-wallets/-/hardware-wallets-5.5.0.tgz#b4a3bc99a843c3b78b133cdf94485a567ba17b8d" @@ -1025,7 +1263,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/hash@^5.6.0": +"@ethersproject/hash@5.6.0", "@ethersproject/hash@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.0.tgz#d24446a5263e02492f9808baa99b6e2b4c3429a2" integrity sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA== @@ -1075,6 +1313,24 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" +"@ethersproject/hdnode@5.6.1", "@ethersproject/hdnode@^5.6.0": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.1.tgz#37fa1eb91f6e20ca39cc5fcb7acd3da263d85dab" + integrity sha512-6IuYDmbH5Bv/WH/A2cUd0FjNr4qTLAvyHAECiFZhNZp69pPvU7qIDwJ7CU7VAkwm4IVBzqdYy9mpMAGhQdwCDA== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + "@ethersproject/json-wallets@5.4.0", "@ethersproject/json-wallets@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.4.0.tgz#2583341cfe313fc9856642e8ace3080154145e95" @@ -1113,6 +1369,25 @@ aes-js "3.0.0" scrypt-js "3.0.1" +"@ethersproject/json-wallets@5.6.0", "@ethersproject/json-wallets@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz#4c2fc27f17e36c583e7a252fb938bc46f98891e5" + integrity sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + "@ethersproject/keccak256@5.4.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" @@ -1129,7 +1404,7 @@ "@ethersproject/bytes" "^5.5.0" js-sha3 "0.8.0" -"@ethersproject/keccak256@^5.6.0": +"@ethersproject/keccak256@5.6.0", "@ethersproject/keccak256@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.0.tgz#fea4bb47dbf8f131c2e1774a1cecbfeb9d606459" integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== @@ -1147,7 +1422,7 @@ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== -"@ethersproject/logger@^5.6.0": +"@ethersproject/logger@5.6.0", "@ethersproject/logger@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== @@ -1166,6 +1441,13 @@ dependencies: "@ethersproject/logger" "^5.5.0" +"@ethersproject/networks@5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.2.tgz#2bacda62102c0b1fcee408315f2bed4f6fbdf336" + integrity sha512-9uEzaJY7j5wpYGTojGp8U89mSsgQLc40PCMJLMCnFXTs7nhBveZ0t7dbqWUNrepWTszDbFkYD6WlL8DKx5huHA== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.0.tgz#486d03fff29b4b6b5414d47a232ded09fe10de5e" @@ -1189,6 +1471,14 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/sha2" "^5.5.0" +"@ethersproject/pbkdf2@5.6.0", "@ethersproject/pbkdf2@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz#04fcc2d7c6bff88393f5b4237d906a192426685a" + integrity sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/properties@5.4.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.0.tgz#38ba20539b44dcc5d5f80c45ad902017dcdbefe7" @@ -1203,7 +1493,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/properties@^5.6.0": +"@ethersproject/properties@5.6.0", "@ethersproject/properties@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== @@ -1260,6 +1550,31 @@ bech32 "1.1.4" ws "7.4.6" +"@ethersproject/providers@5.6.6", "@ethersproject/providers@^5.4.5": + version "5.6.6" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.6.tgz#1967149cb4557d253f8c176a44aabda155f228cd" + integrity sha512-6X6agj3NeQ4tgnvBMCjHK+CjQbz+Qmn20JTxCYZ/uymrgCEOpJtY9zeRxJIDsSi0DPw8xNAxypj95JMCsapUfA== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + bech32 "1.1.4" + ws "7.4.6" + "@ethersproject/providers@^5.4.4": version "5.4.5" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.4.5.tgz#eb2ea2a743a8115f79604a8157233a3a2c832928" @@ -1326,6 +1641,14 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" +"@ethersproject/random@5.6.0", "@ethersproject/random@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.0.tgz#1505d1ab6a250e0ee92f436850fa3314b2cb5ae6" + integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/random@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.0.tgz#305ed9e033ca537735365ac12eed88580b0f81f9" @@ -1334,14 +1657,6 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/random@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.0.tgz#1505d1ab6a250e0ee92f436850fa3314b2cb5ae6" - integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== - dependencies: - "@ethersproject/bytes" "^5.6.0" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/rlp@5.4.0", "@ethersproject/rlp@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" @@ -1358,7 +1673,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/rlp@^5.6.0": +"@ethersproject/rlp@5.6.0", "@ethersproject/rlp@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.0.tgz#55a7be01c6f5e64d6e6e7edb6061aa120962a717" integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== @@ -1384,7 +1699,7 @@ "@ethersproject/logger" "^5.5.0" hash.js "1.1.7" -"@ethersproject/sha2@^5.6.0": +"@ethersproject/sha2@5.6.0", "@ethersproject/sha2@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.0.tgz#364c4c11cc753bda36f31f001628706ebadb64d9" integrity sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA== @@ -1417,6 +1732,18 @@ elliptic "6.5.4" hash.js "1.1.7" +"@ethersproject/signing-key@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.1.tgz#31b0a531520616254eb0465b9443e49515c4d457" + integrity sha512-XvqQ20DH0D+bS3qlrrgh+axRMth5kD1xuvqUQUTeezxUTXBOeR6hWz2/C6FBEu39FRytyybIWrYf7YLSAKr1LQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + "@ethersproject/signing-key@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.0.tgz#4f02e3fb09e22b71e2e1d6dc4bcb5dafa69ce042" @@ -1452,6 +1779,18 @@ "@ethersproject/sha2" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/solidity@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.0.tgz#64657362a596bf7f5630bdc921c07dd78df06dc3" + integrity sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/strings@5.4.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" @@ -1470,7 +1809,7 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/strings@^5.6.0": +"@ethersproject/strings@5.6.0", "@ethersproject/strings@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.0.tgz#9891b26709153d996bf1303d39a7f4bc047878fd" integrity sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg== @@ -1509,7 +1848,7 @@ "@ethersproject/rlp" "^5.5.0" "@ethersproject/signing-key" "^5.5.0" -"@ethersproject/transactions@^5.6.0": +"@ethersproject/transactions@5.6.0", "@ethersproject/transactions@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.0.tgz#4b594d73a868ef6e1529a2f8f94a785e6791ae4e" integrity sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg== @@ -1542,6 +1881,15 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" +"@ethersproject/units@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.0.tgz#e5cbb1906988f5740254a21b9ded6bd51e826d9c" + integrity sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/wallet@5.4.0", "@ethersproject/wallet@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.4.0.tgz#fa5b59830b42e9be56eadd45a16a2e0933ad9353" @@ -1584,6 +1932,27 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" +"@ethersproject/wallet@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.1.tgz#5df4f75f848ed84ca30fd6ca75d2c66b19c5552b" + integrity sha512-oXWoOslEWtwZiViIMlGVjeKDQz/tI7JF9UkyzN9jaGj8z7sXt2SyFMb0Ev6vSAqjIzrCrNrJ/+MkAhtKnGOfZw== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/json-wallets" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + "@ethersproject/web@5.4.0", "@ethersproject/web@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" @@ -1606,7 +1975,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/web@^5.6.0": +"@ethersproject/web@5.6.0", "@ethersproject/web@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.0.tgz#4bf8b3cbc17055027e1a5dd3c357e37474eaaeb8" integrity sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg== @@ -1639,6 +2008,17 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" +"@ethersproject/wordlists@5.6.0", "@ethersproject/wordlists@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.0.tgz#79e62c5276e091d8575f6930ba01a29218ded032" + integrity sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@hapi/bourne@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.0.0.tgz#5bb2193eb685c0007540ca61d166d4e1edaf918d" @@ -2515,11 +2895,29 @@ safe-buffer "^5.1.1" util.promisify "^1.0.0" +"@nomiclabs/hardhat-ethers@^2.0.0": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.6.tgz#1c695263d5b46a375dcda48c248c4fba9dfe2fc2" + integrity sha512-q2Cjp20IB48rEn2NPjR1qxsIQBvFVYW9rFRCFq+bC4RUrn1Ljz3g4wM8uSlgIBZYBi2JMXxmOzFqHraczxq4Ng== + "@nomiclabs/hardhat-ethers@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.2.tgz#c472abcba0c5185aaa4ad4070146e95213c68511" integrity sha512-6quxWe8wwS4X5v3Au8q1jOvXYEPkS1Fh+cME5u6AwNdnI4uERvPlVjlgRWzpnb+Rrt1l/cEqiNRH9GlsBMSDQg== +"@nomiclabs/hardhat-etherscan@^2.1.3": + version "2.1.8" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.8.tgz#e206275e96962cd15e5ba9148b44388bc922d8c2" + integrity sha512-0+rj0SsZotVOcTLyDOxnOc3Gulo8upo0rsw/h+gBPcmtj91YqYJNhdARHoBxOhhE8z+5IUQPx+Dii04lXT14PA== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^5.0.2" + debug "^4.1.1" + fs-extra "^7.0.1" + node-fetch "^2.6.0" + semver "^6.3.0" + "@nomiclabs/hardhat-etherscan@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.3.tgz#ca54a03351f3de41f9f5240e37bea9d64fa24e64" @@ -2533,6 +2931,14 @@ semver "^6.3.0" undici "^4.14.1" +"@nomiclabs/hardhat-waffle@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" + integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + "@nomiclabs/hardhat-waffle@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.1.tgz#5d43654fba780720c5033dea240fe14f70ef4bd2" @@ -2714,6 +3120,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.4.0.tgz#85161d87c840c5bce2b6ed0c727b407e774852ae" integrity sha512-hIEyWJHu7bDTv6ckxOaV+K3+7mVzhjtyvp3QSaz56Rk5PscXtPAbkiNTb3yz6UJCWHPWpxVyULVgZ6RubuFEZg== +"@openzeppelin/contracts-upgradeable@^4.5.2": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.6.0.tgz#1bf55f230f008554d4c6fe25eb165b85112108b0" + integrity sha512-5OnVuO4HlkjSCJO165a4i2Pu1zQGzMs//o54LPrwUgxvEO2P3ax1QuaSI0cEHHTveA77guS0PnNugpR2JMsPfA== + "@openzeppelin/contracts@3.4.1-solc-0.7-2": version "3.4.1-solc-0.7-2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92" @@ -2734,6 +3145,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.4.0.tgz#4a1df71f736c31230bbbd634dfb006a756b51e6b" integrity sha512-dlKiZmDvJnGRLHojrDoFZJmsQVeltVeoiRN7RK+cf2FmkhASDEblE0RiaYdxPNsUZa6mRG8393b9bfyp+V5IAw== +"@openzeppelin/contracts@^4.5.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.6.0.tgz#c91cf64bc27f573836dba4122758b4743418c1b3" + integrity sha512-8vi4d50NNya/bQqCmaVzvHNmwHvS0OBKb7HNtuNwEE3scXWrP31fKQoGxNMT+KbzmrNZzatE3QK5p2gFONI/hg== + "@primitivefi/hardhat-dodoc@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@primitivefi/hardhat-dodoc/-/hardhat-dodoc-0.1.3.tgz#338ecff24b93d3b43fa35a98909f6840af86c27c" @@ -2945,7 +3361,7 @@ dependencies: antlr4ts "^0.5.0-alpha.4" -"@solidity-parser/parser@^0.14.1": +"@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1": version "0.14.1" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.1.tgz#179afb29f4e295a77cc141151f26b3848abc3c46" integrity sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw== @@ -2959,6 +3375,24 @@ dependencies: defer-to-connect "^1.0.1" +"@textlint/ast-node-types@^4.2.5": + version "4.4.3" + resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-4.4.3.tgz#fdba16e8126cddc50f45433ce7f6c55e7829566c" + integrity sha512-qi2jjgO6Tn3KNPGnm6B7p6QTEPvY95NFsIAaJuwbulur8iJUEenp1OnoUfiDaC/g2WPPEFkcfXpmnu8XEMFo2A== + +"@textlint/markdown-to-ast@~6.1.7": + version "6.1.7" + resolved "https://registry.yarnpkg.com/@textlint/markdown-to-ast/-/markdown-to-ast-6.1.7.tgz#7ed9561b577bcd5307c8ef82660bc568ce31647e" + integrity sha512-B0QtokeQR4a9+4q0NQr8T9l7A1fFihTN5Ze57tVgqW+3ymzXEouh8DvPHeNQ4T6jEkAThvdjk95mxAMpGRJ79w== + dependencies: + "@textlint/ast-node-types" "^4.2.5" + debug "^4.1.1" + remark-frontmatter "^1.2.0" + remark-parse "^5.0.0" + structured-source "^3.0.2" + traverse "^0.6.6" + unified "^6.1.6" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -3007,6 +3441,14 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== +"@typechain/ethers-v5@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.0.0.tgz#1b6e292d2ed9afb0d2f7a4674cc199bb95bad714" + integrity sha512-Kot7fwAqnH96ZbI8xrRgj5Kpv9yCEdjo7mxRqrH7bYpEgijT5MmuOo8IVsdhOu7Uog4ONg7k/d5UdbAtTKUgsA== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + "@typechain/ethers-v5@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" @@ -3014,21 +3456,29 @@ dependencies: ethers "^5.0.2" -"@typechain/ethers-v5@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-8.0.2.tgz#0f2cc0db1513cb02e3e78929139216b153c9d2c0" - integrity sha512-oRMA3X5UWrsUiNb/lFTusa8xBpw6CckOHAk7sZBHeDQh4tAp+ZU24wdwdURcOtPnagzdCv5Dvl1qlD038brf1A== +"@typechain/ethers-v5@^7.0.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz#d559cffe0efe6bdbc20e644b817f6fa8add5e8f8" + integrity sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw== dependencies: lodash "^4.17.15" ts-essentials "^7.0.1" -"@typechain/hardhat@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-3.0.0.tgz#a94396855506d42b98d6e7c09f87ca14180d6c64" - integrity sha512-FpnIIXkDXm54XCHI/Z2iOet7h1MrFSvZfuljX9Uzc6FEjEfb01Tuzu8ywe2iquD3g5JXqovgdv+M54L/2Z6jkg== +"@typechain/hardhat@^2.3.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-2.3.1.tgz#1e8a6e3795e115a5d5348526282b5c597fab0b78" + integrity sha512-BQV8OKQi0KAzLXCdsPO0pZBNQQ6ra8A2ucC26uFX/kquRBtJu1yEyWnVSmtr07b5hyRoJRpzUeINLnyqz4/MAw== dependencies: fs-extra "^9.1.0" +"@typechain/hardhat@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.0.0.tgz#5e305641de67276efbfaa8c37c78e38f22b22ef4" + integrity sha512-AnhwODKHxx3+st5uc1j2NQh79Lv2OuvDQe4dKn8ZxhqYsAsTPnHTLBeI8KPZ+mfdE7v13D2QYssRTIkkGhK35A== + dependencies: + fs-extra "^9.1.0" + lodash "^4.17.15" + "@types/abstract-leveldown@*": version "5.0.2" resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.2.tgz#ee81917fe38f770e29eec8139b6f16ee4a8b0a5f" @@ -3068,6 +3518,11 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.21.tgz#9f35a5643129df132cf3b5c1ec64046ea1af0650" integrity sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg== +"@types/chai@^4.2.21": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04" + integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ== + "@types/concat-stream@^1.6.0": version "1.6.1" resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" @@ -3087,6 +3542,11 @@ resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== +"@types/dateformat@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-5.0.0.tgz#17ce64b0318f3f36d1c830c58a7a915445f1f93d" + integrity sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA== + "@types/express-serve-static-core@^4.17.18": version "4.17.24" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07" @@ -3184,6 +3644,11 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323" integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== +"@types/mocha@^9.0.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + "@types/node-fetch@^2.5.5": version "2.5.10" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132" @@ -3202,6 +3667,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== +"@types/node@^12.0.0": + version "12.20.52" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.52.tgz#2fd2dc6bfa185601b15457398d4ba1ef27f81251" + integrity sha512-cfkwWw72849SNYp3Zx0IcIs25vABmFh73xicxhCkTcvtZQeIez15PpwQN8fY3RD7gv1Wrxlc9MEtfMORZDEsGw== + "@types/node@^12.12.6", "@types/node@^12.7.1": version "12.20.20" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.20.tgz#ce3d6c13c15c5e622a85efcd3a1cb2d9c7fa43a6" @@ -3217,6 +3687,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== +"@types/node@^17.0.23": + version "17.0.33" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.33.tgz#3c1879b276dc63e73030bb91165e62a4509cd506" + integrity sha512-miWq2m2FiQZmaHfdZNcbpp9PuXg34W5JZ5CrJ/BaS70VuhoJENBEQybeiYSaPBRNq6KQGnjfEnc/F3PN++D+XQ== + "@types/node@^8.0.0": version "8.10.66" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" @@ -3366,6 +3841,20 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/eslint-plugin@^4.29.1": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== + dependencies: + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/experimental-utils@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz#52e437a689ccdef73e83c5106b34240a706f15e1" @@ -3378,6 +3867,18 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + "@typescript-eslint/parser@^4.26.0": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.29.3.tgz#2ac25535f34c0e98f50c0e6b28c679c2357d45f2" @@ -3388,6 +3889,16 @@ "@typescript-eslint/typescript-estree" "4.29.3" debug "^4.3.1" +"@typescript-eslint/parser@^4.29.1": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== + dependencies: + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + debug "^4.3.1" + "@typescript-eslint/scope-manager@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz#497dec66f3a22e459f6e306cf14021e40ec86e19" @@ -3396,11 +3907,24 @@ "@typescript-eslint/types" "4.29.3" "@typescript-eslint/visitor-keys" "4.29.3" +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + "@typescript-eslint/types@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.29.3.tgz#d7980c49aef643d0af8954c9f14f656b7fd16017" integrity sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg== +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + "@typescript-eslint/typescript-estree@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz#1bafad610015c4ded35c85a70b6222faad598b40" @@ -3414,6 +3938,19 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/visitor-keys@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz#c691760a00bd86bf8320d2a90a93d86d322f1abf" @@ -3422,6 +3959,14 @@ "@typescript-eslint/types" "4.29.3" eslint-visitor-keys "^2.0.0" +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + "@ungap/promise-all-settled@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" @@ -3675,6 +4220,13 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +anchor-markdown-header@~0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz#045063d76e6a1f9cd327a57a0126aa0fdec371a7" + integrity sha1-BFBj125qH5zTJ6V6ASaqD97Dcac= + dependencies: + emoji-regex "~6.1.0" + ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" @@ -3857,6 +4409,16 @@ array-back@^2.0.0: dependencies: typical "^2.6.1" +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -4012,6 +4574,11 @@ async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: dependencies: lodash "^4.17.14" +async@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" + integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -4592,6 +5159,11 @@ backoff@^2.5.0: dependencies: precond "0.2" +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -4770,6 +5342,11 @@ body-parser@1.19.0, body-parser@^1.16.0: raw-body "2.4.0" type-is "~1.6.17" +boundary@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/boundary/-/boundary-1.0.1.tgz#4d67dc2602c0cc16dd9bce7ebf87e948290f5812" + integrity sha1-TWfcJgLAzBbdm85+v4fpSCkPWBI= + boxen@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -4814,7 +5391,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -5187,6 +5764,19 @@ chai-as-promised@^7.1.1: dependencies: check-error "^1.0.2" +chai@^4.2.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + chai@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" @@ -5235,6 +5825,21 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -5526,6 +6131,11 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" + integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -5534,7 +6144,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -5553,11 +6163,27 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.6.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.1.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + colorette@^1.2.2, colorette@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" @@ -5573,6 +6199,14 @@ colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +colorspace@1.1.x: + version "1.1.4" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" + integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== + dependencies: + color "^3.1.3" + text-hex "1.0.x" + columnify@^1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" @@ -5602,6 +6236,26 @@ command-line-args@^4.0.7: find-replace "^1.0.3" typical "^2.6.1" +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + commander@2.18.0: version "2.18.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" @@ -6167,7 +6821,7 @@ deep-equal@~1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@^0.6.0: +deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== @@ -6360,6 +7014,18 @@ directory-tree@^2.2.7: resolved "https://registry.yarnpkg.com/directory-tree/-/directory-tree-2.3.1.tgz#78b8aa84878eb84dd29a51dcd664ded4cd0247c7" integrity sha512-hxolIHCtQ/a56CUywaLzGD/V78zPwFihI+UK/4ZjOp7GoV4Mptmtv95yavOn/RlnTi7cCMjszvfcNrwCoWLH+Q== +doctoc@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctoc/-/doctoc-2.1.0.tgz#e7cbcd1f9e65519c295461423b2e7195d9e0d7ab" + integrity sha512-0darEVEuWKLyIlpGOzE5cILf/pgUu25qUs6YwCqLqfxb8+3b9Cl4iakA8vwYrBQOkJ5SwpHKEPVMu2KOMrTA7A== + dependencies: + "@textlint/markdown-to-ast" "~6.1.7" + anchor-markdown-header "~0.5.7" + htmlparser2 "~4.1.0" + minimist "~1.2.5" + underscore "~1.12.1" + update-section "~0.3.3" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -6374,11 +7040,48 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" + integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== + dependencies: + domelementtype "^2.0.1" + +domhandler@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.0.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -6470,6 +7173,11 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +emoji-regex@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66" + integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -6485,6 +7193,16 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +emoji-regex@~6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.3.tgz#ec79a3969b02d2ecf2b72254279bf99bc7a83932" + integrity sha1-7HmjlpsC0uzytyJUJ5v5m8eoOTI= + +enabled@2.0.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== + encode-utf8@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" @@ -6537,6 +7255,16 @@ enquirer@^2.3.0, enquirer@^2.3.5, enquirer@^2.3.6: dependencies: ansi-colors "^4.1.1" +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + env-paths@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -6680,6 +7408,11 @@ eslint-config-prettier@^8.3.0: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== +eslint-config-standard@^16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" + integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== + eslint-import-resolver-node@^0.3.6: version "0.3.6" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" @@ -6696,6 +7429,14 @@ eslint-module-utils@^2.6.2: debug "^3.2.7" pkg-dir "^2.0.0" +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + eslint-plugin-import@^2.23.4: version "2.24.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz#64aba8b567a1ba9921d5465586e86c491b8e2135" @@ -6732,6 +7473,18 @@ eslint-plugin-jsdoc@^35.1.2: semver "^7.3.5" spdx-expression-parse "^3.0.1" +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + eslint-plugin-prefer-arrow@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz#e7fbb3fa4cd84ff1015b9c51ad86550e55041041" @@ -6744,6 +7497,11 @@ eslint-plugin-prettier@^3.4.0: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-promise@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz#a596acc32981627eb36d9d75f9666ac1a4564971" + integrity sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw== + eslint-plugin-react@^7.24.0: version "7.24.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz#eadedfa351a6f36b490aa17f4fa9b14e842b9eb4" @@ -6815,7 +7573,7 @@ eslint-utils@^1.3.1: dependencies: eslint-visitor-keys "^1.1.0" -eslint-utils@^2.1.0: +eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== @@ -6881,7 +7639,7 @@ eslint@^5.6.0: table "^5.2.3" text-table "^0.2.0" -eslint@^7.27.0: +eslint@^7.27.0, eslint@^7.29.0: version "7.32.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== @@ -7178,6 +7936,17 @@ ethereum-cryptography@^0.1.2, ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" +ethereum-waffle@^3.0.0: + version "3.4.4" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" + integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== + dependencies: + "@ethereum-waffle/chai" "^3.4.4" + "@ethereum-waffle/compiler" "^3.4.4" + "@ethereum-waffle/mock-contract" "^3.4.4" + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.0.1" + ethereum-waffle@^3.3.0, ethereum-waffle@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.0.tgz#990b3c6c26db9c2dd943bf26750a496f60c04720" @@ -7471,6 +8240,42 @@ ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2: "@ethersproject/web" "5.4.0" "@ethersproject/wordlists" "5.4.0" +ethers@^5.4.5, ethers@^5.5.2, ethers@^5.6.2, ethers@^5.6.6: + version "5.6.6" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.6.tgz#a37aa7e265a484a1b4d2ef91d4d89d6b43808a57" + integrity sha512-2B2ZmSGvRcJpHnFMBk58mkXP50njFipUBCgLK8jUTFbomhVs501cLzyMU6+Vx8YnUDQxywC3qkZvd33xWS+2FA== + dependencies: + "@ethersproject/abi" "5.6.2" + "@ethersproject/abstract-provider" "5.6.0" + "@ethersproject/abstract-signer" "5.6.1" + "@ethersproject/address" "5.6.0" + "@ethersproject/base64" "5.6.0" + "@ethersproject/basex" "5.6.0" + "@ethersproject/bignumber" "5.6.1" + "@ethersproject/bytes" "5.6.1" + "@ethersproject/constants" "5.6.0" + "@ethersproject/contracts" "5.6.1" + "@ethersproject/hash" "5.6.0" + "@ethersproject/hdnode" "5.6.1" + "@ethersproject/json-wallets" "5.6.0" + "@ethersproject/keccak256" "5.6.0" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.2" + "@ethersproject/pbkdf2" "5.6.0" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.6" + "@ethersproject/random" "5.6.0" + "@ethersproject/rlp" "5.6.0" + "@ethersproject/sha2" "5.6.0" + "@ethersproject/signing-key" "5.6.1" + "@ethersproject/solidity" "5.6.0" + "@ethersproject/strings" "5.6.0" + "@ethersproject/transactions" "5.6.0" + "@ethersproject/units" "5.6.0" + "@ethersproject/wallet" "5.6.1" + "@ethersproject/web" "5.6.0" + "@ethersproject/wordlists" "5.6.0" + ethers@^5.5.0, ethers@^5.5.4: version "5.5.4" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.4.tgz#e1155b73376a2f5da448e4a33351b57a885f4352" @@ -7681,7 +8486,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@~3.0.2: +extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -7784,6 +8589,18 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fault@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + +fecha@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== + fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" @@ -7876,6 +8693,13 @@ find-replace@^1.0.3: array-back "^1.0.4" test-value "^2.1.0" +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + find-up@3.0.0, find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -7993,6 +8817,11 @@ fmix@^0.1.0: dependencies: imul "^1.0.0" +fn.name@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + follow-redirects@^1.12.1, follow-redirects@^1.14.0: version "1.14.8" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" @@ -8064,6 +8893,11 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= + formidable@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" @@ -8455,6 +9289,18 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +glob@7.1.7, glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@7.2.0, glob@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -8478,18 +9324,6 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - global-modules@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" @@ -8545,7 +9379,7 @@ globby@^10.0.1: merge2 "^1.2.3" slash "^3.0.0" -globby@^11.0.0, globby@^11.0.2, globby@^11.0.3: +globby@^11.0.0, globby@^11.0.2, globby@^11.0.3, globby@~11.0.4: version "11.0.4" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== @@ -8639,6 +9473,34 @@ hard-rejection@^2.1.0: resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== +hardhat-deploy@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.4.tgz#39b06d3b0ad25195071cc1f2f71649b1f9f030d0" + integrity sha512-BNMwWqaxrwb8XKrYzmCwnUzOSKzicUBk+fwd28doUNoAGFFh8kpoypkcHMzKDVdLhnamAardcfqJet73zrZoTA== + dependencies: + "@ethersproject/abi" "^5.4.0" + "@ethersproject/abstract-signer" "^5.4.1" + "@ethersproject/address" "^5.4.0" + "@ethersproject/bignumber" "^5.4.1" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/contracts" "^5.4.1" + "@ethersproject/providers" "^5.4.4" + "@ethersproject/solidity" "^5.4.0" + "@ethersproject/transactions" "^5.4.0" + "@ethersproject/wallet" "^5.4.0" + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + hardhat-deploy@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.9.3.tgz#cf9a7806c0a86a6f7e9352fc558b26c079983496" @@ -8688,6 +9550,60 @@ hardhat-watcher@^2.1.1: dependencies: chokidar "^3.4.3" +hardhat@^2.7.1: + version "2.9.5" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.9.5.tgz#6814a9f3afd5630ffe6bcb05a4367eb259c9222a" + integrity sha512-UIhjLQmccFOH87ODfFnVatI5vpwycsJ+D5+gmgOQNxUWp4c0ZenkeCE4yDEQ0tQm/zc/vz/mpskULz4aSFsPAg== + dependencies: + "@ethereumjs/block" "^3.6.2" + "@ethereumjs/blockchain" "^5.5.2" + "@ethereumjs/common" "^2.6.4" + "@ethereumjs/tx" "^3.5.1" + "@ethereumjs/vm" "^5.9.0" + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@sentry/node" "^5.18.1" + "@solidity-parser/parser" "^0.14.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^0.1.2" + ethereumjs-abi "^0.6.8" + ethereumjs-util "^7.1.4" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "^7.1.3" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + lodash "^4.17.11" + merkle-patricia-tree "^4.2.4" + mnemonist "^0.38.0" + mocha "^9.2.0" + p-map "^4.0.0" + qs "^6.7.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + slash "^3.0.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + "true-case-path" "^2.2.1" + tsort "0.0.1" + undici "^4.14.1" + uuid "^8.3.2" + ws "^7.4.6" + hardhat@^2.9.2: version "2.9.2" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.9.2.tgz#123f3fed6810ef8637b127b73ca44bb9c9efc249" @@ -8923,6 +9839,16 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +htmlparser2@~4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" + integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + domutils "^2.0.0" + entities "^2.0.0" + http-basic@^8.1.1: version "8.1.3" resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" @@ -9063,6 +9989,11 @@ ignore@^5.1.1, ignore@^5.1.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.8: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + immediate@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" @@ -9135,7 +10066,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -9264,6 +10195,19 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -9277,6 +10221,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -9299,7 +10248,7 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: +is-buffer@^1.1.4, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -9335,6 +10284,13 @@ is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.6.0: dependencies: has "^1.0.3" +is-core-module@^2.8.1: + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -9356,6 +10312,11 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -9452,6 +10413,11 @@ is-hex-prefixed@1.0.0: resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" @@ -9612,11 +10578,21 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" + integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== + is-windows@^1.0.0, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== + is-wsl@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -10056,6 +11032,11 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +kuler@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -10366,6 +11347,13 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + lint-staged@11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-11.0.0.tgz#24d0a95aa316ba28e257f5c4613369a75a10c712" @@ -10481,6 +11469,11 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -10578,6 +11571,17 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +logform@^2.3.2, logform@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" + integrity sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw== + dependencies: + "@colors/colors" "1.5.0" + fecha "^4.2.0" + ms "^2.1.1" + safe-stable-stringify "^2.3.1" + triple-beam "^1.3.0" + looper@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" @@ -10595,6 +11599,13 @@ loose-envify@^1.0.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -10746,11 +11757,57 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" + integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== + +markdown-it@12.2.0: + version "12.2.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.2.0.tgz#091f720fd5db206f80de7a8d1f1a7035fd0d38db" + integrity sha512-Wjws+uCrVQRqOoJvze4HCqkKl1AsSh95iFAeQDwnyfxM09divCBSXlDR1uTvyUP3Grzpn4Ru8GeCxYPM8vkCQg== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + markdown-table@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== +markdownlint-cli2-formatter-default@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.2.tgz#76f1a064d70966178dfe3bb489af9423d830ca79" + integrity sha512-jIz1X3SIC8sX4NDFqQFUXL+JEtfnDoN4i+xocEu+etcxGX455pHb6sx86f/yVk4mKJ2o7aNe2ydSx9an22BfBg== + +markdownlint-cli2@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/markdownlint-cli2/-/markdownlint-cli2-0.3.2.tgz#328774b5ab981997fdd6fa8f72ea7feaed84722b" + integrity sha512-Wj4iQy2J49m9CVkWkLTdFxMTPDqD3AyL3NbLQgz/nUnTu8LnDguFCbQtFhdzQPvncHVjrKT2vYqg7DifzVP4tA== + dependencies: + globby "~11.0.4" + markdownlint "~0.24.0" + markdownlint-cli2-formatter-default "^0.0.2" + markdownlint-rule-helpers "~0.15.0" + micromatch "~4.0.4" + strip-json-comments "~3.1.1" + yaml "~1.10.2" + +markdownlint-rule-helpers@~0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.15.0.tgz#11434c573649b9235ae70b967314f5711f7d8fa8" + integrity sha512-A+9mswc3m/kkqpJCqntmte/1VKhDJ+tjZsERLz5L4h/Qr7ht2/BkGkgY5E7/wsxIhcpl+ctIfz+oS3PQrMOB2w== + +markdownlint@^0.24.0, markdownlint@~0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.24.0.tgz#224b53f671367a237d40c8be1745c7be9a322671" + integrity sha512-OJIGsGFV/rC9irI5E1FMy6v9hdACSwaa+EN3224Y5KG8zj2EYzdHOw0pOJovIYmjNfEZ9BtxUY4P7uYHTSNnbQ== + dependencies: + markdown-it "12.2.0" + marked-terminal@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-3.3.0.tgz#25ce0c0299285998c7636beaefc87055341ba1bd" @@ -10794,6 +11851,11 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -10967,6 +12029,18 @@ merkle-patricia-tree@^4.2.2, merkle-patricia-tree@^4.2.3: readable-stream "^3.6.0" semaphore-async-await "^1.5.1" +merkle-patricia-tree@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.4.tgz#ff988d045e2bf3dfa2239f7fabe2d59618d57413" + integrity sha512-eHbf/BG6eGNsqqfbLED9rIqbsF4+sykEaBn6OLNs71tjclbMcMOk1tEPmJKcNcNCLkvbpY/lwyOlizWsqPNo8w== + dependencies: + "@types/levelup" "^4.3.0" + ethereumjs-util "^7.1.4" + level-mem "^5.0.1" + level-ws "^2.0.0" + readable-stream "^3.6.0" + semaphore-async-await "^1.5.1" + merkletreejs@^0.2.18: version "0.2.24" resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.2.24.tgz#6dc52b3e0946846c25816216f1b60094a18a5e7a" @@ -11021,6 +12095,14 @@ micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" +micromatch@~4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -11566,7 +12648,7 @@ node-fetch@2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -12034,6 +13116,13 @@ once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +one-time@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== + dependencies: + fn.name "1.x.x" + onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -12331,6 +13420,18 @@ parse-cache-control@^1.0.1: resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" integrity sha1-juqz5U+laSD+Fro493+iGqzC104= +parse-entities@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" + integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-headers@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" @@ -12470,7 +13571,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -12527,6 +13628,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -12738,6 +13844,18 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" +prettier-plugin-solidity@^1.0.0-beta.13: + version "1.0.0-beta.19" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz#7c3607fc4028f5e6a425259ff03e45eedf733df3" + integrity sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g== + dependencies: + "@solidity-parser/parser" "^0.14.0" + emoji-regex "^10.0.0" + escape-string-regexp "^4.0.0" + semver "^7.3.5" + solidity-comments-extractor "^0.0.7" + string-width "^4.2.3" + prettier-plugin-solidity@^1.0.0-beta.18: version "1.0.0-beta.18" resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.18.tgz#9705453bacd55b3242110d472f23f624ae6777fc" @@ -12760,6 +13878,11 @@ prettier@^2.1.2, prettier@^2.3.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== +prettier@^2.3.2, prettier@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + printj@~1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" @@ -13320,6 +14443,11 @@ redeyed@~2.1.0: dependencies: esprima "~4.0.0" +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + regenerate@^1.2.1: version "1.4.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" @@ -13370,7 +14498,7 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpp@^3.1.0: +regexpp@^3.0.0, regexpp@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -13408,12 +14536,41 @@ release-zalgo@^1.0.0: dependencies: es6-error "^4.0.1" +remark-frontmatter@^1.2.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-1.3.3.tgz#67ec63c89da5a84bb793ecec166e11b4eb47af10" + integrity sha512-fM5eZPBvu2pVNoq3ZPW22q+5Ativ1oLozq2qYt9I2oNyxiUd/tDl0iLLntEVAegpZIslPWg1brhcP1VsaSVUag== + dependencies: + fault "^1.0.1" + xtend "^4.0.1" + +remark-parse@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" + integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA== + dependencies: + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^1.1.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^1.0.0" + vfile-location "^2.0.0" + xtend "^4.0.1" + repeat-element@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.6.1: +repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -13425,6 +14582,11 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" +replace-ext@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + req-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" @@ -13568,6 +14730,15 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.20.0, resolve@^1.8. is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^1.10.1: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.3: version "2.0.0-next.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" @@ -13731,6 +14902,11 @@ safe-regex@^2.1.1: dependencies: regexp-tree "~0.1.1" +safe-stable-stringify@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73" + integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -13821,7 +14997,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -14029,6 +15205,13 @@ simple-get@^3.0.3: once "^1.3.1" simple-concat "^1.0.0" +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -14222,6 +15405,30 @@ solidity-comments-extractor@^0.0.7: resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== +solidity-coverage@^0.7.16: + version "0.7.21" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.21.tgz#20c5615a3a543086b243c2ca36e2951a75316b40" + integrity sha512-O8nuzJ9yXiKUx3NdzVvHrUW0DxoNVcGzq/I7NzewNO9EZE3wYAQ4l8BwcnV64r4aC/HB6Vnw/q2sF0BQHv/3fg== + dependencies: + "@solidity-parser/parser" "^0.14.0" + "@truffle/provider" "^0.2.24" + chalk "^2.4.2" + death "^1.1.0" + detect-port "^1.3.0" + fs-extra "^8.1.0" + ghost-testrpc "^0.0.2" + global-modules "^2.0.0" + globby "^10.0.1" + jsonschema "^1.2.4" + lodash "^4.17.15" + node-emoji "^1.10.0" + pify "^4.0.1" + recursive-readdir "^2.2.2" + sc-istanbul "^0.4.5" + semver "^7.3.4" + shelljs "^0.8.3" + web3-utils "^1.3.0" + solidity-coverage@^0.7.17: version "0.7.17" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.17.tgz#5139de8f6666d4755d88f453d8e35632a7bb3444" @@ -14436,6 +15643,11 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + stacktrace-parser@^0.1.10: version "0.1.10" resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" @@ -14443,6 +15655,11 @@ stacktrace-parser@^0.1.10: dependencies: type-fest "^0.7.1" +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" + integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -14496,6 +15713,11 @@ string-argv@0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -14531,7 +15753,7 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string-width@^4.2.2: +string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -14688,7 +15910,7 @@ strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -14702,6 +15924,13 @@ strong-log-transformer@^2.1.0: minimist "^1.2.0" through "^2.3.4" +structured-source@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/structured-source/-/structured-source-3.0.2.tgz#dd802425e0f53dc4a6e7aca3752901a1ccda7af5" + integrity sha1-3YAkJeD1PcSm56yjdSkBoczaevU= + dependencies: + boundary "^1.0.1" + superagent@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/superagent/-/superagent-6.1.0.tgz#09f08807bc41108ef164cfb4be293cebd480f4a6" @@ -14775,6 +16004,11 @@ supports-hyperlinks@^1.0.1: has-flag "^2.0.0" supports-color "^5.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + swarm-js@^0.1.40: version "0.1.40" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" @@ -14808,6 +16042,16 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -14959,6 +16203,11 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -15115,6 +16364,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= +traverse@^0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= + treeify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" @@ -15135,6 +16389,26 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +trim-trailing-lines@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" + integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +triple-beam@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" + integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + "true-case-path@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-2.2.1.tgz#c5bf04a5bbec3fd118be4084461b3a27c4d796bf" @@ -15145,6 +16419,16 @@ tryer@^1.0.1: resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== +ts-command-line-args@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.3.1.tgz#b6188e42efc6cf7a8898e438a873fbb15505ddd6" + integrity sha512-FR3y7pLl/fuUNSmnPhfLArGqRrpojQgIEEOVzYx9DhTmfIN7C9RWSfpkJEF4J+Gk7aVx5pak8I7vWZsaN4N84g== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + ts-essentials@^1.0.0, ts-essentials@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" @@ -15199,6 +16483,15 @@ ts-mocha@^8.0.0: optionalDependencies: tsconfig-paths "^3.5.0" +ts-mocha@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-9.0.2.tgz#c1ef0248874d04a0f26dd9bd8d88e617a8d82ab1" + integrity sha512-WyQjvnzwrrubl0JT7EC1yWmNpcsU3fOuBFfdps30zbmFBgKniSaSOyZMZx+Wq7kytUs5CY+pEbSYEbGfIKnXTw== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + ts-node@7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" @@ -15231,6 +16524,25 @@ ts-node@^10.0.0: make-error "^1.1.1" yn "3.1.1" +ts-node@^10.1.0, ts-node@^10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" + integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" + yn "3.1.1" + ts-node@^8.0.2: version "8.10.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" @@ -15402,10 +16714,10 @@ typechain@^3.0.0: ts-essentials "^6.0.3" ts-generator "^0.1.1" -typechain@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-6.0.2.tgz#0a1d6328aa934dfd66c8941cd94c1d3491cc34f0" - integrity sha512-fphYQ2+r5z38eq02qr4KjgU9/Xdda8Cj+eV2QHSRXhDPyhEVv+ln9123iGjjDLEhGyROb3DQkbvjm3Dl0GtUeQ== +typechain@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-5.2.0.tgz#10525a44773a34547eb2eed8978cb72c0a39a0f4" + integrity sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw== dependencies: "@types/prettier" "^2.1.1" command-line-args "^4.0.7" @@ -15418,6 +16730,22 @@ typechain@^6.0.2: prettier "^2.1.2" ts-essentials "^7.0.1" +typechain@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.0.0.tgz#a5dbe754717a7e16247df52b5285903de600e8ff" + integrity sha512-rqDfDYc9voVAhmfVfAwzg3VYFvhvs5ck1X9T/iWkX745Cul4t+V/smjnyqrbDzWDbzD93xfld1epg7Y/uFAesQ== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.3.1" + fs-extra "^7.0.0" + glob "7.1.7" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -15446,6 +16774,11 @@ typescript@^4.3.4, typescript@^4.3.5, typescript@^4.6.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== +typescript@^4.5.2, typescript@^4.6.3, typescript@^4.6.4: + version "4.6.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" + integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== + typewise-core@^1.2, typewise-core@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" @@ -15468,11 +16801,26 @@ typical@^2.6.0, typical@^2.6.1: resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + u2f-api@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" integrity sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg== +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + uglify-js@^3.1.4: version "3.14.1" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.1.tgz#e2cb9fe34db9cb4cf7e35d1d26dfea28e09a7d06" @@ -15508,11 +16856,36 @@ underscore@1.9.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== +underscore@~1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" + integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== + undici@^4.14.1: version "4.15.0" resolved "https://registry.yarnpkg.com/undici/-/undici-4.15.0.tgz#507ec94bce46bec5c76e934938c50b825eda8258" integrity sha512-kHppwh/y49FLEXl/zYCCbGB0D3nrcWNBczNYCsDdNYzWPs80aQgfKic1PVkJEIc2YlR7m0Lf5i559zbr0AA7FQ== +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" + integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== + dependencies: + inherits "^2.0.0" + xtend "^4.0.0" + +unified@^6.1.6: + version "6.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" + integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^1.1.0" + trough "^1.0.0" + vfile "^2.0.0" + x-is-string "^0.1.0" + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -15537,6 +16910,37 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" +unist-util-is@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" + integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== + +unist-util-remove-position@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz#ec037348b6102c897703eee6d0294ca4755a2020" + integrity sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A== + dependencies: + unist-util-visit "^1.1.0" + +unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" + integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== + +unist-util-visit-parents@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" + integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== + dependencies: + unist-util-is "^3.0.0" + +unist-util-visit@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" + integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== + dependencies: + unist-util-visit-parents "^2.0.0" + uniswap-v3-deploy-plugin@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/uniswap-v3-deploy-plugin/-/uniswap-v3-deploy-plugin-0.1.0.tgz#dd1798106373c16108aa2b5a0ec3b176c5c51d43" @@ -15589,6 +16993,11 @@ upath@^2.0.1: resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== +update-section@~0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/update-section/-/update-section-0.3.3.tgz#458f17820d37820dc60e20b86d94391b00123158" + integrity sha1-RY8Xgg03gg3GDiC4bZQ5GwASMVg= + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -15729,6 +17138,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" @@ -15768,6 +17182,28 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vfile-location@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" + integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== + +vfile-message@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1" + integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA== + dependencies: + unist-util-stringify-position "^1.1.1" + +vfile@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" + integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== + dependencies: + is-buffer "^1.1.4" + replace-ext "1.0.0" + unist-util-stringify-position "^1.0.0" + vfile-message "^1.0.0" + vscode-oniguruma@^1.6.1: version "1.6.2" resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607" @@ -16414,6 +17850,31 @@ window-size@^0.2.0: resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= +winston-transport@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" + integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== + dependencies: + logform "^2.3.2" + readable-stream "^3.6.0" + triple-beam "^1.3.0" + +winston@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.7.2.tgz#95b4eeddbec902b3db1424932ac634f887c400b1" + integrity sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng== + dependencies: + "@dabh/diagnostics" "^2.0.2" + async "^3.2.3" + is-stream "^2.0.0" + logform "^2.4.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.5.0" + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -16424,6 +17885,14 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + workerpool@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b" @@ -16559,6 +18028,11 @@ ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== +x-is-string@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" + integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= + xhr-request-promise@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" @@ -16648,7 +18122,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0: +yaml@^1.10.0, yaml@~1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== From 77c49398134629ab1a3c6e6517bfee0342e29605 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Sat, 14 May 2022 21:19:02 -0600 Subject: [PATCH 583/585] monorepo merge: bring back CI Known issues: - There are broken links that `lychee` picks up on. These still need to be updated. - Slither returns errors, both here and in `optimistic-specs`. - `go-bip39` was updated to a newer version. The newer version broke a `bss-core` test, which had to be fixed. - Forge is not compatible with Lerna. As a result, the `contracts-bedrock` package had to be moved out of the `packages` hierarchy. - The devnet itests don't work because the Go modules aren't on the default branch. We need to decide if we merge to develop, or stay on a feature branch before fixing this. --- .circleci/config.yml | 152 ++++++++++++ .gitignore | 7 + protocol/Makefile => Makefile | 10 +- batch-submitter/go.sum | 392 +++++++++++++++++++++++++++++ bss-core/crypto_test.go | 4 +- bss-core/go.mod | 1 - bss-core/go.sum | 1 - contracts-bedrock/package.json | 2 +- contracts-bedrock/yarn.lock | 8 +- gas-oracle/go.mod | 1 - gas-oracle/go.sum | 250 ++++++++++++++++++- go.work.sum | 7 +- indexer/go.sum | 411 +++++++++++++++++++++++++++++++ l2geth-exporter/go.mod | 1 - l2geth-exporter/go.sum | 1 - l2geth/go.sum | 260 +++++++++++++++++++ ops/docker/js-builder/Dockerfile | 5 + proxyd/go.mod | 1 - proxyd/go.sum | 1 - teleportr/go.mod | 2 +- teleportr/go.sum | 1 + 21 files changed, 1493 insertions(+), 25 deletions(-) rename protocol/Makefile => Makefile (83%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 64a5e016a9ef..f1bfa2699262 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,8 @@ version: 2.1 +orbs: + node: circleci/node@5.0.2 + executors: go-builder: docker: @@ -307,10 +310,159 @@ jobs: echo "$DOCKER_PASS" | docker login -u "$DOCKER_USERNAME" --password-stdin docker push <> + bedrock-markdown: + machine: + image: ubuntu-2004:202111-02 + steps: + - checkout + - run: + name: markdown lint + command: | + docker run -v `pwd`:/workdir davidanson/markdownlint-cli2:0.4.0 "op-node/README.md" "./specs/**/*.md" "#**/node_modules" + - run: + name: link lint + command: | + docker run --init -it -v `pwd`:/input lycheeverse/lychee --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude-mail /input/README.md "/input/specs/**/*.md" "/input/meta/**/*.md" "/input/op-node/**/*.md" || exit 0 + + bedrock-solidity: + docker: + - image: ethereumoptimism/js-builder:0.0.4 + steps: + - checkout + - run: + name: init submodules + command: | + git submodule sync --recursive + git submodule update --recursive --init + - run: + name: install + command: yarn install + working_directory: contracts-bedrock + - run: + name: lint + command: | + # remove prettierrc in root of repo since it doesn't work with non-Lerna packages + mv ../.eslintrc.js ../.eslintrc.bak + yarn lint:check + mv ../.eslintrc.bak ../.eslintrc.js + working_directory: contracts-bedrock + - run: + name: slither + command: yarn slither || exit 0 + working_directory: contracts-bedrock + - run: + name: build forge + command: yarn build:forge + working_directory: contracts-bedrock + - run: + name: test forge + command: yarn test:forge + working_directory: contracts-bedrock + - run: + name: gas snapshot + command: forge snapshot + working_directory: contracts-bedrock + + + bedrock-go-tests: + docker: + - image: ethereumoptimism/go-builder:latest + steps: + - checkout + - run: + name: lint op-node + command: | + golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell ./... + working_directory: op-node + - run: + name: lint op-proposer + command: | + golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell ./... + working_directory: op-proposer + - run: + name: lint op-batcher + command: | + golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell ./... + working_directory: op-batcher + - run: + name: lint op-e2e + command: | + golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell ./... + working_directory: op-e2e + - run: + name: prep results dir + command: mkdir -p /test-results + - run: + name: test op-node + command: | + gotestsum --junitfile /test-results/op-node.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + working_directory: op-node + - run: + name: test op-proposer + command: | + gotestsum --junitfile /test-results/op-proposer.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + working_directory: op-proposer + - run: + name: test op-batcher + command: | + gotestsum --junitfile /test-results/op-batcher.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + working_directory: op-batcher + - run: + name: test op-e2e + command: | + gotestsum --junitfile /test-results/op-e2e.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + working_directory: op-e2e + - store_test_results: + path: /test-results + + fuzz-op-node: + docker: + - image: ethereumoptimism/go-builder:latest + steps: + - checkout + - run: + name: Fuzz + command: make fuzz + working_directory: op-node + + bedrock-integration-tests: + machine: + image: ubuntu-2004:202111-02 + docker_layer_caching: true + steps: + - checkout + - run: + name: init submodules + command: | + git submodule sync --recursive + git submodule update --recursive --init + - node/install: + install-yarn: true + node-version: '16.13' + - run: + name: install Foundry + command: | + curl -L https://foundry.paradigm.xyz | bash + source /home/circleci/.bashrc + foundryup + - run: + name: build typescript + command: make build-ts + - run: + name: start devnet + command: make devnet-up + - run: + name: run itests + command: make test-integration + workflows: main: jobs: - yarn-monorepo + - bedrock-go-tests + - bedrock-solidity + - bedrock-markdown + - fuzz-op-node - go-lint-test-build: name: batch-submitter-tests binary_name: batch-submitter diff --git a/.gitignore b/.gitignore index 4fc1beef2c23..f8e96dbcf403 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,10 @@ packages/data-transport-layer/db .env* !.env.example *.log + +.devnet + +# Ignore local fuzzing results +**/testdata/fuzz/ + +coverage.out diff --git a/protocol/Makefile b/Makefile similarity index 83% rename from protocol/Makefile rename to Makefile index 8eef1d869235..161e43c887eb 100644 --- a/protocol/Makefile +++ b/Makefile @@ -31,11 +31,11 @@ op-proposer: .PHONY: op-proposer contracts: - cd ./packages/contracts && yarn install && yarn build + cd ./contracts-bedrock && yarn install && yarn build .PHONY: contracts integration-tests: - cd ./packages/integration-tests && yarn install && yarn build:contracts + cd ./packages/integration-tests-bedrock && yarn install && yarn build:contracts .PHONY: integration-tests clean: @@ -51,7 +51,7 @@ devnet-down: .PHONY: devnet-down devnet-clean: - rm -rf ./packages/contracts/deployments/devnetL1 + rm -rf ./contracts-bedrock/deployments/devnetL1 rm -rf ./.devnet cd ./ops-bedrock && docker-compose down docker volume rm ops_l1_data @@ -63,12 +63,12 @@ test-unit: make -C ./op-proposer test make -C ./op-batcher test make -C ./op-e2e test - cd ./packages/contracts && yarn test + cd ./contracts-bedrock && yarn test .PHONY: test-unit test-integration: bash ./ops-bedrock/test-integration.sh \ - ./packages/contracts/deployments/devnetL1 + ./contracts-bedrock/deployments/devnetL1 .PHONY: test-integration devnet-genesis: diff --git a/batch-submitter/go.sum b/batch-submitter/go.sum index 5a718fec1448..cefaf74b6a0e 100644 --- a/batch-submitter/go.sum +++ b/batch-submitter/go.sum @@ -8,42 +8,70 @@ cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTj 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/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +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/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= @@ -55,12 +83,22 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF 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/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/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/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.42.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 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= @@ -75,12 +113,15 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -92,26 +133,37 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= 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/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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= 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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= 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/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= @@ -152,20 +204,32 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +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/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -173,16 +237,22 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/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/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/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/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk= +github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= @@ -194,9 +264,11 @@ github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= 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= @@ -205,39 +277,61 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 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= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -251,43 +345,81 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 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= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -295,6 +427,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt 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/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 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= @@ -315,11 +448,15 @@ github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -332,12 +469,14 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 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/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= @@ -360,29 +499,41 @@ 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/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= 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/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 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.0/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-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -390,12 +541,20 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 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/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -407,12 +566,19 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW 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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -421,19 +587,34 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ 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 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 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/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= 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/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= 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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= @@ -441,70 +622,100 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/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-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/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.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= 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.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 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/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 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/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/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/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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 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/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -514,19 +725,26 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -541,22 +759,39 @@ github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+m github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +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= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -569,9 +804,12 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -582,6 +820,9 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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= @@ -593,20 +834,28 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -616,11 +865,24 @@ 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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -628,14 +890,20 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +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-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -643,15 +911,21 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ 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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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= @@ -665,35 +939,63 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20191220142924-d4481acd189f/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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/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= @@ -702,12 +1004,18 @@ 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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -729,13 +1037,36 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-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-20200103221440-774c71fcf114/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= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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-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.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= @@ -747,6 +1078,7 @@ 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.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 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= @@ -754,16 +1086,28 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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/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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 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= @@ -773,27 +1117,64 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx 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.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/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= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +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= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -801,11 +1182,14 @@ gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3M gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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= @@ -818,13 +1202,21 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= 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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/bss-core/crypto_test.go b/bss-core/crypto_test.go index aab5fddd2c80..42b465d885e8 100644 --- a/bss-core/crypto_test.go +++ b/bss-core/crypto_test.go @@ -6,6 +6,8 @@ import ( "strings" "testing" + "github.com/tyler-smith/go-bip39" + bsscore "github.com/ethereum-optimism/optimism/bss-core" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -100,7 +102,7 @@ func TestDerivePrivateKey(t *testing.T) { name: "invalid mnemonic", mnemonic: invalidMnemonic, hdPath: validHDPath, - expErr: errors.New("Checksum incorrect"), + expErr: bip39.ErrInvalidMnemonic, // the bip39 lib spells mnemonic wrong... }, { name: "valid mnemonic invalid hdpath", diff --git a/bss-core/go.mod b/bss-core/go.mod index f45a870fc0ee..45072a668990 100644 --- a/bss-core/go.mod +++ b/bss-core/go.mod @@ -16,7 +16,6 @@ require ( github.com/allegro/bigcache v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect diff --git a/bss-core/go.sum b/bss-core/go.sum index a125801f4954..e45276836ee3 100644 --- a/bss-core/go.sum +++ b/bss-core/go.sum @@ -77,7 +77,6 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2 github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= diff --git a/contracts-bedrock/package.json b/contracts-bedrock/package.json index 61463249eb30..3037c872ea54 100644 --- a/contracts-bedrock/package.json +++ b/contracts-bedrock/package.json @@ -54,7 +54,7 @@ "eslint-config-standard": "^16.0.3", "eslint-plugin-import": "^2.23.4", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-promise": "^5.1.0", "ethereum-waffle": "^3.0.0", "ethers": "^5.0.0", diff --git a/contracts-bedrock/yarn.lock b/contracts-bedrock/yarn.lock index ffa4115fe6e4..70f392051dd7 100644 --- a/contracts-bedrock/yarn.lock +++ b/contracts-bedrock/yarn.lock @@ -4069,10 +4069,10 @@ eslint-plugin-node@^11.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" - integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== +eslint-plugin-prettier@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" + integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== dependencies: prettier-linter-helpers "^1.0.0" diff --git a/gas-oracle/go.mod b/gas-oracle/go.mod index 370603d96bb5..b2ea3c57d28b 100644 --- a/gas-oracle/go.mod +++ b/gas-oracle/go.mod @@ -11,7 +11,6 @@ require ( github.com/VictoriaMetrics/fastcache v1.9.0 // indirect github.com/allegro/bigcache v1.2.1 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect diff --git a/gas-oracle/go.sum b/gas-oracle/go.sum index b30506f6e850..d9e5f5176770 100644 --- a/gas-oracle/go.sum +++ b/gas-oracle/go.sum @@ -34,18 +34,36 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt 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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= 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/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/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/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/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 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= @@ -57,34 +75,50 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxq 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/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= 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/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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= 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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= 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/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= @@ -94,6 +128,7 @@ 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 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= @@ -104,9 +139,15 @@ github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwu github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= @@ -114,12 +155,16 @@ github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5w 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/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/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/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 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/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/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= @@ -129,24 +174,35 @@ github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJ 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-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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= 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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 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.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -162,7 +218,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -176,35 +235,69 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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/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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 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= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -213,6 +306,7 @@ github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vA github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 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= @@ -226,10 +320,15 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd 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/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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= @@ -238,6 +337,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V 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.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= @@ -259,6 +359,9 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F 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/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= 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= @@ -267,32 +370,60 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 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-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -300,61 +431,105 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W 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 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 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/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= 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/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= 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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 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/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/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/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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 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 v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -369,38 +544,60 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45 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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190701094942-4def268fd1a4/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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -429,11 +626,16 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20181023162649-9b4f9f5ad519/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -443,6 +645,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR 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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -451,8 +654,10 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-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-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -468,26 +673,34 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20181122145206-62eef0e2fa9b/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-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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -498,14 +711,20 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -516,12 +735,18 @@ 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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -540,13 +765,17 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-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-20200103221440-774c71fcf114/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-20201224043029-2b0845dc783e/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= @@ -558,6 +787,7 @@ 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.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 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= @@ -566,6 +796,7 @@ google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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= @@ -575,6 +806,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn 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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 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= @@ -584,10 +816,15 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx 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/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 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= @@ -595,20 +832,27 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +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= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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= @@ -619,7 +863,9 @@ 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= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= @@ -628,3 +874,5 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/go.work.sum b/go.work.sum index 339aba62148f..470766be7045 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,9 +1,6 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce h1:Wa0BVNdeyzIoJkrZtI7o2NEw8F98vVIzkPpiFACbdCA= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/indexer/go.sum b/indexer/go.sum index a7380905026e..339b5ba034ba 100644 --- a/indexer/go.sum +++ b/indexer/go.sum @@ -8,54 +8,95 @@ cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTj 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/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +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/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= 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/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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/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/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.42.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 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= @@ -69,12 +110,16 @@ github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -86,6 +131,8 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -93,21 +140,30 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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/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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= 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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= 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/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= @@ -126,20 +182,32 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +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/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -147,13 +215,18 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/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/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/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/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk= @@ -169,48 +242,74 @@ github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 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= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -224,45 +323,83 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 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= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= 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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -270,6 +407,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt 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/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 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= @@ -290,19 +428,28 @@ github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= @@ -310,6 +457,7 @@ github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYb github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= @@ -321,6 +469,7 @@ github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo 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.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -336,28 +485,38 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL 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/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= +github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 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.0/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-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -365,12 +524,21 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 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/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -378,15 +546,23 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= 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/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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -395,20 +571,35 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ 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 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 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/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= 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/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= 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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= @@ -416,62 +607,101 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/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-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/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.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +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.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +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/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 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/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/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/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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 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/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -481,19 +711,26 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -509,22 +746,39 @@ github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+m github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +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= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -537,10 +791,12 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -551,6 +807,9 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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= @@ -562,20 +821,28 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -585,10 +852,24 @@ 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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -597,15 +878,19 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +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-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -613,19 +898,27 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ 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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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= @@ -633,21 +926,40 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20191220142924-d4481acd189f/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= @@ -656,15 +968,22 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +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= @@ -674,12 +993,17 @@ 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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -701,13 +1025,36 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-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-20200103221440-774c71fcf114/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= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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-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.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= @@ -719,6 +1066,7 @@ 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.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 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= @@ -726,16 +1074,28 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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/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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 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= @@ -745,25 +1105,64 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx 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.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/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= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +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= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -771,15 +1170,19 @@ gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3M gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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= @@ -787,13 +1190,21 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= 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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/l2geth-exporter/go.mod b/l2geth-exporter/go.mod index 56e462291e15..83c7b1597852 100644 --- a/l2geth-exporter/go.mod +++ b/l2geth-exporter/go.mod @@ -11,7 +11,6 @@ require ( github.com/VictoriaMetrics/fastcache v1.9.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect diff --git a/l2geth-exporter/go.sum b/l2geth-exporter/go.sum index 4c1e96a81c25..142ebfcc4f63 100644 --- a/l2geth-exporter/go.sum +++ b/l2geth-exporter/go.sum @@ -65,7 +65,6 @@ github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+Wji github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/l2geth/go.sum b/l2geth/go.sum index 2a31ff381532..7e45146b63fe 100644 --- a/l2geth/go.sum +++ b/l2geth/go.sum @@ -24,40 +24,63 @@ github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuI github.com/Azure/azure-storage-blob-go v0.7.0 h1:MuueVOYkufCxJw5YZzF842DY2MBsp+hLuh2apKY0mck= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 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/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= 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/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/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/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/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.42.6 h1:CiJmv8Fdc7wLZhfWy1ZA9TNoOQrFtUC0mhpgyJTaKOs= github.com/aws/aws-sdk-go v1.42.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 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= @@ -69,12 +92,16 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxq 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/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 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 v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -86,6 +113,8 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -93,15 +122,23 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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/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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA= github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= 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/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 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.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= @@ -111,36 +148,53 @@ 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 v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 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.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM= github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= 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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 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/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc= +github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 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/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/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 h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 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/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/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= @@ -150,25 +204,36 @@ github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJ 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-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/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= 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 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-resty/resty/v2 v2.4.0 h1:s6TItTLejEI+2mn98oijC5w/Rk2YU+OA6x0mnZN6r6k= github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 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-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -184,8 +249,11 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -199,33 +267,68 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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/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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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 h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 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/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -233,6 +336,7 @@ github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7m github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vAiBg8= 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/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 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= @@ -243,26 +347,35 @@ github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mq github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jarcoal/httpmock v1.0.8 h1:8kI16SoO6LQKgPE7PvQuV+YuD/inwHd7fOOe2zMbo4k= github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +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.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= @@ -285,31 +398,51 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F 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/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= 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.0/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-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/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-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -317,9 +450,20 @@ github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hz 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= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -327,69 +471,111 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W 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 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 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/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= 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/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= 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 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff h1:+6NUiITWwE5q1KO6SAfUX918c+Tab0+tGAM/mtdlUyA= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 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/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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 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 v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -399,13 +585,18 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 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= @@ -413,28 +604,43 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190701094942-4def268fd1a4/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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -467,8 +673,13 @@ golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73r 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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -478,6 +689,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR 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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -487,9 +699,11 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v 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-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-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -505,26 +719,34 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20181122145206-62eef0e2fa9b/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-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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -535,17 +757,25 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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= @@ -554,12 +784,18 @@ 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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -579,13 +815,17 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-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-20200103221440-774c71fcf114/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-20201224043029-2b0845dc783e/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= @@ -597,6 +837,7 @@ 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.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 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= @@ -605,6 +846,7 @@ google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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= @@ -614,6 +856,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn 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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 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= @@ -623,10 +866,15 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx 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/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 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= @@ -634,24 +882,32 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +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= 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= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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= @@ -662,10 +918,12 @@ 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 h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= @@ -674,3 +932,5 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/ops/docker/js-builder/Dockerfile b/ops/docker/js-builder/Dockerfile index 774de88038fc..5fb85f8a12d1 100644 --- a/ops/docker/js-builder/Dockerfile +++ b/ops/docker/js-builder/Dockerfile @@ -1,3 +1,5 @@ +FROM ghcr.io/foundry-rs/foundry:latest as foundry + FROM python:3.8.12-slim-buster RUN apt-get update && \ @@ -8,3 +10,6 @@ RUN apt-get update && \ npm i -g yarn && \ npm i -g depcheck && \ pip install slither-analyzer + +COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge +COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast \ No newline at end of file diff --git a/proxyd/go.mod b/proxyd/go.mod index 8415a9492e3c..8fe7035532ea 100644 --- a/proxyd/go.mod +++ b/proxyd/go.mod @@ -22,7 +22,6 @@ require ( github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect diff --git a/proxyd/go.sum b/proxyd/go.sum index 88dd55311acd..7a2e81f41a06 100644 --- a/proxyd/go.sum +++ b/proxyd/go.sum @@ -71,7 +71,6 @@ github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+Wji github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/teleportr/go.mod b/teleportr/go.mod index 6c170ade2c4c..5d1fc0fd8705 100644 --- a/teleportr/go.mod +++ b/teleportr/go.mod @@ -41,8 +41,8 @@ require ( github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/nxadm/tail v1.4.8 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/onsi/ginkgo v1.16.4 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect diff --git a/teleportr/go.sum b/teleportr/go.sum index 9313ea21276e..578997fd7b69 100644 --- a/teleportr/go.sum +++ b/teleportr/go.sum @@ -77,6 +77,7 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2 github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= From 945c0e737e15c44bcd606d0fccada0eca0b8cf10 Mon Sep 17 00:00:00 2001 From: Diederik Loerakker Date: Sun, 15 May 2022 16:47:54 +0200 Subject: [PATCH 584/585] outline bedrock dirs, rm stale protocol repo files (#2562) --- .gitignore | 5 + README.md | 37 ++++-- meta/releases.md | 36 ------ protocol/.editorconfig | 19 --- protocol/.github/workflows/devnet-ci.yml | 38 ------ protocol/.github/workflows/go-ci.yml | 132 --------------------- protocol/.github/workflows/markdown-ci.yml | 57 --------- protocol/.github/workflows/solidity-ci.yml | 87 -------------- protocol/.gitignore | 18 --- protocol/config.yml | 68 ----------- protocol/go.work | 13 -- protocol/go.work.sum | 9 -- protocol/package.json | 24 ---- {meta => specs/meta}/README.md | 5 +- protocol/README.md => specs/meta/devnet.md | 40 +------ {meta => specs/meta}/linting.md | 0 {meta => specs/meta}/markdown-style.md | 6 +- 17 files changed, 39 insertions(+), 555 deletions(-) delete mode 100644 meta/releases.md delete mode 100644 protocol/.editorconfig delete mode 100644 protocol/.github/workflows/devnet-ci.yml delete mode 100644 protocol/.github/workflows/go-ci.yml delete mode 100644 protocol/.github/workflows/markdown-ci.yml delete mode 100644 protocol/.github/workflows/solidity-ci.yml delete mode 100644 protocol/.gitignore delete mode 100644 protocol/config.yml delete mode 100644 protocol/go.work delete mode 100644 protocol/go.work.sum delete mode 100644 protocol/package.json rename {meta => specs/meta}/README.md (56%) rename protocol/README.md => specs/meta/devnet.md (55%) rename {meta => specs/meta}/linting.md (100%) rename {meta => specs/meta}/markdown-style.md (86%) diff --git a/.gitignore b/.gitignore index f8e96dbcf403..127e0bd22b78 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ temp coverage.json *.tsbuildinfo +yarn-error.log + dist artifacts cache @@ -19,6 +21,9 @@ packages/contracts/hardhat* packages/data-transport-layer/db +packages/integration-tests-bedrock/cache +packages/integration-tests-bedrock/artifacts + # vim *.sw* diff --git a/README.md b/README.md index 872ebfc84469..438c9ce19a67 100644 --- a/README.md +++ b/README.md @@ -31,21 +31,38 @@ Then check out our list of [good first issues](https://github.com/ethereum-optim
 root
 ├── packages
+│   ├── common-ts: Common tools for building apps in TypeScript
 │   ├── contracts: L1 and L2 smart contracts for Optimism
 │   ├── core-utils: Low-level utilities that make building Optimism easier
-│   ├── common-ts: Common tools for building apps in TypeScript
 │   ├── data-transport-layer: Service for indexing Optimism-related L1 data
-│   ├── fault-detector: Service for detecting faulty L2 output proposals
+│   ├── fault-detector:
+│   ├── integration-tests-bedrock (BEDROCK upgrade): Bedrock integration tests.
 │   ├── message-relayer: Tool for automatically relaying L1<>L2 messages in development
-│   └── replica-healthcheck: Service for monitoring the health of a replica node
-├── go
-│   ├── batch-submitter: Service for submitting batches of transactions and results to L1
-│   ├── bss-core: Core batch-submitter logic and utilities
-│   ├── gas-oracle: Service for updating L1 gas prices on L2
-│   └── proxyd: Configurable RPC request router and proxy
-├── l2geth: Optimism client software, a fork of geth v1.9.10
+│   ├── replica-healthcheck: Service for monitoring the health of a replica node
+│   └── sdk: provides a set of tools for interacting with Optimism
+
+~~ Production ~~
+├── batch-submitter: Service for submitting batches of transactions and results to L1
+├── bss-core: Core batch-submitter logic and utilities
+├── gas-oracle: Service for updating L1 gas prices on L2
+├── indexer: indexes and syncs transactions
+├── infra/op-replica: Deployment examples and resources for running an Optimism replica
 ├── integration-tests: Various integration tests for the Optimism network
-└── ops: Tools for running Optimism nodes and networks
+├── l2geth: Optimism client software, a fork of geth v1.9.10  (deprecated for BEDROCK upgrade)
+├── l2geth-exporter: A prometheus exporter to collect/serve metrics from an L2 geth node
+├── op-exporter: A prometheus exporter to collect/serve metrics from an Optimism node
+├── proxyd: Configurable RPC request router and proxy
+├── technical-documents: audits and post-mortem documents
+├── teleportr: Bridge for teleporting ETH between L1 and L2 at low cost
+
+~~ BEDROCK upgrade - Not production-ready yet, part of next major upgrade ~~
+├── contracts-bedrock: Bedrock smart contracts. To be merged with ./packages/contracts.
+├── op-batcher: L2-Batch Submitter, submits bundles of batches to L1
+├── op-e2e: End-to-End testing of all bedrock components in Go
+├── op-node: rollup consensus-layer client.
+├── op-proposer: L2-Output Submitter, submits proposals to L1
+├── ops-bedrock: Bedrock devnet work
+└── specs: Specs of the rollup starting at the Bedrock upgrade
 
## Branching Model and Releases diff --git a/meta/releases.md b/meta/releases.md deleted file mode 100644 index 8c93b042d61b..000000000000 --- a/meta/releases.md +++ /dev/null @@ -1,36 +0,0 @@ - -# Release process - -1. Confirm all release features are completed -2. Run tests and verify build outputs - ```shell - # 2.0: Verify linting - yarn - yarn lint - yarn lint:links - - # 2.1: Confirm contracts pass tests and compile - cd packages/contracts - yarn - yarn build - yarn test - cd ../.. - - # 2.2: Confirm contract bindings are up-to-date - cd op-node/contracts - make abi - make binding - cd ../.. - - # 2.3: Run Go tests (including end-to-end tests) - go test -v ../.. - ``` -3. Sign an annotated release tag (make sure to prefix with `v` and follow [semantic versioning](https://semver.org/)) - ```shell - # Opens editor for annotating the tag, give it a release title - git tag -s -a v0.1.0 - # Push the tag - git push origin v0.1.0 - ``` -4. Create a release on GitHub with the tag, provide a description of features and usage - diff --git a/protocol/.editorconfig b/protocol/.editorconfig deleted file mode 100644 index 79d2fd91e224..000000000000 --- a/protocol/.editorconfig +++ /dev/null @@ -1,19 +0,0 @@ -root = true - -# defaults -[*] -charset = utf-8 -end_of_line = lf -indent_size = 4 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true - -[*.go] -indent_style = tab - -[*.{ts,js}] -indent_size = 2 - -[*.yml] -indent_size = 2 diff --git a/protocol/.github/workflows/devnet-ci.yml b/protocol/.github/workflows/devnet-ci.yml deleted file mode 100644 index 686c4fd7faa6..000000000000 --- a/protocol/.github/workflows/devnet-ci.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Devnet integration tests - -on: - push: - branches: - - 'main' - - 'staging' - - 'feat/*' - pull_request: - workflow_dispatch: - -jobs: - compose-devnet: - runs-on: ubuntu-latest - name: Run integration tests on devnet - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - - uses: actions/setup-node@v2 - with: - node-version: '14' - cache: 'yarn' - - - name: Install Foundry - uses: onbjerg/foundry-toolchain@v1 - with: - version: nightly - - - run: make build-ts - name: Build TS - - - run: make devnet-up - name: Bring up the stack - - - run: make test-integration - name: Run integration tests diff --git a/protocol/.github/workflows/go-ci.yml b/protocol/.github/workflows/go-ci.yml deleted file mode 100644 index 8aaf5f9ab63d..000000000000 --- a/protocol/.github/workflows/go-ci.yml +++ /dev/null @@ -1,132 +0,0 @@ -name: Go lint and test - -on: - push: - branches: - - 'main' - - 'staging' - - 'feat/*' - pull_request: - workflow_dispatch: - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: 1.18 - - name: Checkout code - uses: actions/checkout@v2 - - - name: golangci-lint op-node - uses: golangci/golangci-lint-action@v3 - with: - version: v1.45.2 # version of golangci-lint, not the action - working-directory: op-node - # rules: https://golangci-lint.run/usage/quick-start/ - args: -E asciicheck,goimports,misspell - - name: golangci-lint op-proposer - uses: golangci/golangci-lint-action@v3 - with: - version: v1.45.2 # version of golangci-lint, not the action - working-directory: op-proposer - args: -E asciicheck,goimports,misspell - - name: golangci-lint op-batcher - uses: golangci/golangci-lint-action@v3 - with: - version: v1.45.2 # version of golangci-lint, not the action - working-directory: op-batcher - args: -E asciicheck,goimports,misspell - - name: golangci-lint op-e2e - uses: golangci/golangci-lint-action@v3 - with: - version: v1.45.2 # version of golangci-lint, not the action - working-directory: op-e2e - args: -E asciicheck,goimports,misspell - - name: Test op-node - run: | - cd op-node - go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... - - name: Test op-proposer - run: | - cd op-proposer - go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... - - name: Test op-batcher - run: | - cd op-batcher - go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... - - name: Test op-e2e - run: | - cd op-e2e - go test -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... - - - name: Upload coverage output - uses: codecov/codecov-action@v2 - with: - files: ./op-node/coverage.out,./op-proposer/coverage.out,./op-batcher/coverage.out,./op-e2e/coverage.out - flags: unittests - name: codecov-umbrella - verbose: true - - build: - runs-on: ubuntu-latest - name: Builds Bindings - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: 1.18 - - - name: Install abigen - run: | - git clone https://github.com/ethereum/go-ethereum /tmp/geth - cd /tmp/geth - make devtools - - - name: Install Foundry - uses: onbjerg/foundry-toolchain@v1 - with: - version: nightly - - - uses: actions/setup-node@v2 - with: - node-version: "16" - cache: "yarn" - - - name: Install Dependencies - run: | - cd packages/contracts - yarn install - - - name: op-node Contracts - run: | - cd op-node/contracts - make - git diff --exit-code - - - name: op-proposer Bindings - run: | - cd op-proposer - make bindings - git diff --exit-code - - op-node-fuzz: - runs-on: ubuntu-latest - name: Fuzz parsers in the opnode - steps: - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: 1.18 - - name: Checkout code - uses: actions/checkout@v2 - - name: Fuzz - run: | - cd op-node - make fuzz diff --git a/protocol/.github/workflows/markdown-ci.yml b/protocol/.github/workflows/markdown-ci.yml deleted file mode 100644 index fc91f0134a1c..000000000000 --- a/protocol/.github/workflows/markdown-ci.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: lint/format markdown - -on: - push: - branches: - - 'main' - - 'staging' - - 'feat/*' - pull_request: - workflow_dispatch: - -jobs: - lint: - name: Linting - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Fetch history - run: git fetch - - uses: actions/setup-node@v1 - with: - node-version: 14 - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Install Dependencies - # only install dependencies if there was a change in the deps - # if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn install - - - name: Lint - run: yarn lint:check - - - name: Toc check - # exit if there are changes (i.e. if the TOC changed) - run: "yarn lint:toc && if [[ `git status --porcelain` ]]; then exit 1; else exit 0; fi" - - linkChecker: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Link Checker - uses: lycheeverse/lychee-action@v1.2.0 - with: - args: --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude-mail README.md "./specs/**/*.md" "./meta/**/*.md" "./op-node/**/*.md" - fail: true diff --git a/protocol/.github/workflows/solidity-ci.yml b/protocol/.github/workflows/solidity-ci.yml deleted file mode 100644 index 4feac712241b..000000000000 --- a/protocol/.github/workflows/solidity-ci.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Contracts lint, test and static analysis - -on: - push: - branches: - - "main" - - "staging" - - "feat/*" - pull_request: - workflow_dispatch: - -env: - PYTEST_ADDOPTS: "--color=yes" - -defaults: - run: - shell: bash - working-directory: ./packages/contracts - -jobs: - yarn-test: - runs-on: ubuntu-latest - name: Yarn Test - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - - uses: actions/setup-node@v2 - with: - node-version: "14" - cache: "yarn" - - run: yarn install - - - name: Lint - run: yarn lint:check - - forge-test: - runs-on: ubuntu-latest - name: Forge Test - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - - name: Install Foundry - uses: onbjerg/foundry-toolchain@v1 - with: - version: nightly - - - name: Install deps - run: yarn install - - - name: Build with Forge - run: yarn build:forge - - - name: Test with Forge - run: yarn test:forge - - - name: Gas snapshot - run: forge snapshot && git diff --exit-code - - slither: - runs-on: ubuntu-latest - name: Slither - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - - uses: actions/setup-node@v2 - with: - node-version: "14" - cache: "yarn" - - run: yarn install - - - name: Set up Python 3.8 - uses: actions/setup-python@v2 - with: - python-version: "3.8" - - - name: Install Slither - run: pip3 install slither-analyzer - - - name: Run Slither - run: yarn slither - continue-on-error: true diff --git a/protocol/.gitignore b/protocol/.gitignore deleted file mode 100644 index 95c7479a15bb..000000000000 --- a/protocol/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -node_modules -yarn-error.log - -# built binaries -bin - -# vim swap files -*.sw* - -integration-tests/cache/ -integration-tests/artifacts/ -**/*.env -.devnet - -# Ignore local fuzzing results -**/testdata/fuzz/ - -coverage.out \ No newline at end of file diff --git a/protocol/config.yml b/protocol/config.yml deleted file mode 100644 index 06af510c357d..000000000000 --- a/protocol/config.yml +++ /dev/null @@ -1,68 +0,0 @@ -version: 2.1 - - -jobs: - build-dockerfile: - docker: - - image: cimg/base:2022.04 - parameters: - image-name: - description: Image name - type: string - image-tag: - description: Image tag - type: string - target: - description: Dockerfile target - type: string - default: "" - dockerfile: - description: Dockerfile to use - type: string - steps: - - checkout - - setup_remote_docker: - version: 20.10.12 - - run: - name: Build - command: | - echo "$DOCKER_PASS" | docker login -u "$DOCKER_USERNAME" --password-stdin - docker build -t "ethereumoptimism/<>:<>" -f <> <<#parameters.target>>--target <><> . - docker push "ethereumoptimism/<>:<>" - -workflows: - main: - jobs: - - build-dockerfile: - context: - - optimism - filters: - branches: - only: - - main - image-name: op-node - image-tag: develop - dockerfile: ops-bedrock/Dockerfile.node - name: Build op-node - - build-dockerfile: - context: - - optimism - filters: - branches: - only: - - main - image-name: op-proposer - image-tag: develop - dockerfile: ops-bedrock/Dockerfile.proposer - name: Build op-proposer - - build-dockerfile: - context: - - optimism - filters: - branches: - only: - - main - image-name: op-batcher - image-tag: develop - dockerfile: ops-bedrock/Dockerfile.batcher - name: Build op-batcher diff --git a/protocol/go.work b/protocol/go.work deleted file mode 100644 index de3336197b46..000000000000 --- a/protocol/go.work +++ /dev/null @@ -1,13 +0,0 @@ -go 1.18 - -use ( - ./op-batcher - ./op-e2e - ./op-node - ./op-proposer -) - -replace github.com/ethereum/go-ethereum v1.10.16 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce - -// For local debugging: -// replace github.com/ethereum/go-ethereum v1.10.16 => ../go-ethereum diff --git a/protocol/go.work.sum b/protocol/go.work.sum deleted file mode 100644 index 339aba62148f..000000000000 --- a/protocol/go.work.sum +++ /dev/null @@ -1,9 +0,0 @@ -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce h1:Wa0BVNdeyzIoJkrZtI7o2NEw8F98vVIzkPpiFACbdCA= -github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= -github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= diff --git a/protocol/package.json b/protocol/package.json deleted file mode 100644 index cf99457d8d76..000000000000 --- a/protocol/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@eth-optimism/specs-2", - "version": "0.4.0", - "license": "MIT", - "private": true, - "devDependencies": { - "doctoc": "2.1.0", - "lint-staged": "11.0.0", - "markdownlint": "^0.24.0", - "markdownlint-cli2": "^0.3.2" - }, - "scripts": { - "setup": "yarn install && cargo install lychee", - "lint": "yarn lint:fix && yarn lint:check", - "lint:fix": "markdownlint-cli2-fix \\\"op-node/README.md\\\" \\\"./specs/**/*.md\\\" \\\"#**/node_modules\\\"", - "lint:check": "markdownlint-cli2 \\\"op-node/README.md\\\" \\\"./specs/**/*.md\\\" \\\"#**/node_modules\\\"", - "lint:links": "lychee --exclude twitter.com --exclude-mail README.md \\\"op-node/README.md\\\" \\\"./specs/**/*.md\\\" \\\"./meta/**/*.md\\\" \\\"./op-node/**/*.md\\\"", - "lint:toc": "doctoc --title=\"**Table of Contents**\" ./specs ./meta" - }, - "dependencies": { - "@eth-optimism/core-utils": "^0.8.1", - "@ethersproject/constants": "^5.6.0" - } -} diff --git a/meta/README.md b/specs/meta/README.md similarity index 56% rename from meta/README.md rename to specs/meta/README.md index 8a9f9f9d9d09..5039d5a6c019 100644 --- a/meta/README.md +++ b/specs/meta/README.md @@ -1,9 +1,8 @@ # Meta Processes -This directory describes processes that we use to build the specification. +This directory describes processes that we use to lint/test the specification. - [Linting](linting.md): how to lint source files. - [Markdown Style Guide](markdown-style.md): how to format and structure Markdown files. -- [Release process](releases.md): how to create releases. - +- [Devnet introduction](devnet.md): how to run a devnet. diff --git a/protocol/README.md b/specs/meta/devnet.md similarity index 55% rename from protocol/README.md rename to specs/meta/devnet.md index c9f84b1611bc..2bd3f7bba625 100644 --- a/protocol/README.md +++ b/specs/meta/devnet.md @@ -1,19 +1,4 @@ -[![codecov](https://codecov.io/gh/ethereum-optimism/optimistic-specs/branch/main/graph/badge.svg?token=19JPIN9XPB)](https://codecov.io/gh/ethereum-optimism/optimistic-specs) - -# The Optimism Spec - -This repository holds the work-in-progress specification for the next version of -Optimism. - -This spec is developed iteratively, specifying a rollup of increasing -complexity. The current stage specifies a "rollup" with deposits, withdrawals and sequenced (L2-native) transactions. -Some aspects, such as the fee logic and calldata compression, are still missing or in placeholder state. - -## Work in Progress - -Please note that this specification is currently under heavy construction. - -## Local Devnet Setup +# Bedrock Local Devnet Setup You can spin up a local devnet via `docker-compose`. For convenience, we have defined `make` targets to start and stop the devnet with a single command. @@ -47,7 +32,7 @@ npx hardhat deposit --amount-eth --to
You'll need a `.env` with the following contents: -``` +```bash L1_PROVIDER_URL=http://localhost:8545 L2_PROVIDER_URL=http://localhost:8546 PRIVATE_KEY=bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 @@ -57,24 +42,3 @@ The batch submitter uses the account below to submit batches to L1: - Address: `0xde3829a23df1479438622a08a116e8eb3f620bb5` - Private key: `bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7` - -## Contributing - -### Basic Contributions - -Contributing to the Optimism specification is easy. - -You'll find a list of open questions and active research topics over on the -[Discussions] page for this repo. Specific tasks and TODOs can be found on the -[Issues] page. You can edit content or add new pages by creating a [pull -request]. - -[Discussions]: https://github.com/ethereum-optimism/optimistic-specs/discussions -[Issues]: https://github.com/ethereum-optimism/optimistic-specs/issues -[pull request]: https://github.com/ethereum-optimism/optimistic-specs/pulls - -## License - -Specification: CC0 1.0 Universal, see [`specs/LICENSE`](./specs/LICENSE) file. - -Reference software: MIT, see [`LICENSE`](./LICENSE) file. diff --git a/meta/linting.md b/specs/meta/linting.md similarity index 100% rename from meta/linting.md rename to specs/meta/linting.md diff --git a/meta/markdown-style.md b/specs/meta/markdown-style.md similarity index 86% rename from meta/markdown-style.md rename to specs/meta/markdown-style.md index e6a40443bade..ccc4ae6ced0b 100644 --- a/meta/markdown-style.md +++ b/specs/meta/markdown-style.md @@ -27,9 +27,9 @@ Notably: In general: - Use link references preferentially. - - e.g. `[my text][link-ref]` and then on its own line `[link-ref]: https://mylink.com` - - e.g. `[my text]` and then on its own line: `[my text]: https://mylink.com` - - exceptions: where it fits neatly on a single line, in particular in lists of links + - e.g. `[my text][link-ref]` and then on its own line `[link-ref]: https://mylink.com` + - e.g. `[my text]` and then on its own line: `[my text]: https://mylink.com` + - exceptions: where it fits neatly on a single line, in particular in lists of links - Excepted for internal and glossary links (see below), add the link reference definition directly after the paragraph where the link first appears. From 940cfacbe1d12a8c5661dab239bf4690d6159103 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 16 May 2022 10:46:43 -0600 Subject: [PATCH 585/585] monorepo merge: re-run yarn --- yarn.lock | 650 ++++++------------------------------------------------ 1 file changed, 73 insertions(+), 577 deletions(-) diff --git a/yarn.lock b/yarn.lock index 042a11e15602..23204508eb93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -528,19 +528,6 @@ "@ethersproject/abstract-signer" "^5.5.0" "@ethersproject/hardware-wallets" "^5.5.0" -"@eth-optimism/core-utils@0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.7.3.tgz#67a7ec3cd65a555c6b5ef50d03ea66aa8df9f6c8" - integrity sha512-e531gfcMN6LWvGgJGfB37cU8HNUXfCkT6OO84KT8qKHMT4mOxyUqnApTYOHBxXGetLd3z/n67KwBCkJLZBr9jw== - dependencies: - "@ethersproject/abstract-provider" "^5.4.1" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/providers" "^5.4.5" - "@ethersproject/web" "^5.5.0" - chai "^4.3.4" - ethers "^5.4.5" - lodash "^4.17.21" - "@eth-optimism/core-utils@0.8.3": version "0.8.3" resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.8.3.tgz#226d6ac4cb80bd165d64f5ffa4f3e0b300568678" @@ -574,14 +561,6 @@ "@ethereum-waffle/provider" "^3.4.0" ethers "^5.0.0" -"@ethereum-waffle/chai@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" - integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== - dependencies: - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.5.2" - "@ethereum-waffle/compiler@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.0.tgz#68917321212563544913de33e408327745cb1284" @@ -599,23 +578,6 @@ ts-generator "^0.1.1" typechain "^3.0.0" -"@ethereum-waffle/compiler@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" - integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== - dependencies: - "@resolver-engine/imports" "^0.3.3" - "@resolver-engine/imports-fs" "^0.3.3" - "@typechain/ethers-v5" "^2.0.0" - "@types/mkdirp" "^0.5.2" - "@types/node-fetch" "^2.5.5" - ethers "^5.0.1" - mkdirp "^0.5.1" - node-fetch "^2.6.1" - solc "^0.6.3" - ts-generator "^0.1.1" - typechain "^3.0.0" - "@ethereum-waffle/ens@^3.3.0": version "3.3.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.3.0.tgz#d54f4c8e6b7bcafdc13ab294433f45416b2b2791" @@ -625,15 +587,6 @@ "@ensdomains/resolver" "^0.2.4" ethers "^5.0.1" -"@ethereum-waffle/ens@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" - integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== - dependencies: - "@ensdomains/ens" "^0.4.4" - "@ensdomains/resolver" "^0.2.4" - ethers "^5.5.2" - "@ethereum-waffle/mock-contract@^3.3.0": version "3.3.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.3.0.tgz#7b331f1c95c5d46ee9478f7a6be2869f707d307a" @@ -642,14 +595,6 @@ "@ethersproject/abi" "^5.0.1" ethers "^5.0.1" -"@ethereum-waffle/mock-contract@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" - integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== - dependencies: - "@ethersproject/abi" "^5.5.0" - ethers "^5.5.2" - "@ethereum-waffle/provider@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.0.tgz#a36a0890d4fbc230e807870c8d3b683594efef00" @@ -661,17 +606,6 @@ patch-package "^6.2.2" postinstall-postinstall "^2.1.0" -"@ethereum-waffle/provider@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" - integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== - dependencies: - "@ethereum-waffle/ens" "^3.4.4" - ethers "^5.5.2" - ganache-core "^2.13.2" - patch-package "^6.2.2" - postinstall-postinstall "^2.1.0" - "@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.0", "@ethereumjs/block@^3.6.1": version "3.6.1" resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.1.tgz#50574d3e993ae247dcfe2abbdb91d2a4a22accb9" @@ -682,16 +616,6 @@ ethereumjs-util "^7.1.4" merkle-patricia-tree "^4.2.3" -"@ethereumjs/block@^3.6.2": - version "3.6.2" - resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.2.tgz#63d1e26d0b7a7a3684fce920de6ebabec1e5b674" - integrity sha512-mOqYWwMlAZpYUEOEqt7EfMFuVL2eyLqWWIzcf4odn6QgXY8jBI2NhVuJncrMCKeMZrsJAe7/auaRRB6YcdH+Qw== - dependencies: - "@ethereumjs/common" "^2.6.3" - "@ethereumjs/tx" "^3.5.1" - ethereumjs-util "^7.1.4" - merkle-patricia-tree "^4.2.4" - "@ethereumjs/blockchain@^5.5.0", "@ethereumjs/blockchain@^5.5.1": version "5.5.1" resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.1.tgz#60f1f50592c06cc47e1704800b88b7d32f609742" @@ -706,20 +630,6 @@ lru-cache "^5.1.1" semaphore-async-await "^1.5.1" -"@ethereumjs/blockchain@^5.5.2": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.2.tgz#1848abd9dc1ee56acf8cec4c84304d7f4667d027" - integrity sha512-Jz26iJmmsQtngerW6r5BDFaew/f2mObLrRZo3rskLOx1lmtMZ8+TX/vJexmivrnWgmAsTdNWhlKUYY4thPhPig== - dependencies: - "@ethereumjs/block" "^3.6.2" - "@ethereumjs/common" "^2.6.3" - "@ethereumjs/ethash" "^1.1.0" - debug "^4.3.3" - ethereumjs-util "^7.1.4" - level-mem "^5.0.1" - lru-cache "^5.1.1" - semaphore-async-await "^1.5.1" - "@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.4.0.tgz#2d67f6e6ba22246c5c89104e6b9a119fb3039766" @@ -736,14 +646,6 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.4" -"@ethereumjs/common@^2.6.3", "@ethereumjs/common@^2.6.4": - version "2.6.4" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.4.tgz#1b3cdd3aa4ee3b0ca366756fc35e4a03022a01cc" - integrity sha512-RDJh/R/EAr+B7ZRg5LfJ0BIpf/1LydFgYdvZEuTraojCbVypO2sQ+QnpP5u2wJf9DASyooKqu8O4FJEWUV6NXw== - dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.4" - "@ethereumjs/ethash@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.1.0.tgz#7c5918ffcaa9cb9c1dc7d12f77ef038c11fb83fb" @@ -771,14 +673,6 @@ "@ethereumjs/common" "^2.6.1" ethereumjs-util "^7.1.4" -"@ethereumjs/tx@^3.5.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.1.tgz#8d941b83a602b4a89949c879615f7ea9a90e6671" - integrity sha512-xzDrTiu4sqZXUcaBxJ4n4W5FrppwxLxZB4ZDGVLtxSQR4lVuOnFR6RcUHdg1mpUhAPVrmnzLJpxaeXnPxIyhWA== - dependencies: - "@ethereumjs/common" "^2.6.3" - ethereumjs-util "^7.1.4" - "@ethereumjs/vm@^5.6.0": version "5.7.1" resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.7.1.tgz#3bf757fbad0081838ccb4f22003cd73319ab3616" @@ -797,24 +691,6 @@ merkle-patricia-tree "^4.2.3" rustbn.js "~0.2.0" -"@ethereumjs/vm@^5.9.0": - version "5.9.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.0.tgz#54e485097c6dbb42554d541ef8d84d06b7ddf12f" - integrity sha512-0IRsj4IuF8lFDWVVLc4mFOImaSX8VWF8CGm3mXHG/LLlQ/Tryy/kKXMw/bU9D+Zw03CdteW+wCGqNFS6+mPjpg== - dependencies: - "@ethereumjs/block" "^3.6.2" - "@ethereumjs/blockchain" "^5.5.2" - "@ethereumjs/common" "^2.6.4" - "@ethereumjs/tx" "^3.5.1" - async-eventemitter "^0.2.4" - core-js-pure "^3.0.1" - debug "^4.3.3" - ethereumjs-util "^7.1.4" - functional-red-black-tree "^1.0.1" - mcl-wasm "^0.7.1" - merkle-patricia-tree "^4.2.4" - rustbn.js "~0.2.0" - "@ethersproject/abi@5.0.0-beta.153": version "5.0.0-beta.153" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" @@ -946,7 +822,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/web" "^5.5.0" -"@ethersproject/abstract-provider@5.6.0", "@ethersproject/abstract-provider@^5.4.1", "@ethersproject/abstract-provider@^5.6.0": +"@ethersproject/abstract-provider@5.6.0", "@ethersproject/abstract-provider@^5.6.0": version "5.6.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz#0c4ac7054650dbd9c476cf5907f588bbb6ef3061" integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== @@ -1140,7 +1016,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.6.1": +"@ethersproject/bytes@5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== @@ -1550,7 +1426,7 @@ bech32 "1.1.4" ws "7.4.6" -"@ethersproject/providers@5.6.6", "@ethersproject/providers@^5.4.5": +"@ethersproject/providers@5.6.6": version "5.6.6" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.6.tgz#1967149cb4557d253f8c176a44aabda155f228cd" integrity sha512-6X6agj3NeQ4tgnvBMCjHK+CjQbz+Qmn20JTxCYZ/uymrgCEOpJtY9zeRxJIDsSi0DPw8xNAxypj95JMCsapUfA== @@ -2895,29 +2771,11 @@ safe-buffer "^5.1.1" util.promisify "^1.0.0" -"@nomiclabs/hardhat-ethers@^2.0.0": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.6.tgz#1c695263d5b46a375dcda48c248c4fba9dfe2fc2" - integrity sha512-q2Cjp20IB48rEn2NPjR1qxsIQBvFVYW9rFRCFq+bC4RUrn1Ljz3g4wM8uSlgIBZYBi2JMXxmOzFqHraczxq4Ng== - "@nomiclabs/hardhat-ethers@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.2.tgz#c472abcba0c5185aaa4ad4070146e95213c68511" integrity sha512-6quxWe8wwS4X5v3Au8q1jOvXYEPkS1Fh+cME5u6AwNdnI4uERvPlVjlgRWzpnb+Rrt1l/cEqiNRH9GlsBMSDQg== -"@nomiclabs/hardhat-etherscan@^2.1.3": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.8.tgz#e206275e96962cd15e5ba9148b44388bc922d8c2" - integrity sha512-0+rj0SsZotVOcTLyDOxnOc3Gulo8upo0rsw/h+gBPcmtj91YqYJNhdARHoBxOhhE8z+5IUQPx+Dii04lXT14PA== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@ethersproject/address" "^5.0.2" - cbor "^5.0.2" - debug "^4.1.1" - fs-extra "^7.0.1" - node-fetch "^2.6.0" - semver "^6.3.0" - "@nomiclabs/hardhat-etherscan@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.3.tgz#ca54a03351f3de41f9f5240e37bea9d64fa24e64" @@ -2931,14 +2789,6 @@ semver "^6.3.0" undici "^4.14.1" -"@nomiclabs/hardhat-waffle@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" - integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== - dependencies: - "@types/sinon-chai" "^3.2.3" - "@types/web3" "1.0.19" - "@nomiclabs/hardhat-waffle@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.1.tgz#5d43654fba780720c5033dea240fe14f70ef4bd2" @@ -3120,11 +2970,6 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.4.0.tgz#85161d87c840c5bce2b6ed0c727b407e774852ae" integrity sha512-hIEyWJHu7bDTv6ckxOaV+K3+7mVzhjtyvp3QSaz56Rk5PscXtPAbkiNTb3yz6UJCWHPWpxVyULVgZ6RubuFEZg== -"@openzeppelin/contracts-upgradeable@^4.5.2": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.6.0.tgz#1bf55f230f008554d4c6fe25eb165b85112108b0" - integrity sha512-5OnVuO4HlkjSCJO165a4i2Pu1zQGzMs//o54LPrwUgxvEO2P3ax1QuaSI0cEHHTveA77guS0PnNugpR2JMsPfA== - "@openzeppelin/contracts@3.4.1-solc-0.7-2": version "3.4.1-solc-0.7-2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92" @@ -3145,11 +2990,6 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.4.0.tgz#4a1df71f736c31230bbbd634dfb006a756b51e6b" integrity sha512-dlKiZmDvJnGRLHojrDoFZJmsQVeltVeoiRN7RK+cf2FmkhASDEblE0RiaYdxPNsUZa6mRG8393b9bfyp+V5IAw== -"@openzeppelin/contracts@^4.5.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.6.0.tgz#c91cf64bc27f573836dba4122758b4743418c1b3" - integrity sha512-8vi4d50NNya/bQqCmaVzvHNmwHvS0OBKb7HNtuNwEE3scXWrP31fKQoGxNMT+KbzmrNZzatE3QK5p2gFONI/hg== - "@primitivefi/hardhat-dodoc@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@primitivefi/hardhat-dodoc/-/hardhat-dodoc-0.1.3.tgz#338ecff24b93d3b43fa35a98909f6840af86c27c" @@ -3361,7 +3201,7 @@ dependencies: antlr4ts "^0.5.0-alpha.4" -"@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1": +"@solidity-parser/parser@^0.14.1": version "0.14.1" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.1.tgz#179afb29f4e295a77cc141151f26b3848abc3c46" integrity sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw== @@ -3441,14 +3281,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== -"@typechain/ethers-v5@^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.0.0.tgz#1b6e292d2ed9afb0d2f7a4674cc199bb95bad714" - integrity sha512-Kot7fwAqnH96ZbI8xrRgj5Kpv9yCEdjo7mxRqrH7bYpEgijT5MmuOo8IVsdhOu7Uog4ONg7k/d5UdbAtTKUgsA== - dependencies: - lodash "^4.17.15" - ts-essentials "^7.0.1" - "@typechain/ethers-v5@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" @@ -3456,29 +3288,21 @@ dependencies: ethers "^5.0.2" -"@typechain/ethers-v5@^7.0.1": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz#d559cffe0efe6bdbc20e644b817f6fa8add5e8f8" - integrity sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw== +"@typechain/ethers-v5@^8.0.2": + version "8.0.5" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-8.0.5.tgz#d469420e9a73deb7fa076cde9edb45d713dd1b8c" + integrity sha512-ntpj4cS3v4WlDu+hSKSyj9A3o1tKtWC30RX1gobeYymZColeJiUemC1Kgfa0MWGmInm5CKxoHVhEvYVgPOZn1A== dependencies: lodash "^4.17.15" ts-essentials "^7.0.1" -"@typechain/hardhat@^2.3.0": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-2.3.1.tgz#1e8a6e3795e115a5d5348526282b5c597fab0b78" - integrity sha512-BQV8OKQi0KAzLXCdsPO0pZBNQQ6ra8A2ucC26uFX/kquRBtJu1yEyWnVSmtr07b5hyRoJRpzUeINLnyqz4/MAw== +"@typechain/hardhat@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-3.1.0.tgz#88bd9e9d55e30fbece6fbb34c03ecd40a8b2013a" + integrity sha512-C6Be6l+vTpao19PvMH2CB/lhL1TRLkhdPkvQCF/zqkY1e+0iqY2Bb9Jd3PTt6I8QvMm89ZDerrCJC9927ZHmlg== dependencies: fs-extra "^9.1.0" -"@typechain/hardhat@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.0.0.tgz#5e305641de67276efbfaa8c37c78e38f22b22ef4" - integrity sha512-AnhwODKHxx3+st5uc1j2NQh79Lv2OuvDQe4dKn8ZxhqYsAsTPnHTLBeI8KPZ+mfdE7v13D2QYssRTIkkGhK35A== - dependencies: - fs-extra "^9.1.0" - lodash "^4.17.15" - "@types/abstract-leveldown@*": version "5.0.2" resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.2.tgz#ee81917fe38f770e29eec8139b6f16ee4a8b0a5f" @@ -3518,11 +3342,6 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.21.tgz#9f35a5643129df132cf3b5c1ec64046ea1af0650" integrity sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg== -"@types/chai@^4.2.21": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04" - integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ== - "@types/concat-stream@^1.6.0": version "1.6.1" resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" @@ -3644,11 +3463,6 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323" integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== -"@types/mocha@^9.0.0": - version "9.1.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" - integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== - "@types/node-fetch@^2.5.5": version "2.5.10" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132" @@ -3667,11 +3481,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== -"@types/node@^12.0.0": - version "12.20.52" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.52.tgz#2fd2dc6bfa185601b15457398d4ba1ef27f81251" - integrity sha512-cfkwWw72849SNYp3Zx0IcIs25vABmFh73xicxhCkTcvtZQeIez15PpwQN8fY3RD7gv1Wrxlc9MEtfMORZDEsGw== - "@types/node@^12.12.6", "@types/node@^12.7.1": version "12.20.20" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.20.tgz#ce3d6c13c15c5e622a85efcd3a1cb2d9c7fa43a6" @@ -3841,20 +3650,6 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/eslint-plugin@^4.29.1": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" - integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== - dependencies: - "@typescript-eslint/experimental-utils" "4.33.0" - "@typescript-eslint/scope-manager" "4.33.0" - debug "^4.3.1" - functional-red-black-tree "^1.0.1" - ignore "^5.1.8" - regexpp "^3.1.0" - semver "^7.3.5" - tsutils "^3.21.0" - "@typescript-eslint/experimental-utils@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz#52e437a689ccdef73e83c5106b34240a706f15e1" @@ -3867,18 +3662,6 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/experimental-utils@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" - integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== - dependencies: - "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.33.0" - "@typescript-eslint/types" "4.33.0" - "@typescript-eslint/typescript-estree" "4.33.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - "@typescript-eslint/parser@^4.26.0": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.29.3.tgz#2ac25535f34c0e98f50c0e6b28c679c2357d45f2" @@ -3889,16 +3672,6 @@ "@typescript-eslint/typescript-estree" "4.29.3" debug "^4.3.1" -"@typescript-eslint/parser@^4.29.1": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" - integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== - dependencies: - "@typescript-eslint/scope-manager" "4.33.0" - "@typescript-eslint/types" "4.33.0" - "@typescript-eslint/typescript-estree" "4.33.0" - debug "^4.3.1" - "@typescript-eslint/scope-manager@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz#497dec66f3a22e459f6e306cf14021e40ec86e19" @@ -3907,24 +3680,11 @@ "@typescript-eslint/types" "4.29.3" "@typescript-eslint/visitor-keys" "4.29.3" -"@typescript-eslint/scope-manager@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" - integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== - dependencies: - "@typescript-eslint/types" "4.33.0" - "@typescript-eslint/visitor-keys" "4.33.0" - "@typescript-eslint/types@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.29.3.tgz#d7980c49aef643d0af8954c9f14f656b7fd16017" integrity sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg== -"@typescript-eslint/types@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" - integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== - "@typescript-eslint/typescript-estree@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz#1bafad610015c4ded35c85a70b6222faad598b40" @@ -3938,19 +3698,6 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" - integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== - dependencies: - "@typescript-eslint/types" "4.33.0" - "@typescript-eslint/visitor-keys" "4.33.0" - debug "^4.3.1" - globby "^11.0.3" - is-glob "^4.0.1" - semver "^7.3.5" - tsutils "^3.21.0" - "@typescript-eslint/visitor-keys@4.29.3": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz#c691760a00bd86bf8320d2a90a93d86d322f1abf" @@ -3959,14 +3706,6 @@ "@typescript-eslint/types" "4.29.3" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" - integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== - dependencies: - "@typescript-eslint/types" "4.33.0" - eslint-visitor-keys "^2.0.0" - "@ungap/promise-all-settled@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" @@ -5764,19 +5503,6 @@ chai-as-promised@^7.1.1: dependencies: check-error "^1.0.2" -chai@^4.2.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" - integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - chai@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" @@ -7173,11 +6899,6 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emoji-regex@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66" - integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== - emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -7408,11 +7129,6 @@ eslint-config-prettier@^8.3.0: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== -eslint-config-standard@^16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" - integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== - eslint-import-resolver-node@^0.3.6: version "0.3.6" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" @@ -7429,14 +7145,6 @@ eslint-module-utils@^2.6.2: debug "^3.2.7" pkg-dir "^2.0.0" -eslint-plugin-es@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" - integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== - dependencies: - eslint-utils "^2.0.0" - regexpp "^3.0.0" - eslint-plugin-import@^2.23.4: version "2.24.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz#64aba8b567a1ba9921d5465586e86c491b8e2135" @@ -7473,18 +7181,6 @@ eslint-plugin-jsdoc@^35.1.2: semver "^7.3.5" spdx-expression-parse "^3.0.1" -eslint-plugin-node@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" - integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== - dependencies: - eslint-plugin-es "^3.0.0" - eslint-utils "^2.0.0" - ignore "^5.1.1" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" - eslint-plugin-prefer-arrow@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz#e7fbb3fa4cd84ff1015b9c51ad86550e55041041" @@ -7497,11 +7193,6 @@ eslint-plugin-prettier@^3.4.0: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-promise@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz#a596acc32981627eb36d9d75f9666ac1a4564971" - integrity sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw== - eslint-plugin-react@^7.24.0: version "7.24.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz#eadedfa351a6f36b490aa17f4fa9b14e842b9eb4" @@ -7573,7 +7264,7 @@ eslint-utils@^1.3.1: dependencies: eslint-visitor-keys "^1.1.0" -eslint-utils@^2.0.0, eslint-utils@^2.1.0: +eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== @@ -7639,7 +7330,7 @@ eslint@^5.6.0: table "^5.2.3" text-table "^0.2.0" -eslint@^7.27.0, eslint@^7.29.0: +eslint@^7.27.0: version "7.32.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== @@ -7936,17 +7627,6 @@ ethereum-cryptography@^0.1.2, ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereum-waffle@^3.0.0: - version "3.4.4" - resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" - integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== - dependencies: - "@ethereum-waffle/chai" "^3.4.4" - "@ethereum-waffle/compiler" "^3.4.4" - "@ethereum-waffle/mock-contract" "^3.4.4" - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.0.1" - ethereum-waffle@^3.3.0, ethereum-waffle@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.0.tgz#990b3c6c26db9c2dd943bf26750a496f60c04720" @@ -8240,42 +7920,6 @@ ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2: "@ethersproject/web" "5.4.0" "@ethersproject/wordlists" "5.4.0" -ethers@^5.4.5, ethers@^5.5.2, ethers@^5.6.2, ethers@^5.6.6: - version "5.6.6" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.6.tgz#a37aa7e265a484a1b4d2ef91d4d89d6b43808a57" - integrity sha512-2B2ZmSGvRcJpHnFMBk58mkXP50njFipUBCgLK8jUTFbomhVs501cLzyMU6+Vx8YnUDQxywC3qkZvd33xWS+2FA== - dependencies: - "@ethersproject/abi" "5.6.2" - "@ethersproject/abstract-provider" "5.6.0" - "@ethersproject/abstract-signer" "5.6.1" - "@ethersproject/address" "5.6.0" - "@ethersproject/base64" "5.6.0" - "@ethersproject/basex" "5.6.0" - "@ethersproject/bignumber" "5.6.1" - "@ethersproject/bytes" "5.6.1" - "@ethersproject/constants" "5.6.0" - "@ethersproject/contracts" "5.6.1" - "@ethersproject/hash" "5.6.0" - "@ethersproject/hdnode" "5.6.1" - "@ethersproject/json-wallets" "5.6.0" - "@ethersproject/keccak256" "5.6.0" - "@ethersproject/logger" "5.6.0" - "@ethersproject/networks" "5.6.2" - "@ethersproject/pbkdf2" "5.6.0" - "@ethersproject/properties" "5.6.0" - "@ethersproject/providers" "5.6.6" - "@ethersproject/random" "5.6.0" - "@ethersproject/rlp" "5.6.0" - "@ethersproject/sha2" "5.6.0" - "@ethersproject/signing-key" "5.6.1" - "@ethersproject/solidity" "5.6.0" - "@ethersproject/strings" "5.6.0" - "@ethersproject/transactions" "5.6.0" - "@ethersproject/units" "5.6.0" - "@ethersproject/wallet" "5.6.1" - "@ethersproject/web" "5.6.0" - "@ethersproject/wordlists" "5.6.0" - ethers@^5.5.0, ethers@^5.5.4: version "5.5.4" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.4.tgz#e1155b73376a2f5da448e4a33351b57a885f4352" @@ -8312,6 +7956,42 @@ ethers@^5.5.0, ethers@^5.5.4: "@ethersproject/web" "5.5.1" "@ethersproject/wordlists" "5.5.0" +ethers@^5.6.2: + version "5.6.6" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.6.tgz#a37aa7e265a484a1b4d2ef91d4d89d6b43808a57" + integrity sha512-2B2ZmSGvRcJpHnFMBk58mkXP50njFipUBCgLK8jUTFbomhVs501cLzyMU6+Vx8YnUDQxywC3qkZvd33xWS+2FA== + dependencies: + "@ethersproject/abi" "5.6.2" + "@ethersproject/abstract-provider" "5.6.0" + "@ethersproject/abstract-signer" "5.6.1" + "@ethersproject/address" "5.6.0" + "@ethersproject/base64" "5.6.0" + "@ethersproject/basex" "5.6.0" + "@ethersproject/bignumber" "5.6.1" + "@ethersproject/bytes" "5.6.1" + "@ethersproject/constants" "5.6.0" + "@ethersproject/contracts" "5.6.1" + "@ethersproject/hash" "5.6.0" + "@ethersproject/hdnode" "5.6.1" + "@ethersproject/json-wallets" "5.6.0" + "@ethersproject/keccak256" "5.6.0" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.2" + "@ethersproject/pbkdf2" "5.6.0" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.6" + "@ethersproject/random" "5.6.0" + "@ethersproject/rlp" "5.6.0" + "@ethersproject/sha2" "5.6.0" + "@ethersproject/signing-key" "5.6.1" + "@ethersproject/solidity" "5.6.0" + "@ethersproject/strings" "5.6.0" + "@ethersproject/transactions" "5.6.0" + "@ethersproject/units" "5.6.0" + "@ethersproject/wallet" "5.6.1" + "@ethersproject/web" "5.6.0" + "@ethersproject/wordlists" "5.6.0" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -9289,18 +8969,6 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.7, glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.2.0, glob@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -9324,6 +8992,18 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-modules@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" @@ -9473,34 +9153,6 @@ hard-rejection@^2.1.0: resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== -hardhat-deploy@^0.11.4: - version "0.11.4" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.4.tgz#39b06d3b0ad25195071cc1f2f71649b1f9f030d0" - integrity sha512-BNMwWqaxrwb8XKrYzmCwnUzOSKzicUBk+fwd28doUNoAGFFh8kpoypkcHMzKDVdLhnamAardcfqJet73zrZoTA== - dependencies: - "@ethersproject/abi" "^5.4.0" - "@ethersproject/abstract-signer" "^5.4.1" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.1" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/contracts" "^5.4.1" - "@ethersproject/providers" "^5.4.4" - "@ethersproject/solidity" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/wallet" "^5.4.0" - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - hardhat-deploy@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.9.3.tgz#cf9a7806c0a86a6f7e9352fc558b26c079983496" @@ -9550,60 +9202,6 @@ hardhat-watcher@^2.1.1: dependencies: chokidar "^3.4.3" -hardhat@^2.7.1: - version "2.9.5" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.9.5.tgz#6814a9f3afd5630ffe6bcb05a4367eb259c9222a" - integrity sha512-UIhjLQmccFOH87ODfFnVatI5vpwycsJ+D5+gmgOQNxUWp4c0ZenkeCE4yDEQ0tQm/zc/vz/mpskULz4aSFsPAg== - dependencies: - "@ethereumjs/block" "^3.6.2" - "@ethereumjs/blockchain" "^5.5.2" - "@ethereumjs/common" "^2.6.4" - "@ethereumjs/tx" "^3.5.1" - "@ethereumjs/vm" "^5.9.0" - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@sentry/node" "^5.18.1" - "@solidity-parser/parser" "^0.14.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^0.1.2" - ethereumjs-abi "^0.6.8" - ethereumjs-util "^7.1.4" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "^7.1.3" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - lodash "^4.17.11" - merkle-patricia-tree "^4.2.4" - mnemonist "^0.38.0" - mocha "^9.2.0" - p-map "^4.0.0" - qs "^6.7.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - slash "^3.0.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - "true-case-path" "^2.2.1" - tsort "0.0.1" - undici "^4.14.1" - uuid "^8.3.2" - ws "^7.4.6" - hardhat@^2.9.2: version "2.9.2" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.9.2.tgz#123f3fed6810ef8637b127b73ca44bb9c9efc249" @@ -9989,11 +9587,6 @@ ignore@^5.1.1, ignore@^5.1.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== -ignore@^5.1.8: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - immediate@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" @@ -10284,13 +9877,6 @@ is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.6.0: dependencies: has "^1.0.3" -is-core-module@^2.8.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== - dependencies: - has "^1.0.3" - is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -11599,13 +11185,6 @@ loose-envify@^1.0.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== - dependencies: - get-func-name "^2.0.0" - lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -12029,18 +11608,6 @@ merkle-patricia-tree@^4.2.2, merkle-patricia-tree@^4.2.3: readable-stream "^3.6.0" semaphore-async-await "^1.5.1" -merkle-patricia-tree@^4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.4.tgz#ff988d045e2bf3dfa2239f7fabe2d59618d57413" - integrity sha512-eHbf/BG6eGNsqqfbLED9rIqbsF4+sykEaBn6OLNs71tjclbMcMOk1tEPmJKcNcNCLkvbpY/lwyOlizWsqPNo8w== - dependencies: - "@types/levelup" "^4.3.0" - ethereumjs-util "^7.1.4" - level-mem "^5.0.1" - level-ws "^2.0.0" - readable-stream "^3.6.0" - semaphore-async-await "^1.5.1" - merkletreejs@^0.2.18: version "0.2.24" resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.2.24.tgz#6dc52b3e0946846c25816216f1b60094a18a5e7a" @@ -12643,7 +12210,7 @@ node-environment-flags@1.0.6: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -13566,7 +13133,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6, path-parse@^1.0.7: +path-parse@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -13839,18 +13406,6 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier-plugin-solidity@^1.0.0-beta.13: - version "1.0.0-beta.19" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz#7c3607fc4028f5e6a425259ff03e45eedf733df3" - integrity sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g== - dependencies: - "@solidity-parser/parser" "^0.14.0" - emoji-regex "^10.0.0" - escape-string-regexp "^4.0.0" - semver "^7.3.5" - solidity-comments-extractor "^0.0.7" - string-width "^4.2.3" - prettier-plugin-solidity@^1.0.0-beta.18: version "1.0.0-beta.18" resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.18.tgz#9705453bacd55b3242110d472f23f624ae6777fc" @@ -13873,11 +13428,6 @@ prettier@^2.1.2, prettier@^2.3.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== -prettier@^2.3.2, prettier@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== - printj@~1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" @@ -14493,7 +14043,7 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpp@^3.0.0, regexpp@^3.1.0: +regexpp@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -14725,15 +14275,6 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.20.0, resolve@^1.8. is-core-module "^2.2.0" path-parse "^1.0.6" -resolve@^1.10.1: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== - dependencies: - is-core-module "^2.8.1" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - resolve@^2.0.0-next.3: version "2.0.0-next.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" @@ -14992,7 +14533,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -15400,30 +14941,6 @@ solidity-comments-extractor@^0.0.7: resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== -solidity-coverage@^0.7.16: - version "0.7.21" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.21.tgz#20c5615a3a543086b243c2ca36e2951a75316b40" - integrity sha512-O8nuzJ9yXiKUx3NdzVvHrUW0DxoNVcGzq/I7NzewNO9EZE3wYAQ4l8BwcnV64r4aC/HB6Vnw/q2sF0BQHv/3fg== - dependencies: - "@solidity-parser/parser" "^0.14.0" - "@truffle/provider" "^0.2.24" - chalk "^2.4.2" - death "^1.1.0" - detect-port "^1.3.0" - fs-extra "^8.1.0" - ghost-testrpc "^0.0.2" - global-modules "^2.0.0" - globby "^10.0.1" - jsonschema "^1.2.4" - lodash "^4.17.15" - node-emoji "^1.10.0" - pify "^4.0.1" - recursive-readdir "^2.2.2" - sc-istanbul "^0.4.5" - semver "^7.3.4" - shelljs "^0.8.3" - web3-utils "^1.3.0" - solidity-coverage@^0.7.17: version "0.7.17" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.17.tgz#5139de8f6666d4755d88f453d8e35632a7bb3444" @@ -15748,7 +15265,7 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string-width@^4.2.2, string-width@^4.2.3: +string-width@^4.2.2: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15999,11 +15516,6 @@ supports-hyperlinks@^1.0.1: has-flag "^2.0.0" supports-color "^5.0.0" -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - swarm-js@^0.1.40: version "0.1.40" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" @@ -16519,7 +16031,7 @@ ts-node@^10.0.0: make-error "^1.1.1" yn "3.1.1" -ts-node@^10.1.0, ts-node@^10.7.0: +ts-node@^10.7.0: version "10.7.0" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== @@ -16709,13 +16221,12 @@ typechain@^3.0.0: ts-essentials "^6.0.3" ts-generator "^0.1.1" -typechain@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-5.2.0.tgz#10525a44773a34547eb2eed8978cb72c0a39a0f4" - integrity sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw== +typechain@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-6.1.0.tgz#462a35f555accf870689d1ba5698749108d0ce81" + integrity sha512-GGfkK0p3fUgz8kYxjSS4nKcWXE0Lo+teHTetghousIK5njbNoYNDlwn91QIyD181L3fVqlTvBE0a/q3AZmjNfw== dependencies: "@types/prettier" "^2.1.1" - command-line-args "^4.0.7" debug "^4.1.1" fs-extra "^7.0.0" glob "^7.1.6" @@ -16723,21 +16234,6 @@ typechain@^5.1.2: lodash "^4.17.15" mkdirp "^1.0.4" prettier "^2.1.2" - ts-essentials "^7.0.1" - -typechain@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.0.0.tgz#a5dbe754717a7e16247df52b5285903de600e8ff" - integrity sha512-rqDfDYc9voVAhmfVfAwzg3VYFvhvs5ck1X9T/iWkX745Cul4t+V/smjnyqrbDzWDbzD93xfld1epg7Y/uFAesQ== - dependencies: - "@types/prettier" "^2.1.1" - debug "^4.3.1" - fs-extra "^7.0.0" - glob "7.1.7" - js-sha3 "^0.8.0" - lodash "^4.17.15" - mkdirp "^1.0.4" - prettier "^2.3.1" ts-command-line-args "^2.2.0" ts-essentials "^7.0.1" @@ -16769,7 +16265,7 @@ typescript@^4.3.4, typescript@^4.3.5, typescript@^4.6.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== -typescript@^4.5.2, typescript@^4.6.3, typescript@^4.6.4: +typescript@^4.6.3: version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==